/**
  * Try to load a config XML file from a named path. If the file does not exist, return
  * NONEXISTENT; or if there is any load error, return null.
  */
 private Document loadXml(String path) {
   assert ProjectManager.mutex().isReadAccess() || ProjectManager.mutex().isWriteAccess();
   assert Thread.holdsLock(modifiedMetadataPaths);
   FileObject xml = dir.getFileObject(path);
   if (xml == null || !xml.isData()) {
     return NONEXISTENT;
   }
   try {
     Document doc =
         XMLUtil.parse(
             new InputSource(xml.getInputStream()),
             false,
             true,
             XMLUtil.defaultErrorHandler(),
             null);
     return doc;
   } catch (IOException e) {
     if (!QUIETLY_SWALLOW_XML_LOAD_ERRORS) {
       LOG.log(Level.INFO, "Load XML: {0}", xml.getPath()); // NOI18N
       ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
     }
   } catch (SAXException e) {
     if (!QUIETLY_SWALLOW_XML_LOAD_ERRORS) {
       LOG.log(Level.INFO, "Load XML: {0}", xml.getPath()); // NOI18N
       ErrorManager.getDefault().notify(ErrorManager.INFORMATIONAL, e);
     }
   }
   return null;
 }
  public static DotClassPath parse(File dotClasspath, List<Link> links) throws IOException {
    Document dotClasspathXml;
    try {
      dotClasspathXml =
          XMLUtil.parse(
              new InputSource(Utilities.toURI(dotClasspath).toString()),
              false,
              true,
              XMLUtil.defaultErrorHandler(),
              null);
    } catch (SAXException e) {
      IOException ioe =
          (IOException) new IOException(dotClasspath + ": " + e.toString()).initCause(e); // NOI18N
      throw ioe;
    }
    Element classpathEl = dotClasspathXml.getDocumentElement();
    if (!"classpath".equals(classpathEl.getLocalName())) { // NOI18N
      return empty();
    }
    List<Element> classpathEntryEls;
    try {
      classpathEntryEls = XMLUtil.findSubElements(classpathEl);
    } catch (IllegalArgumentException x) {
      throw new IOException(x);
    }
    if (classpathEntryEls == null) {
      return empty();
    }

    // accessrules are ignored as they are not supported in NB anyway, eg:
    /*
    <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER">
        <accessrules>
            <accessrule kind="accessible" pattern="com/sun/management/*"/>
            <accessrule kind="nonaccessible" pattern="com/sun/**"/>
        </accessrules>
    </classpathentry>
     */

    List<DotClassPathEntry> classpath = new ArrayList<DotClassPathEntry>();
    List<DotClassPathEntry> sources = new ArrayList<DotClassPathEntry>();
    DotClassPathEntry output = null;
    DotClassPathEntry jre = null;
    for (Element classpathEntry : classpathEntryEls) {
      Map<String, String> props = new HashMap<String, String>();
      NamedNodeMap attrs = classpathEntry.getAttributes();
      String linkName = null;
      for (int i = 0; i < attrs.getLength(); i++) {
        Node n = attrs.item(i);
        String key = n.getNodeName();
        String value = classpathEntry.getAttribute(n.getNodeName());
        if (DotClassPathEntry.ATTRIBUTE_PATH.equals(key)) {
          String resolvedLink = resolveLink(value, links);
          if (resolvedLink != null) {
            linkName = value;
            value = resolvedLink;
          }
        }
        props.put(key, value);
      }
      Element entryAttrs = XMLUtil.findElement(classpathEntry, "attributes", null); // NOI18N
      if (entryAttrs != null) {
        /*
        <classpathentry kind="lib" path="/home/dev/hibernate-annotations-3.3.1.GA/lib/hibernate-commons-annotations.jar" sourcepath="/home/dev/hibernate-annotations-3.3.1.GA/src">
            <attributes>
                <attribute name="javadoc_location" value="file:/home/dev/hibernate-annotations-3.3.1.GA/doc/api/"/>
            </attributes>
        </classpathentry>
         */
        List<Element> attrsList = XMLUtil.findSubElements(entryAttrs);
        if (attrsList != null) {
          for (Element e : attrsList) {
            props.put(e.getAttribute("name"), e.getAttribute("value")); // NOI18N
          }
        }
      }
      DotClassPathEntry entry = new DotClassPathEntry(props, linkName);
      if (entry.getKind() == DotClassPathEntry.Kind.SOURCE) {
        sources.add(entry);
      } else if (entry.getKind() == DotClassPathEntry.Kind.OUTPUT) {
        assert output == null : "there should be always just one default output"; // NOI18N
        output = entry;
      } else if (entry.getKind() == DotClassPathEntry.Kind.CONTAINER
          && entry.getRawPath().startsWith(Workspace.DEFAULT_JRE_CONTAINER)) {
        jre = entry;
      } else {
        classpath.add(entry);
      }
    }
    return new DotClassPath(classpath, sources, output, jre);
  }