/** @see IJavaElementRequestor */
  public void acceptType(IType type) {
    try {
      if (this.unitToSkip != null && this.unitToSkip.equals(type.getCompilationUnit())) {
        return;
      }
      char[] packageName = type.getPackageFragment().getElementName().toCharArray();
      boolean isBinary = type instanceof BinaryType;

      // determine associated access restriction
      AccessRestriction accessRestriction = null;

      if (this.checkAccessRestrictions
          && (isBinary || !type.getJavaProject().equals(this.project))) {
        PackageFragmentRoot root =
            (PackageFragmentRoot) type.getAncestor(IJavaElement.PACKAGE_FRAGMENT_ROOT);
        ClasspathEntry entry = (ClasspathEntry) this.nameLookup.rootToResolvedEntries.get(root);
        if (entry != null) { // reverse map always contains resolved CP entry
          AccessRuleSet accessRuleSet = entry.getAccessRuleSet();
          if (accessRuleSet != null) {
            // TODO (philippe) improve char[] <-> String conversions to avoid performing them on the
            // fly
            char[][] packageChars = CharOperation.splitOn('.', packageName);
            char[] fileWithoutExtension = type.getElementName().toCharArray();
            accessRestriction =
                accessRuleSet.getViolatedRestriction(
                    CharOperation.concatWith(packageChars, fileWithoutExtension, '/'));
          }
        }
      }
      this.requestor.acceptType(
          packageName,
          type.getElementName().toCharArray(),
          null,
          type.getFlags(),
          accessRestriction);
    } catch (JavaModelException jme) {
      // ignore
    }
  }
  /* package */ String serialize() throws IOException {
    ByteArrayOutputStream s = new ByteArrayOutputStream();
    OutputStreamWriter writer = new OutputStreamWriter(s, "UTF8"); // $NON-NLS-1$
    XMLWriter xmlWriter =
        new XMLWriter(
            writer, null /*use the workspace line delimiter*/, true /*print XML version*/);

    HashMap library = new HashMap();
    library.put(TAG_VERSION, String.valueOf(CURRENT_VERSION));
    library.put(TAG_SYSTEMLIBRARY, String.valueOf(this.isSystemLibrary));
    xmlWriter.printTag(TAG_USERLIBRARY, library, true, true, false);

    for (int i = 0; i < this.entries.length; ++i) {
      ClasspathEntry cpEntry = (ClasspathEntry) this.entries[i];

      HashMap archive = new HashMap();
      archive.put(TAG_PATH, cpEntry.getPath().toString());
      IPath sourceAttach = cpEntry.getSourceAttachmentPath();
      if (sourceAttach != null) archive.put(TAG_SOURCEATTACHMENT, sourceAttach);
      IPath sourceAttachRoot = cpEntry.getSourceAttachmentRootPath();
      if (sourceAttachRoot != null) archive.put(TAG_SOURCEATTACHMENTROOT, sourceAttachRoot);

      boolean hasExtraAttributes =
          cpEntry.extraAttributes != null && cpEntry.extraAttributes.length != 0;
      boolean hasRestrictions =
          cpEntry.getAccessRuleSet() != null; // access rule set is null if no access rules
      xmlWriter.printTag(
          TAG_ARCHIVE, archive, true, true, !(hasExtraAttributes || hasRestrictions));

      // write extra attributes if necessary
      if (hasExtraAttributes) {
        cpEntry.encodeExtraAttributes(xmlWriter, true, true);
      }

      // write extra attributes and restriction if necessary
      if (hasRestrictions) {
        cpEntry.encodeAccessRules(xmlWriter, true, true);
      }

      // write archive end tag if necessary
      if (hasExtraAttributes || hasRestrictions) {
        xmlWriter.endTag(TAG_ARCHIVE, true /*insert tab*/, true /*insert new line*/);
      }
    }
    xmlWriter.endTag(TAG_USERLIBRARY, true /*insert tab*/, true /*insert new line*/);
    writer.flush();
    writer.close();
    return s.toString("UTF8"); // $NON-NLS-1$
  }
 public void addClasspath(File path, boolean wildcard) {
   ClasspathEntry entry = new ClasspathEntry();
   entry.path = path;
   entry.wildcard = wildcard;
   classpath.add(entry);
 }
 /**
  * Returns a Java model status describing the problem related to this classpath entry if any, a
  * status object with code <code>IStatus.OK</code> if the entry is fine (that is, if the given
  * classpath entry denotes a valid element to be referenced onto a classpath).
  *
  * @param project the given java project
  * @param entry the given classpath entry
  * @param checkSourceAttachment a flag to determine if source attachment should be checked
  * @return a java model status describing the problem related to this classpath entry if any, a
  *     status object with code <code>IStatus.OK</code> if the entry is fine
  * @since 2.0
  */
 public static IJavaModelStatus validateClasspathEntry(
     IJavaProject project, IClasspathEntry entry, boolean checkSourceAttachment) {
   return ClasspathEntry.validateClasspathEntry(
       project, entry, checkSourceAttachment, false /*not referred by container*/);
 }
  /**
   * Validate a given classpath and output location for a project, using the following rules:
   *
   * <ul>
   *   <li>Classpath entries cannot collide with each other; that is, all entry paths must be
   *       unique.
   *   <li>The project output location path cannot be null, must be absolute and located inside the
   *       project.
   *   <li>Specific output locations (specified on source entries) can be null, if not they must be
   *       located inside the project,
   *   <li>A project entry cannot refer to itself directly (that is, a project cannot prerequisite
   *       itself).
   *   <li>Classpath entries or output locations cannot coincide or be nested in each other, except
   *       for the following scenarios listed below:
   *       <ul>
   *         <li>A source folder can coincide with its own output location, in which case this
   *             output can then contain library archives. However, a specific output location
   *             cannot coincide with any library or a distinct source folder than the one referring
   *             to it.<br>
   *             Note: Since 3.8, this behavior can be overridden by configuring {@link
   *             JavaCore#CORE_OUTPUT_LOCATION_OVERLAPPING_ANOTHER_SOURCE}
   *         <li>A source/library folder can be nested in any source folder as long as the nested
   *             folder is excluded from the enclosing one.
   *         <li>An output location can be nested in a source folder, if the source folder coincides
   *             with the project itself, or if the output location is excluded from the source
   *             folder.
   *       </ul>
   * </ul>
   *
   * Note that the classpath entries are not validated automatically. Only bound variables or
   * containers are considered in the checking process (this allows to perform a consistency check
   * on a classpath which has references to yet non existing projects, folders, ...).
   *
   * <p>This validation is intended to anticipate classpath issues prior to assigning it to a
   * project. In particular, it will automatically be performed during the classpath setting
   * operation (if validation fails, the classpath setting will not complete).
   *
   * <p>
   *
   * @param javaProject the given java project
   * @param rawClasspath the given classpath
   * @param projectOutputLocation the given output location
   * @return a status object with code <code>IStatus.OK</code> if the given classpath and output
   *     location are compatible, otherwise a status object indicating what is wrong with the
   *     classpath or output location
   * @since 2.0
   */
  public static IJavaModelStatus validateClasspath(
      IJavaProject javaProject, IClasspathEntry[] rawClasspath, IPath projectOutputLocation) {

    return ClasspathEntry.validateClasspath(javaProject, rawClasspath, projectOutputLocation);
  }
  /* package */ static UserLibrary createFromString(Reader reader) throws IOException {
    Element cpElement;
    try {
      DocumentBuilder parser = DocumentBuilderFactory.newInstance().newDocumentBuilder();
      cpElement = parser.parse(new InputSource(reader)).getDocumentElement();
    } catch (SAXException e) {
      throw new IOException(Messages.file_badFormat);
    } catch (ParserConfigurationException e) {
      throw new IOException(Messages.file_badFormat);
    } finally {
      reader.close();
    }

    if (!cpElement.getNodeName().equalsIgnoreCase(TAG_USERLIBRARY)) {
      throw new IOException(Messages.file_badFormat);
    }
    // String version= cpElement.getAttribute(TAG_VERSION);
    // in case we update the format: add code to read older versions

    boolean isSystem = Boolean.valueOf(cpElement.getAttribute(TAG_SYSTEMLIBRARY)).booleanValue();

    NodeList list = cpElement.getChildNodes();
    int length = list.getLength();

    ArrayList res = new ArrayList(length);
    for (int i = 0; i < length; ++i) {
      Node node = list.item(i);

      if (node.getNodeType() == Node.ELEMENT_NODE) {
        Element element = (Element) node;
        if (element.getNodeName().equals(TAG_ARCHIVE)) {
          String path = element.getAttribute(TAG_PATH);
          IPath sourceAttach =
              element.hasAttribute(TAG_SOURCEATTACHMENT)
                  ? new Path(element.getAttribute(TAG_SOURCEATTACHMENT))
                  : null;
          IPath sourceAttachRoot =
              element.hasAttribute(TAG_SOURCEATTACHMENTROOT)
                  ? new Path(element.getAttribute(TAG_SOURCEATTACHMENTROOT))
                  : null;
          NodeList children = element.getElementsByTagName("*"); // $NON-NLS-1$
          boolean[] foundChildren = new boolean[children.getLength()];
          NodeList attributeList =
              ClasspathEntry.getChildAttributes(
                  ClasspathEntry.TAG_ATTRIBUTES, children, foundChildren);
          IIncludePathAttribute[] extraAttributes =
              ClasspathEntry.decodeExtraAttributes(attributeList);
          attributeList =
              ClasspathEntry.getChildAttributes(
                  ClasspathEntry.TAG_ACCESS_RULES, children, foundChildren);
          IAccessRule[] accessRules = ClasspathEntry.decodeAccessRules(attributeList);
          IIncludePathEntry entry =
              JavaScriptCore.newLibraryEntry(
                  new Path(path),
                  sourceAttach,
                  sourceAttachRoot,
                  accessRules,
                  extraAttributes,
                  false /*not exported*/);
          res.add(entry);
        }
      }
    }

    IIncludePathEntry[] entries =
        (IIncludePathEntry[]) res.toArray(new IIncludePathEntry[res.size()]);

    return new UserLibrary(entries, isSystem);
  }