/* 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$
  }
  /** @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
    }
  }