/**
   * Creates and parses a Collada root for an untyped source. The source must be either a {@link
   * File} or a {@link String} identifying either a file path or a {@link URL}. Null is returned if
   * the source type is not recognized.
   *
   * @param docSource either a {@link File} or a {@link String} identifying a file path or {@link
   *     URL}.
   * @return a new {@link ColladaRoot} for the specified source, or null if the source type is not
   *     supported.
   * @throws IllegalArgumentException if the source is null.
   * @throws IOException if an error occurs while reading the source.
   */
  public static ColladaRoot createAndParse(Object docSource)
      throws IOException, XMLStreamException {
    ColladaRoot colladaRoot = ColladaRoot.create(docSource);

    if (colladaRoot == null) {
      String message =
          Logging.getMessage(
              "generic.UnrecognizedSourceTypeOrUnavailableSource", docSource.toString());
      throw new IllegalArgumentException(message);
    }

    colladaRoot.parse();

    return colladaRoot;
  }
  /**
   * Open and parse the specified file expressed as a file: URL..
   *
   * @param url the URL of the file to open, expressed as a URL with a scheme of "file".
   * @param linkBase the original address of the document if the file is a retrieved and cached
   *     file.
   * @return A {@code ColladaRoot} representing the file's COLLADA contents.
   * @throws IOException if an I/O error occurs during opening and parsing.
   * @throws XMLStreamException if a server parsing error is encountered.
   */
  protected ColladaRoot parseCachedColladaFile(URL url, String linkBase)
      throws IOException, XMLStreamException {
    ColladaDoc colladaDoc;

    InputStream refStream = url.openStream();

    colladaDoc = new ColladaInputStream(refStream, WWIO.makeURI(linkBase));

    try {
      ColladaRoot refRoot = new ColladaRoot(colladaDoc);
      refRoot.parse(); // also closes the URL's stream
      return refRoot;
    } catch (XMLStreamException e) {
      refStream.close(); // parsing failed, so explicitly close the stream
      throw e;
    }
  }