8171243: CatalogManager.catalogResolver throws FileSystemNotFoundException with jar
authorjoehw
Wed, 11 Jan 2017 13:06:04 -0800
changeset 43121 e73af7b6ce47
parent 43040 ab2c8b03c328
child 43122 cf6fa122e5cb
8171243: CatalogManager.catalogResolver throws FileSystemNotFoundException with jar Reviewed-by: rriggs, dfuchs, lancea, alanb
jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java
jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java
jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java
jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/dummy.xml
jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java
jaxp/test/javax/xml/jaxp/libs/jaxp/library/JarUtils.java
jaxp/test/javax/xml/jaxp/libs/jaxp/library/SimpleHttpServer.java
jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogAccessTest.java
jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java
jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java
jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java
jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java
jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/MANIFEST.MF
jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/catalog/ws-addr.xsd
jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/jax-ws-catalog.xml
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/AltCatalog.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -58,7 +58,7 @@
     }
 
     /**
-     * Returns the catalog attribute as an URI String.
+     * Returns the catalog attribute as a URI String.
      * @return The value of the catalog attribute
      */
     String getCatalogId() {
@@ -66,7 +66,7 @@
     }
 
     /**
-     * Returns the catalog attribute as an URI.
+     * Returns the catalog attribute as a URI.
      * @return The value of the catalog attribute
      */
     URI getCatalogURI() {
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/BaseEntry.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,6 +27,7 @@
 import java.net.MalformedURLException;
 import java.net.URL;
 import java.util.Objects;
+import static javax.xml.catalog.CatalogMessages.ERR_INVALID_ARGUMENT;
 
 /**
  * Represents a general Catalog entry.
@@ -210,13 +211,12 @@
      * @param arg The name of the argument
      * @param uri The URI to be verified
      * @return The URI created from the specified uri
-     * @throws IllegalArgumentException if the specified uri is null,
-     * or an URL can not be created based on the specified base and uri
+     * @throws NullPointerException if the specified uri is null
+     * @throws IllegalArgumentException if a URL can not be created based on
+     * the specified base and uri
      */
     URL verifyURI(String arg, URL base, String uri) {
-        if (uri == null) {
-            CatalogMessages.reportIAE(new Object[]{uri, arg}, null);
-        }
+        CatalogMessages.reportNPEOnNull(arg, uri);
 
         URL url = null;
         uri = Normalizer.normalizeURI(uri);
@@ -228,32 +228,9 @@
                 url = new URL(uri);
             }
         } catch (MalformedURLException e) {
-            CatalogMessages.reportIAE(new Object[]{uri, arg}, e);
+            CatalogMessages.reportIAE(ERR_INVALID_ARGUMENT,
+                    new Object[]{uri, arg}, e);
         }
         return url;
     }
-
-    /**
-     * Construct an absolute URI from a relative one, using the current base
-     * URI.
-     *
-     * @param sysid The (possibly relative) system identifier
-     * @return The system identifier made absolute with respect to the current
-     * {@link #base}.
-     */
-    protected String makeAbsolute(String sysid) {
-        URL local = null;
-
-        sysid = Util.fixSlashes(sysid);
-        /**
-         * try { local = new URL(base, sysid); } catch (MalformedURLException e)
-         * { catalogManager.debug.message(1, "Malformed URL on system
-         * identifier", sysid); }
-         */
-        if (local != null) {
-            return local.toString();
-        } else {
-            return sysid;
-        }
-    }
 }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Catalog.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -44,7 +44,7 @@
  * <ul>
  * <li>Locate the external resources with a public or system identifier;
  * </li>
- * <li>Locate an alternate URI reference with an URI.
+ * <li>Locate an alternate URI reference with a URI.
  * </li>
  * </ul>
  * <p>
@@ -84,7 +84,7 @@
      *
      * @param systemId the system identifier of the entity to be matched
      *
-     * @return an URI string if a mapping is found, or null otherwise
+     * @return a URI string if a mapping is found, or null otherwise
      */
     public String matchSystem(String systemId);
 
@@ -108,7 +108,7 @@
      *
      * @param publicId the public identifier of the entity to be matched
      * @see CatalogFeatures.Feature
-     * @return an URI string if a mapping is found, or null otherwise
+     * @return a URI string if a mapping is found, or null otherwise
      */
     public String matchPublic(String publicId);
 
@@ -134,7 +134,7 @@
      *
      * @param uri the URI reference of the entity to be matched
      *
-     * @return an URI string if a mapping is found, or null otherwise
+     * @return a URI string if a mapping is found, or null otherwise
      */
     public String matchURI(String uri);
 
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogFeatures.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -56,14 +56,14 @@
  *
  * <tr>
  * <td><a name="FILES">FILES</a></td>
- * <td>A semicolon-delimited list of catalog files. Relative file paths are
- * considered relative to ${user.dir}.
+ * <td>A semicolon-delimited list of URIs to locate the catalog files.
+ * The URIs must be absolute and have a URL protocol handler for the URI scheme.
  * </td>
  * <td>javax.xml.catalog.files</td>
  * <td>javax.xml.catalog.files</td>
  * <td>javax.xml.catalog.files</td>
  * <td>String</td>
- * <td>File paths</td>
+ * <td>URIs</td>
  * <td>
  * Reads the first catalog as the current catalog; Loads others if no match
  * is found in the current catalog including delegate catalogs if any.
@@ -170,7 +170,7 @@
  * Properties set through the Catalog API override those that may have been set
  * by system properties and/or in {@code jaxp.properties}. In case of multiple
  * interfaces, the latest in a procedure shall take preference. For
- * {@link Feature#FILES}, this means that the path(s) specified through the methods
+ * {@link Feature#FILES}, this means that the URI(s) specified through the methods
  * of the {@link CatalogManager} will override any that may have been entered
  * through the {@link Builder}.
  *
@@ -188,7 +188,7 @@
  * in the following sample code:
  * <pre>{@code
                 CatalogFeatures f = CatalogFeatures.builder()
-                        .with(Feature.FILES, "catalog.xml")
+                        .with(Feature.FILES, "file:///etc/xml/catalog")
                         .with(Feature.PREFER, "public")
                         .with(Feature.DEFER, "true")
                         .with(Feature.RESOLVE, "ignore")
@@ -202,14 +202,14 @@
  * Schema Validation ({@link javax.xml.validation}), and XML Transformation
  * ({@link javax.xml.transform}). The features described above can be set through JAXP
  * factories or processors that define a setProperty or setAttribute interface.
- * For example, the following code snippet sets a path to a catalog file on a SAX
+ * For example, the following code snippet sets a URI to a catalog file on a SAX
  * parser through the {@code javax.xml.catalog.files} property:
  * <p>
  * <pre>{@code
  *      SAXParserFactory spf = SAXParserFactory.newInstance();
  *      spf.setFeature(XMLConstants.USE_CATALOG, true); [1]
  *      SAXParser parser = spf.newSAXParser();
- *      parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "catalog.xml");
+ *      parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "file:///etc/xml/catalog");
  * }</pre>
  * <p>
  * [1] Note that this statement is not required since the default value of
@@ -275,7 +275,7 @@
    The following XInclude element:
    <xi:include href="http://openjdk.java.net/xml/disclaimer.xml"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xml/disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
    or
    <uriSuffix uriSuffix="disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
@@ -291,7 +291,7 @@
     <xsd:import namespace="http://openjdk.java.net/xsd/XSDImport_person"
                 schemaLocation="http://openjdk.java.net/xsd/XSDImport_person.xsd"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsd/XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
    or
    <uriSuffix uriSuffix="XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
@@ -308,7 +308,7 @@
    The following include element:
    <xsd:include schemaLocation="http://openjdk.java.net/xsd/XSDInclude_person.xsd"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsd/XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
    or
    <uriSuffix uriSuffix="XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
@@ -323,7 +323,7 @@
    The following include element:
    <xsl:include href="http://openjdk.java.net/xsl/include.xsl"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsl/include.xsl" uri="file:///pathto/local/include.xsl"/>
    or
    <uriSuffix uriSuffix="include.xsl" uri="file:///pathto/local/include.xsl"/>
@@ -338,7 +338,7 @@
    The document in the following element:
    <xsl:variable name="dummy" select="document('http://openjdk.java.net/xsl/list.xml')"/>
 
-   can be resolved using an uri entry:
+   can be resolved using a URI entry:
    <uri name="http://openjdk.java.net/xsl/list.xml" uri="file:///pathto/local/list.xml"/>
    or
    <uriSuffix uriSuffix="list.xml" uri="file:///pathto/local/list.xml"/>
@@ -559,7 +559,7 @@
         values = new String[Feature.values().length];
         states = new State[Feature.values().length];
         for (Feature cf : Feature.values()) {
-            setProperty(cf.ordinal(), State.DEFAULT, cf.defaultValue());
+            setProperty(cf, State.DEFAULT, cf.defaultValue());
         }
         //read system properties or jaxp.properties
         readSystemProperties();
@@ -571,52 +571,27 @@
      */
     private void setProperties(Builder builder) {
         builder.values.entrySet().stream().forEach((entry) -> {
-            setProperty(entry.getKey().ordinal(), State.APIPROPERTY, entry.getValue());
+            setProperty(entry.getKey(), State.APIPROPERTY, entry.getValue());
         });
     }
     /**
-     * Sets the value of a property by its index, updates only if it shall override.
+     * Sets the value of a property, updates only if it shall override.
      *
      * @param index the index of the property
      * @param state the state of the property
      * @param value the value of the property
      * @throws IllegalArgumentException if the value is invalid
      */
-    private void setProperty(int index, State state, String value) {
+    private void setProperty(Feature feature, State state, String value) {
+        int index = feature.ordinal();
         if (value != null && value.length() != 0) {
-            if (index == Feature.PREFER.ordinal()) {
-                if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.PREFER.name()}, null);
-                }
-            } else if (index == Feature.DEFER.ordinal()) {
-                if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.DEFER.name()}, null);
-                }
-            } else if (index == Feature.RESOLVE.ordinal()) {
-                if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
-                         && !value.equals(RESOLVE_IGNORE)) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.RESOLVE.name()}, null);
-                }
-            } else if (index == Feature.FILES.ordinal()) {
-                try {
-                    String[] catalogFile = value.split(";[ ]*");
-                    for (String temp : catalogFile) {
-                        if (Util.verifyAndGetURI(temp, null) == null) {
-                            CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, null);
-                        }
-                    }
-                }catch (MalformedURLException | URISyntaxException | IllegalArgumentException ex) {
-                    CatalogMessages.reportIAE(new Object[]{value, Feature.FILES.name()}, ex);
-                }
+            if (state != State.APIPROPERTY) {
+                Util.validateFeatureInput(feature, value);
             }
             if (states[index] == null || state.compareTo(states[index]) >= 0) {
                 values[index] = value;
                 states[index] = state;
             }
-        } else {
-            if (state == State.SYSTEMPROPERTY || state == State.JAXPDOTPROPERTIES) {
-                CatalogMessages.reportIAE(new Object[]{value, Feature.values()[index].name()}, null);
-            }
         }
     }
 
@@ -639,13 +614,13 @@
         if (cf.hasSystemProperty()) {
             String value = SecuritySupport.getSystemProperty(sysPropertyName);
             if (value != null && !value.equals("")) {
-                setProperty(cf.ordinal(), State.SYSTEMPROPERTY, value);
+                setProperty(cf, State.SYSTEMPROPERTY, value);
                 return true;
             }
 
             value = SecuritySupport.readJAXPProperty(sysPropertyName);
             if (value != null && !value.equals("")) {
-                setProperty(cf.ordinal(), State.JAXPDOTPROPERTIES, value);
+                setProperty(cf, State.JAXPDOTPROPERTIES, value);
                 return true;
             }
         }
@@ -685,9 +660,7 @@
          * property
          */
         public Builder with(Feature feature, String value) {
-            if (value == null || value.length() == 0) {
-                CatalogMessages.reportIAE(new Object[]{value, feature.name()}, null);
-            }
+            Util.validateFeatureInput(feature, value);
             values.put(feature, value);
             return this;
         }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogImpl.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -75,7 +75,7 @@
 
     /*
      A list of catalog entry files from the input, excluding the current catalog.
-     Paths in the List are normalized.
+     URIs in the List are verified during input validation or property retrieval.
      */
     List<String> inputFiles;
 
@@ -86,43 +86,44 @@
     SAXParser parser;
 
     /**
-     * Construct a Catalog with specified path.
+     * Construct a Catalog with specified URI.
      *
-     * @param file The path to a catalog file.
+     * @param uris the uri(s) to one or more catalogs
      * @throws CatalogException If an error happens while parsing the specified
      * catalog file.
      */
-    public CatalogImpl(CatalogFeatures f, String... file) throws CatalogException {
-        this(null, f, file);
+    public CatalogImpl(CatalogFeatures f, URI... uris) throws CatalogException {
+        this(null, f, uris);
     }
 
     /**
-     * Construct a Catalog with specified path.
+     * Construct a Catalog with specified URI.
      *
      * @param parent The parent catalog
-     * @param file The path to a catalog file.
+     * @param uris the uri(s) to one or more catalogs
      * @throws CatalogException If an error happens while parsing the specified
      * catalog file.
      */
-    public CatalogImpl(CatalogImpl parent, CatalogFeatures f, String... file) throws CatalogException {
+    public CatalogImpl(CatalogImpl parent, CatalogFeatures f, URI... uris) throws CatalogException {
         super(CatalogEntryType.CATALOG, parent);
         if (f == null) {
             throw new NullPointerException(
                     formatMessage(CatalogMessages.ERR_NULL_ARGUMENT, new Object[]{"CatalogFeatures"}));
         }
 
-        if (file.length > 0) {
-            CatalogMessages.reportNPEOnNull("The path to the catalog file", file[0]);
-        }
-
         init(f);
 
         //Path of catalog files
-        String[] catalogFile = file;
-        if (level == 0 && file.length == 0) {
+        String[] catalogFile = null;
+        if (level == 0 && uris.length == 0) {
             String files = features.get(Feature.FILES);
             if (files != null) {
-                catalogFile = files.split(";[ ]*");
+                catalogFile = files.split(";");
+            }
+        } else {
+            catalogFile = new String[uris.length];
+            for (int i=0; i<uris.length; i++) {
+                catalogFile[i] = uris[i].toASCIIString();
             }
         }
 
@@ -134,10 +135,10 @@
             int start = 0;
             URI uri = null;
             for (String temp : catalogFile) {
-                uri = getSystemId(temp);
+                uri = URI.create(temp);
                 start++;
                 if (verifyCatalogFile(uri)) {
-                    systemId = uri.toASCIIString();
+                    systemId = temp;
                     try {
                         baseURI = new URL(systemId);
                     } catch (MalformedURLException e) {
@@ -294,29 +295,6 @@
     }
 
     /**
-     * Resolves the specified file path to an absolute systemId. If it is
-     * relative, it shall be resolved using the base or user.dir property if
-     * base is not specified.
-     *
-     * @param file The specified file path
-     * @return The systemId of the file
-     * @throws CatalogException if the specified file path can not be converted
-     * to a system id
-     */
-    private URI getSystemId(String file) {
-        URI temp = null;
-
-        try {
-            temp = Util.verifyAndGetURI(file, baseURI);
-        } catch (MalformedURLException | URISyntaxException | IllegalArgumentException e) {
-            CatalogMessages.reportRunTimeError(CatalogMessages.ERR_INVALID_PATH,
-                    new Object[]{file}, e);
-        }
-
-        return temp;
-    }
-
-    /**
      * Returns a SAXParser instance
      * @return a SAXParser instance
      * @throws CatalogException if constructing a SAXParser failed
@@ -394,7 +372,7 @@
                 //Check the input list
                 if (c == null && inputFiles != null) {
                     while (c == null && inputFilesIndex < inputFiles.size()) {
-                        c = getCatalog(getSystemId(inputFiles.get(inputFilesIndex++)));
+                        c = getCatalog(URI.create(inputFiles.get(inputFilesIndex++)));
                     }
                 }
 
@@ -436,8 +414,8 @@
 
         //loads catalogs from the input list
         if (inputFiles != null) {
-            inputFiles.stream().forEach((file) -> {
-                getCatalog(getSystemId(file));
+            inputFiles.stream().forEach((uri) -> {
+                getCatalog(URI.create(uri));
             });
         }
     }
@@ -454,12 +432,11 @@
         }
 
         CatalogImpl c = null;
-        String path = uri.toASCIIString();
 
         if (verifyCatalogFile(uri)) {
-            c = getLoadedCatalog(path);
+            c = getLoadedCatalog(uri.toASCIIString());
             if (c == null) {
-                c = new CatalogImpl(this, features, path);
+                c = new CatalogImpl(this, features, uri);
                 c.load();
             }
         }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogManager.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,6 +24,7 @@
  */
 package javax.xml.catalog;
 
+import java.net.URI;
 
 /**
  * The Catalog Manager manages the creation of XML Catalogs and Catalog Resolvers.
@@ -39,30 +40,36 @@
 
     /**
      * Creates a {@code Catalog} object using the specified feature settings and
-     * path to one or more catalog files.
+     * uri(s) to one or more catalog files.
      * <p>
-     * If {@code paths} is empty, system property {@code javax.xml.catalog.files}
-     * will be read to locate the initial list of catalog files.
+     * If {@code uris} is empty, system property {@code javax.xml.catalog.files},
+     * as defined in {@link CatalogFeatures}, will be read to locate the initial
+     * list of catalog files.
      * <p>
-     * If more than one catalog files are specified through the paths argument or
+     * If multiple catalog files are specified through the {@code uris} argument or
      * {@code javax.xml.catalog.files} property, the first entry is considered
      * the main catalog, while others are treated as alternative catalogs after
      * those referenced by the {@code nextCatalog} elements in the main catalog.
      * <p>
      * As specified in
      * <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html#s.res.fail">
-     * XML Catalogs, OASIS Standard V1.1</a>, invalid path entries will be ignored.
-     * No error will be reported. In case all entries are invalid, the resolver
-     * will return as no mapping is found.
+     * XML Catalogs, OASIS Standard V1.1</a>, if a catalog entry is invalid, it
+     * is ignored. In case all entries are invalid, the resulting Catalog object
+     * will contain no Catalog elements. Any matching operation using the Catalog
+     * will return null.
      *
      * @param features the catalog features
-     * @param paths path(s) to one or more catalogs.
+     * @param uris uri(s) to one or more catalogs.
      *
      * @return an instance of a {@code Catalog}
+     * @throws IllegalArgumentException if either the URIs are not absolute
+     * or do not have a URL protocol handler for the URI scheme
      * @throws CatalogException If an error occurs while parsing the catalog
+     * @throws SecurityException if access to the resource is denied by the security manager
      */
-    public static Catalog catalog(CatalogFeatures features, String... paths) {
-        CatalogImpl catalog = new CatalogImpl(features, paths);
+    public static Catalog catalog(CatalogFeatures features, URI... uris) {
+        Util.validateUrisSyntax(uris);
+        CatalogImpl catalog = new CatalogImpl(features, uris);
         catalog.load();
         return catalog;
     }
@@ -80,30 +87,36 @@
 
     /**
      * Creates an instance of a {@code CatalogResolver} using the specified feature
-     * settings and path to one or more catalog files.
+     * settings and uri(s) to one or more catalog files.
      * <p>
-     * If {@code paths} is empty, system property {@code javax.xml.catalog.files}
-     * will be read to locate the initial list of catalog files.
+     * If {@code uris} is empty, system property {@code javax.xml.catalog.files},
+     * as defined in {@link CatalogFeatures}, will be read to locate the initial
+     * list of catalog files.
      * <p>
-     * If more than one catalog files are specified through the paths argument or
+     * If multiple catalog files are specified through the {@code uris} argument or
      * {@code javax.xml.catalog.files} property, the first entry is considered
      * the main catalog, while others are treated as alternative catalogs after
      * those referenced by the {@code nextCatalog} elements in the main catalog.
      * <p>
      * As specified in
      * <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html#s.res.fail">
-     * XML Catalogs, OASIS Standard V1.1</a>, invalid path entries will be ignored.
-     * No error will be reported. In case all entries are invalid, the resolver
-     * will return as no mapping is found.
+     * XML Catalogs, OASIS Standard V1.1</a>, if a catalog entry is invalid, it
+     * is ignored. In case all entries are invalid, the resulting CatalogResolver
+     * object will contain no valid catalog. Any resolution operation using the
+     * resolver therefore will return as no mapping is found. See {@link CatalogResolver}
+     * for the behavior when no mapping is found.
      *
      * @param features the catalog features
-     * @param paths the path(s) to one or more catalogs
+     * @param uris the uri(s) to one or more catalogs
      *
      * @return an instance of a {@code CatalogResolver}
+     * @throws IllegalArgumentException if either the URIs are not absolute
+     * or do not have a URL protocol handler for the URI scheme
      * @throws CatalogException If an error occurs while parsing the catalog
+     * @throws SecurityException if access to the resource is denied by the security manager
      */
-    public static CatalogResolver catalogResolver(CatalogFeatures features, String... paths) {
-        Catalog catalog = catalog(features, paths);
+    public static CatalogResolver catalogResolver(CatalogFeatures features, URI... uris) {
+        Catalog catalog = catalog(features, uris);
         return new CatalogResolverImpl(catalog);
     }
 }
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -24,10 +24,11 @@
  */
 package javax.xml.catalog;
 
-import jdk.xml.internal.SecuritySupport;
+import java.net.URI;
 import java.util.Locale;
 import java.util.MissingResourceException;
 import java.util.ResourceBundle;
+import jdk.xml.internal.SecuritySupport;
 
 /**
  * Catalog Error messages
@@ -38,6 +39,8 @@
 
     public static final String ERR_INVALID_CATALOG = "InvalidCatalog";
     public static final String ERR_INVALID_ENTRY_TYPE = "InvalidEntryType";
+    public static final String ERR_URI_NOTABSOLUTE = "UriNotAbsolute";
+    public static final String ERR_URI_NOTVALIDURL = "UriNotValidUrl";
     public static final String ERR_INVALID_ARGUMENT = "InvalidArgument";
     public static final String ERR_NULL_ARGUMENT = "NullArgument";
     public static final String ERR_CIRCULAR_REFERENCE = "CircularReference";
@@ -120,7 +123,7 @@
      * @param name the name of the argument
      * @param value the value of the argument
      */
-    static void reportNPEOnNull(String name, String value) {
+    static void reportNPEOnNull(String name, Object value) {
         if (value == null) {
             throw new NullPointerException(
                     formatMessage(ERR_NULL_ARGUMENT, new Object[]{name}));
@@ -132,9 +135,9 @@
      * @param arguments the arguments for formating the error message
      * @param cause the cause if any
      */
-    static void reportIAE(Object[] arguments, Throwable cause) {
+    static void reportIAE(String key, Object[] arguments, Throwable cause) {
         throw new IllegalArgumentException(
-                formatMessage(ERR_INVALID_ARGUMENT, arguments), cause);
+                formatMessage(key, arguments), cause);
     }
 
     /**
@@ -174,7 +177,7 @@
 
     /**
      * Returns sanitized URI.
-     * @param uri an URI to be sanitized
+     * @param uri a URI to be sanitized
      */
     static String sanitize(String uri) {
         if (uri == null) {
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogMessages.properties	Wed Jan 11 13:06:04 2017 -0800
@@ -31,6 +31,8 @@
 CircularReference = Circular reference is not allowed: ''{0}''.
 
 #errors
+UriNotAbsolute = The specified URI ''{0}'' is not absolute.
+UriNotValidUrl = The specified URI ''{0}'' is not a valid URL.
 InvalidArgument = The specified argument ''{0}'' (case sensitive) for ''{1}'' is not valid.
 NullArgument = The argument ''{0}'' can not be null.
 InvalidPath = The path ''{0}'' is invalid.
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogReader.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,10 +25,6 @@
 package javax.xml.catalog;
 
 import java.io.StringReader;
-import java.net.URI;
-import java.net.URISyntaxException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import javax.xml.catalog.BaseEntry.CatalogEntryType;
 import javax.xml.parsers.SAXParser;
 import javax.xml.transform.Source;
@@ -94,25 +90,6 @@
         this.parser = parser;
     }
 
-    /**
-     * Returns when the specified path is valid.
-     * @param path a path
-     * @return true if the path is valid, false otherwise
-     */
-    boolean isValidPath(String path) {
-        boolean valid = true;
-        try {
-            Path p = Paths.get(new URI(path));
-            if (!p.toFile().exists()) {
-                valid = false;
-            }
-        } catch (URISyntaxException ex) {
-            valid = false;
-        }
-
-        return valid;
-    }
-
     @Override
     public void startElement(String namespaceURI,
             String localName,
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolver.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -47,7 +47,7 @@
  * {@link javax.xml.stream.XMLResolver} and {@link org.w3c.dom.ls.LSResourceResolver}
  * however, make no such distinction.
  * In consistent with the existing Java API, this CatalogResolver recognizes a
- * system identifier as an URI and will search both {@code system} and {@code uri}
+ * system identifier as a URI and will search both {@code system} and {@code uri}
  * entries in a catalog in order to find a matching entry.
  * <p>
  * The search is started in the current catalog. If a match is found,
@@ -137,9 +137,9 @@
      * with the specified {@code href} attribute. The {@code href} attribute will
      * be used literally, with no attempt to be made absolute to the {@code base}.
      * <p>
-     * If the value is an URN, the {@code href} attribute is recognized as a
+     * If the value is a URN, the {@code href} attribute is recognized as a
      * {@code publicId}, and used to search {@code public} entries.
-     * If the value is an URI, it is taken as a {@code systemId}, and used to
+     * If the value is a URI, it is taken as a {@code systemId}, and used to
      * search both {@code system} and {@code uri} entries.
      *
      *
@@ -219,7 +219,7 @@
      * @param publicId  the public identifier of the external entity being
      *   referenced, or {@code null} if no public identifier was
      *   supplied or if the resource is not an entity.
-     * @param systemId  the system identifier, an URI reference of the
+     * @param systemId  the system identifier, a URI reference of the
      *   external resource being referenced
      * @param baseUri  the absolute base URI, not used by the CatalogResolver
      *
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/CatalogResolverImpl.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -73,7 +73,7 @@
         systemId = Normalizer.normalizeURI(Util.getNotNullOrEmpty(systemId));
         publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(Util.getNotNullOrEmpty(publicId)));
 
-        //check whether systemId is an urn
+        //check whether systemId is a urn
         if (systemId != null && systemId.startsWith(Util.URN)) {
             systemId = Normalizer.decodeURN(systemId);
             if (publicId != null && !publicId.equals(systemId)) {
@@ -123,7 +123,7 @@
             return null;
         }
 
-        //check whether uri is an urn
+        //check whether uri is a urn
         if (uri != null && uri.startsWith(Util.URN)) {
             String publicId = Normalizer.decodeURN(uri);
             if (publicId != null) {
@@ -131,7 +131,7 @@
             }
         }
 
-        //if no match with a public id, continue search for an URI
+        //if no match with a public id, continue search for a URI
         if (result == null) {
             //remove fragment if any.
             int hashPos = uri.indexOf("#");
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/GroupEntry.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,8 +25,6 @@
 package javax.xml.catalog;
 
 import java.net.URI;
-import java.nio.file.Files;
-import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -217,7 +215,7 @@
      * @param systemId The system identifier of the external entity being
      * referenced.
      *
-     * @return An URI string if a mapping is found, or null otherwise.
+     * @return a URI string if a mapping is found, or null otherwise.
      */
     public String matchSystem(String systemId) {
         systemEntrySearched = true;
@@ -285,7 +283,7 @@
      * @param publicId The public identifier of the external entity being
      * referenced.
      *
-     * @return An URI string if a mapping is found, or null otherwise.
+     * @return a URI string if a mapping is found, or null otherwise.
      */
     public String matchPublic(String publicId) {
         /*
@@ -329,7 +327,7 @@
      *
      * @param uri The URI reference of a resource.
      *
-     * @return An URI string if a mapping is found, or null otherwise.
+     * @return a URI string if a mapping is found, or null otherwise.
      */
     public String matchURI(String uri) {
         String match = null;
@@ -455,7 +453,7 @@
             delegateCatalog = getLoadedCatalog(catalogId);
             if (delegateCatalog == null) {
                 if (verifyCatalogFile(catalogURI)) {
-                    delegateCatalog = new CatalogImpl(catalog, features, catalogId);
+                    delegateCatalog = new CatalogImpl(catalog, features, catalogURI);
                     delegateCatalog.load();
                     delegateCatalogs.put(catalogId, delegateCatalog);
                 }
@@ -504,7 +502,8 @@
         }
 
         //Ignore it if it doesn't exist
-        if (!Files.exists(Paths.get(catalogURI))) {
+        if (Util.isFileUri(catalogURI) &&
+                !Util.isFileUriExist(catalogURI, false)) {
             return false;
         }
 
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/UriEntry.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -27,7 +27,7 @@
 import java.net.URL;
 
 /**
- * Represents an uriEntry entry.
+ * Represents a uri entry.
  *
  * @since 9
  */
@@ -36,7 +36,7 @@
     URL uri;
 
     /**
-     * Construct a group entry.
+     * Construct a uri entry.
      * @param name The name attribute.
      * @param uri The uri attribute.
      */
--- a/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/src/java.xml/share/classes/javax/xml/catalog/Util.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,13 +25,20 @@
 package javax.xml.catalog;
 
 import java.io.File;
+import java.io.IOException;
 import java.net.MalformedURLException;
 import java.net.URI;
-import java.net.URISyntaxException;
-import java.net.URL;
-import java.nio.file.Path;
-import java.nio.file.Paths;
 import java.util.Iterator;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import static javax.xml.catalog.CatalogFeatures.DEFER_FALSE;
+import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
+import javax.xml.catalog.CatalogFeatures.Feature;
+import static javax.xml.catalog.CatalogFeatures.PREFER_PUBLIC;
+import static javax.xml.catalog.CatalogFeatures.PREFER_SYSTEM;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_CONTINUE;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_IGNORE;
+import static javax.xml.catalog.CatalogFeatures.RESOLVE_STRICT;
 import jdk.xml.internal.SecuritySupport;
 
 /**
@@ -39,22 +46,25 @@
  * @since 9
  */
 class Util {
+
     final static String URN = "urn:publicid:";
     final static String PUBLICID_PREFIX = "-//";
     final static String PUBLICID_PREFIX_ALT = "+//";
+    final static String SCHEME_FILE = "file";
+    final static String SCHEME_JAR = "jar";
+    final static String SCHEME_JARFILE = "jar:file:";
 
     /**
      * Finds an entry in the catalog that matches with the publicId or systemId.
      *
-     * The resolution follows the following rules determined by the prefer setting:
+     * The resolution follows the following rules determined by the prefer
+     * setting:
      *
-     * prefer "system": attempts to resolve with a system entry;
-     *                  attempts to resolve with a public entry when only
-     *                  publicId is specified.
+     * prefer "system": attempts to resolve with a system entry; attempts to
+     * resolve with a public entry when only publicId is specified.
      *
-     * prefer "public": attempts to resolve with a system entry;
-     *                  attempts to resolve with a public entry if no matching
-     *                  system entry is found.
+     * prefer "public": attempts to resolve with a system entry; attempts to
+     * resolve with a public entry if no matching system entry is found.
      *
      * If no match is found, continue searching uri entries
      *
@@ -70,9 +80,9 @@
         catalog.reset();
         if (systemId != null) {
             /*
-               If a system identifier is specified, it is used no matter how
-            prefer is set.
-            */
+             If a system identifier is specified, it is used no matter how
+             prefer is set.
+             */
             resolvedSystemId = catalog.matchSystem(systemId);
         }
 
@@ -91,7 +101,7 @@
         if (resolvedSystemId == null) {
             Iterator<Catalog> iter = catalog.catalogs().iterator();
             while (iter.hasNext()) {
-                resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
+                resolvedSystemId = resolve((CatalogImpl) iter.next(), publicId, systemId);
                 if (resolvedSystemId != null) {
                     break;
                 }
@@ -102,73 +112,112 @@
         return resolvedSystemId;
     }
 
+    static void validateUrisSyntax(URI... uris) {
+        for (URI uri : uris) {
+            validateUriSyntax(uri);
+        }
+    }
+
+    static void validateUrisSyntax(String... uris) {
+        for (String uri : uris) {
+            validateUriSyntax(URI.create(uri));
+        }
+    }
+
     /**
-     * Resolves the specified file path to an absolute systemId. If it is
-     * relative, it shall be resolved using the base or user.dir property if
-     * base is not specified.
+     * Validate that the URI must be absolute and a valid URL.
      *
-     * @param file The specified file path
-     * @param baseURI the base URI
-     * @return The URI
-     * @throws CatalogException if the specified file path can not be converted
-     * to a system id
+     * Note that this method does not verify the existence of the resource. The
+     * Catalog standard requires that such resources be ignored.
+     *
+     * @param uri
+     * @throws IllegalArgumentException if the uri is not absolute and a valid
+     * URL
      */
-    static URI verifyAndGetURI(String file, URL baseURI)
-            throws MalformedURLException, URISyntaxException, IllegalArgumentException {
-        URL filepath;
-        URI temp;
-        if (file != null && file.length() > 0) {
-            File f = new File(file);
+    static void validateUriSyntax(URI uri) {
+        CatalogMessages.reportNPEOnNull("URI input", uri);
+
+        if (!uri.isAbsolute()) {
+            CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTABSOLUTE,
+                    new Object[]{uri}, null);
+        }
 
-            if (baseURI != null && !f.isAbsolute()) {
-                filepath = new URL(baseURI, fixSlashes(file));
-                temp = filepath.toURI();
-            } else {
-                temp = resolveURI(file);
-            }
-            //Paths.get may throw IllegalArgumentException
-            Path path = Paths.get(temp);
-            if (path.toFile().isFile()) {
-                return temp;
+        try {
+            // check if the scheme was valid
+            uri.toURL();
+        } catch (MalformedURLException ex) {
+            CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
+                    new Object[]{uri}, null);
+        }
+
+        // verify the resource exists where possible
+        if (isFileUri(uri)) {
+            if (!isFileUriExist(uri, false)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_URI_NOTVALIDURL,
+                        new Object[]{uri}, null);
             }
         }
-        return null;
     }
 
     /**
-     * Resolves the specified uri. If the uri is relative, makes it absolute by
-     * the user.dir directory.
+     * Checks whether the URI is a file URI, including JAR file.
      *
-     * @param uri The specified URI.
-     * @return The resolved URI
+     * @param uri the specified URI.
+     * @return true if it is a file or JAR file URI, false otherwise
      */
-    static URI resolveURI(String uri) throws MalformedURLException {
-        if (uri == null) {
-            uri = "";
+    static boolean isFileUri(URI uri) {
+        if (SCHEME_FILE.equals(uri.getScheme())
+                || SCHEME_JAR.equals(uri.getScheme())) {
+            return true;
         }
-
-        URI temp = null;
-        try {
-            URL url = new URL(uri);
-            temp = url.toURI();
-        } catch (MalformedURLException | URISyntaxException mue) {
-            File file = new File(uri);
-            temp = file.toURI();
-        }
-
-        return temp;
+        return false;
     }
 
     /**
-     * Replace backslashes with forward slashes. (URLs always use forward
-     * slashes.)
+     * Verifies whether the file resource exists.
      *
-     * @param sysid The input system identifier.
-     * @return The same system identifier with backslashes turned into forward
-     * slashes.
+     * @param uri the URI to locate the resource
+     * @param openJarFile a flag to indicate whether a JAR file should be
+     * opened. This operation may be expensive.
+     * @return true if the resource exists, false otherwise.
      */
-    static String fixSlashes(String sysid) {
-        return sysid.replace('\\', '/');
+    static boolean isFileUriExist(URI uri, boolean openJarFile) {
+        if (uri != null && uri.isAbsolute()) {
+            if (null != uri.getScheme()) {
+                switch (uri.getScheme()) {
+                    case SCHEME_FILE:
+                        String path = uri.getPath();
+                        File f1 = new File(path);
+                        if (f1.isFile()) {
+                            return true;
+                        }
+                        break;
+                    case SCHEME_JAR:
+                        String tempUri = uri.toString();
+                        int pos = tempUri.indexOf("!");
+                        if (pos < 0) {
+                            return false;
+                        }
+                        if (openJarFile) {
+                            String jarFile = tempUri.substring(SCHEME_JARFILE.length(), pos);
+                            String entryName = tempUri.substring(pos + 2);
+                            try {
+                                JarFile jf = new JarFile(jarFile);
+                                JarEntry je = jf.getJarEntry(entryName);
+                                if (je != null) {
+                                    return true;
+                                }
+                            } catch (IOException ex) {
+                                return false;
+                            }
+                        } else {
+                            return true;
+                        }
+                        break;
+                }
+            }
+        }
+        return false;
     }
 
     /**
@@ -187,11 +236,12 @@
     }
 
     /**
-     * Checks whether the specified string is null or empty, returns the original
-     * string with leading and trailing spaces removed if not.
+     * Checks whether the specified string is null or empty, returns the
+     * original string with leading and trailing spaces removed if not.
+     *
      * @param test the string to be tested
-     * @return the original string with leading and trailing spaces removed,
-     * or null if it is null or empty
+     * @return the original string with leading and trailing spaces removed, or
+     * null if it is null or empty
      *
      */
     static String getNotNullOrEmpty(String test) {
@@ -206,4 +256,39 @@
             }
         }
     }
+
+    /**
+     * Validates the input for features.
+     *
+     * @param f the feature
+     * @param value the value
+     * @throws IllegalArgumentException if the value is invalid for the feature
+     */
+    static void validateFeatureInput(Feature f, String value) {
+        CatalogMessages.reportNPEOnNull(f.name(), value);
+        if (value.length() == 0) {
+            CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                    new Object[]{value, f.name()}, null);
+        }
+
+        if (f == Feature.PREFER) {
+            if (!value.equals(PREFER_SYSTEM) && !value.equals(PREFER_PUBLIC)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                        new Object[]{value, Feature.PREFER.name()}, null);
+            }
+        } else if (f == Feature.DEFER) {
+            if (!value.equals(DEFER_TRUE) && !value.equals(DEFER_FALSE)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                        new Object[]{value, Feature.DEFER.name()}, null);
+            }
+        } else if (f == Feature.RESOLVE) {
+            if (!value.equals(RESOLVE_STRICT) && !value.equals(RESOLVE_CONTINUE)
+                    && !value.equals(RESOLVE_IGNORE)) {
+                CatalogMessages.reportIAE(CatalogMessages.ERR_INVALID_ARGUMENT,
+                        new Object[]{value, Feature.RESOLVE.name()}, null);
+            }
+        } else if (f == Feature.FILES) {
+            Util.validateUrisSyntax(value.split(";"));
+        }
+    }
 }
--- a/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/SpecifyCatalogTest.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -81,7 +81,7 @@
     @Test
     public void specifyCatalogViaSysProps() {
         setSystemProperty(FEATURE_FILES,
-                getCatalogPath("specifyCatalog-sysProps.xml"));
+                getCatalogPath("specifyCatalog-sysProps.xml").toASCIIString());
 
         checkResolutionOnEntityResolver(catalogResolver((String[]) null),
                 "http://local/base/dtd/docSysPropsSys.dtd");
@@ -107,6 +107,6 @@
     }
 
     private static CatalogFeatures createFeature(String catalogName) {
-        return builder().with(FILES, getCatalogPath(catalogName)).build();
+        return builder().with(FILES, getCatalogPath(catalogName).toASCIIString()).build();
     }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/functional/catalog/catalogFiles/dummy.xml	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,1 @@
+<dummy />
--- a/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/libs/catalog/CatalogTestUtils.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -25,17 +25,16 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.URI;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
 import java.util.Map;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
-
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogManager;
 import javax.xml.catalog.CatalogResolver;
-
 import jaxp.library.JAXPTestUtilities;
 
 /*
@@ -115,20 +114,20 @@
     }
 
     // Gets the paths of the specified catalogs.
-    private static String[] getCatalogPaths(String... catalogNames) {
+    private static URI[] getCatalogPaths(String... catalogNames) {
         return catalogNames == null
                 ? null
                 : Stream.of(catalogNames).map(
                         catalogName -> getCatalogPath(catalogName)).collect(
-                                Collectors.toList()).toArray(new String[0]);
+                                Collectors.toList()).toArray(new URI[0]);
     }
 
     // Gets the paths of the specified catalogs.
-    static String getCatalogPath(String catalogName) {
+    static URI getCatalogPath(String catalogName) {
         return catalogName == null
                 ? null
-                : JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles")
-                        + catalogName;
+                : Paths.get(JAXPTestUtilities.getPathByClassName(CatalogTestUtils.class, "catalogFiles")
+                        + catalogName).toUri();
     }
 
     /* ********** jaxp.properties ********** */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/JarUtils.java	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jaxp.library;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
+import java.util.jar.Manifest;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+/**
+ * This class consists exclusively of static utility methods that are useful
+ * for creating and manipulating JAR files.
+ */
+
+public final class JarUtils {
+    private JarUtils() { }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cfm <jarfile> <manifest> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Manifest man, Path dir, Path... file)
+        throws IOException
+    {
+        // create the target directory
+        Path parent = jarfile.getParent();
+        if (parent != null)
+            Files.createDirectories(parent);
+
+        List<Path> entries = new ArrayList<>();
+        for (Path entry : file) {
+            Files.find(dir.resolve(entry), Integer.MAX_VALUE,
+                        (p, attrs) -> attrs.isRegularFile())
+                    .map(e -> dir.relativize(e))
+                    .forEach(entries::add);
+        }
+
+        try (OutputStream out = Files.newOutputStream(jarfile);
+             JarOutputStream jos = new JarOutputStream(out))
+        {
+            if (man != null) {
+                JarEntry je = new JarEntry(JarFile.MANIFEST_NAME);
+                jos.putNextEntry(je);
+                man.write(jos);
+                jos.closeEntry();
+            }
+
+            for (Path entry : entries) {
+                String name = toJarEntryName(entry);
+                jos.putNextEntry(new JarEntry(name));
+                Files.copy(dir.resolve(entry), jos);
+                jos.closeEntry();
+            }
+        }
+    }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile>  -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, Path... file)
+        throws IOException
+    {
+        createJarFile(jarfile, null, dir, file);
+    }
+
+    /**
+     * Creates a JAR file.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> file...}
+     *
+     * The input files are resolved against the given directory. Any input
+     * files that are directories are processed recursively.
+     */
+    public static void createJarFile(Path jarfile, Path dir, String... input)
+        throws IOException
+    {
+        Path[] paths = Stream.of(input).map(Paths::get).toArray(Path[]::new);
+        createJarFile(jarfile, dir, paths);
+    }
+
+    /**
+     * Creates a JAR file from the contents of a directory.
+     *
+     * Equivalent to {@code jar cf <jarfile> -C <dir> .}
+     */
+    public static void createJarFile(Path jarfile, Path dir) throws IOException {
+        createJarFile(jarfile, dir, Paths.get("."));
+    }
+
+    /**
+     * Map a file path to the equivalent name in a JAR file
+     */
+    private static String toJarEntryName(Path file) {
+        Path normalized = file.normalize();
+        return normalized.subpath(0, normalized.getNameCount())  // drop root
+                .toString()
+                .replace(File.separatorChar, '/');
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/libs/jaxp/library/SimpleHttpServer.java	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package jaxp.library;
+
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpContext;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+import com.sun.net.httpserver.HttpServer;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.InetSocketAddress;
+import java.net.URI;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+/**
+ * A simple HTTP Server
+ */
+public class SimpleHttpServer {
+    HttpServer _httpserver;
+    ExecutorService _executor;
+
+    String _address;
+
+    String _context, _docroot;
+    int _port;
+
+    public SimpleHttpServer(String context, String docroot) {
+        //let the system pick up an ephemeral port in a bind operation
+        this(0, context, docroot);
+    }
+
+    public SimpleHttpServer(int port, String context, String docroot) {
+        _port = port;
+        _context = context;
+        _docroot = docroot;
+    }
+
+    public void start() {
+        MyHttpHandler handler = new MyHttpHandler(_docroot);
+        InetSocketAddress addr = new InetSocketAddress(_port);
+        try {
+            _httpserver = HttpServer.create(addr, 0);
+        } catch (IOException ex) {
+            throw new RuntimeException("cannot create httpserver", ex);
+        }
+
+        //TestHandler is mapped to /test
+        HttpContext ctx = _httpserver.createContext(_context, handler);
+
+        _executor = Executors.newCachedThreadPool();
+        _httpserver.setExecutor(_executor);
+        _httpserver.start();
+
+        _address = "http://localhost:" + _httpserver.getAddress().getPort();
+    }
+
+    public void stop() {
+        _httpserver.stop(2);
+        _executor.shutdown();
+    }
+
+    public String getAddress() {
+        return _address;
+    }
+
+    static class MyHttpHandler implements HttpHandler {
+
+        String _docroot;
+
+        public MyHttpHandler(String docroot) {
+            _docroot = docroot;
+        }
+
+        public void handle(HttpExchange t)
+                throws IOException {
+            InputStream is = t.getRequestBody();
+            Headers map = t.getRequestHeaders();
+            Headers rmap = t.getResponseHeaders();
+            OutputStream os = t.getResponseBody();
+            URI uri = t.getRequestURI();
+            String path = uri.getPath();
+
+
+            while (is.read() != -1) ;
+            is.close();
+
+            File f = new File(_docroot, path);
+            if (!f.exists()) {
+                notfound(t, path);
+                return;
+            }
+
+            String method = t.getRequestMethod();
+            if (method.equals("HEAD")) {
+                rmap.set("Content-Length", Long.toString(f.length()));
+                t.sendResponseHeaders(200, -1);
+                t.close();
+            } else if (!method.equals("GET")) {
+                t.sendResponseHeaders(405, -1);
+                t.close();
+                return;
+            }
+
+            if (path.endsWith(".html") || path.endsWith(".htm")) {
+                rmap.set("Content-Type", "text/html");
+            } else {
+                rmap.set("Content-Type", "text/plain");
+            }
+
+            t.sendResponseHeaders (200, f.length());
+
+            FileInputStream fis = new FileInputStream(f);
+            int count = 0;
+            try {
+                byte[] buf = new byte[16 * 1024];
+                int len;
+                while ((len = fis.read(buf)) != -1) {
+                    os.write(buf, 0, len);
+                    count += len;
+                }
+            } catch (IOException e) {
+                e.printStackTrace();
+            }
+            fis.close();
+            os.close();
+        }
+
+        void moved(HttpExchange t) throws IOException {
+            Headers req = t.getRequestHeaders();
+            Headers map = t.getResponseHeaders();
+            URI uri = t.getRequestURI();
+            String host = req.getFirst("Host");
+            String location = "http://" + host + uri.getPath() + "/";
+            map.set("Content-Type", "text/html");
+            map.set("Location", location);
+            t.sendResponseHeaders(301, -1);
+            t.close();
+        }
+
+        void notfound(HttpExchange t, String p) throws IOException {
+            t.getResponseHeaders().set("Content-Type", "text/html");
+            t.sendResponseHeaders(404, 0);
+            OutputStream os = t.getResponseBody();
+            String s = "<h2>File not found</h2>";
+            s = s + p + "<p>";
+            os.write(s.getBytes());
+            os.close();
+            t.close();
+        }
+    }
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogAccessTest.java	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package catalog;
+
+import java.net.URI;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import org.testng.Assert;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+import static jaxp.library.JAXPTestUtilities.tryRunWithAllPerm;
+
+/*
+ * @test
+ * @bug 8171243
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm -DrunSecMngr=true catalog.CatalogAccessTest
+ * @summary the Catalog API grants no privilege to external resources. This test
+ * verifies that SecurityException will be thrown if access to resources is denied
+ * by the security manager.
+ */
+@Listeners({jaxp.library.BasePolicy.class})
+public class CatalogAccessTest {
+    static final CatalogFeatures FEATURES = CatalogFeatures.builder().
+            with(CatalogFeatures.Feature.PREFER, "system").build();
+
+    /*
+     * Verifies that the SecurityException is thrown if access to the resource is
+     * denied by the security manager.
+     */
+    @Test(dataProvider = "accessTest", expectedExceptions = SecurityException.class)
+    public void testSecurity(String cfile, String sysId, String pubId) throws Exception {
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(cfile));
+        InputSource is = cr.resolveEntity(pubId, sysId);
+        Assert.fail("Failed to throw SecurityException");
+    }
+
+    /*
+        DataProvider: used for SecurityException testing
+        Data columns:
+        catalog uri, systemId, publicId
+     */
+    @DataProvider(name = "accessTest")
+    Object[][] getDataForAccessTest() throws Exception {
+        String systemId = "http://www.sys00test.com/rewrite.dtd";
+        String publicId = "PUB-404";
+        String urlFile = tryRunWithAllPerm(() ->
+                getClass().getResource("rewriteSystem_id.xml").toExternalForm());
+        return new Object[][]{
+            {urlFile, systemId, publicId}
+        };
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogFileInputTest.java	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,282 @@
+/*
+ * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
+ *
+ * This code is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 only, as
+ * published by the Free Software Foundation.
+ *
+ * This code is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
+ * version 2 for more details (a copy is included in the LICENSE file that
+ * accompanied this code).
+ *
+ * You should have received a copy of the GNU General Public License version
+ * 2 along with this work; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
+ * or visit www.oracle.com if you need additional information or have any
+ * questions.
+ */
+package catalog;
+
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.net.URI;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import static java.nio.file.StandardOpenOption.APPEND;
+import static java.nio.file.StandardOpenOption.CREATE;
+import javax.xml.catalog.Catalog;
+import javax.xml.catalog.CatalogException;
+import javax.xml.catalog.CatalogFeatures;
+import javax.xml.catalog.CatalogManager;
+import javax.xml.catalog.CatalogResolver;
+import static jaxp.library.JAXPTestUtilities.getSystemProperty;
+import jaxp.library.JarUtils;
+import jaxp.library.SimpleHttpServer;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.DataProvider;
+import org.testng.annotations.Listeners;
+import org.testng.annotations.Test;
+import org.xml.sax.InputSource;
+
+/*
+ * @test
+ * @bug 8151154 8171243
+ * @library /javax/xml/jaxp/libs /javax/xml/jaxp/unittest
+ * @run testng/othervm catalog.CatalogFileInputTest
+ * @summary Verifies that the Catalog API accepts valid URIs only;
+            Verifies that the CatalogFeatures' builder throws
+ *          IllegalArgumentException on invalid file inputs.
+ *          This test was splitted from CatalogTest.java due to
+ *          JDK-8168968, it has to only run without SecurityManager
+ *          because an ACE will be thrown for invalid path.
+ */
+@Listeners({jaxp.library.FilePolicy.class, jaxp.library.NetAccessPolicy.class})
+public class CatalogFileInputTest extends CatalogSupportBase {
+
+    static final CatalogFeatures FEATURES = CatalogFeatures.builder().
+            with(CatalogFeatures.Feature.PREFER, "system").build();
+    static String USER_DIR = getSystemProperty("user.dir");
+    static String CLS_DIR = getSystemProperty("test.classes");
+    static String SRC_DIR = System.getProperty("test.src");
+    static String JAR_CONTENT = "META-INF";
+    final static String SCHEME_JARFILE = "jar:";
+    static final String REMOTE_FILE_LOCATION = "/jar/META-INF";
+    static final String DOCROOT = SRC_DIR;
+    static final String TESTCONTEXT = REMOTE_FILE_LOCATION;  //mapped to local file path
+    SimpleHttpServer _httpserver;
+    String _remoteFilePath;
+
+    /*
+     * Initializing fields
+     */
+    @BeforeClass
+    public void setUpClass() throws Exception {
+        super.setUp();
+
+        // set up HttpServer
+        _httpserver = new SimpleHttpServer(TESTCONTEXT, DOCROOT);
+        _httpserver.start();
+        _remoteFilePath = _httpserver.getAddress() + REMOTE_FILE_LOCATION;
+
+    }
+
+    @AfterClass
+    protected void tearDown() throws Exception {
+        if (_httpserver != null) {
+            _httpserver.stop();
+        }
+    }
+
+    /*
+     * Verifies that the Catalog can be created with file system paths including JAR
+     * and http URL, and used to resolve a systemId as expected.
+     */
+    @Test(dataProvider = "acceptedURI")
+    public void testMatch(String uri, String sysId, String pubId,
+            String expectedId, String msg) throws Exception {
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, URI.create(uri));
+        InputSource is = cr.resolveEntity(pubId, sysId);
+        Assert.assertNotNull(is, msg);
+        Assert.assertEquals(expectedId, is.getSystemId(), msg);
+    }
+
+    @Test(dataProvider = "invalidCatalog")
+    public void testEmptyCatalog(String uri, String publicId, String msg) {
+        Catalog c = CatalogManager.catalog(FEATURES, uri != null? URI.create(uri) : null);
+        Assert.assertNull(c.matchSystem(publicId), msg);
+    }
+
+    @Test(dataProvider = "invalidCatalog", expectedExceptions = CatalogException.class)
+    public void testCatalogResolverWEmptyCatalog(String uri, String publicId, String msg) {
+        CatalogResolver cr = CatalogManager.catalogResolver(
+                CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "strict").build(),
+                uri != null? URI.create(uri) : null);
+        InputSource is = cr.resolveEntity(publicId, "");
+    }
+
+    @Test(dataProvider = "invalidCatalog")
+    public void testCatalogResolverWEmptyCatalog1(String uri, String publicId, String msg) {
+        CatalogResolver cr = CatalogManager.catalogResolver(
+                CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE, "continue").build(),
+                uri != null? URI.create(uri) : null);
+        Assert.assertNull(cr.resolveEntity(publicId, ""), msg);
+    }
+
+    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+    public void testFileInput(String file) {
+        CatalogFeatures features = CatalogFeatures.builder()
+            .with(CatalogFeatures.Feature.FILES, file)
+            .build();
+    }
+
+    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+    public void testInvalidUri(String file) {
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, file != null? URI.create(file) : null);
+    }
+
+    @Test(dataProvider = "invalidInput", expectedExceptions = IllegalArgumentException.class)
+    public void testInvalidUri1(String file) {
+        Catalog c = CatalogManager.catalog(FEATURES, file != null? URI.create(file) : null);
+        System.err.println("Catalog =" + c);
+    }
+
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullFileInput() {
+        CatalogFeatures features = CatalogFeatures.builder()
+            .with(CatalogFeatures.Feature.FILES, null)
+            .build();
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullUri() {
+        URI uri = null;
+        CatalogResolver cr = CatalogManager.catalogResolver(FEATURES, uri);
+    }
+
+    @Test(expectedExceptions = NullPointerException.class)
+    public void testNullUri1() {
+        URI uri = null;
+        Catalog c = CatalogManager.catalog(FEATURES, uri);
+    }
+
+    String systemId = "http://www.sys00test.com/rewrite.dtd";
+    String publicId = "PUB-404";
+    String expected = "http://www.groupxmlbase.com/dtds/rewrite.dtd";
+    String errMsg = "Relative rewriteSystem with xml:base at group level failed";
+
+    /*
+        DataProvider: used to verify CatalogResolver's resolveEntity function.
+        Data columns:
+        catalog, systemId, publicId, expectedUri, msg
+     */
+    @DataProvider(name = "acceptedURI")
+    Object[][] getData() throws Exception {
+        String filename = "rewriteSystem_id.xml";
+        String urlFile = getClass().getResource(filename).toExternalForm();
+        String urlHttp = _remoteFilePath + "/jax-ws-catalog.xml";
+        String remoteXSD = _remoteFilePath + "/catalog/ws-addr.xsd";
+        File file = new File(CLS_DIR + "/JDK8171243.jar!/META-INF/jax-ws-catalog.xml");
+        String jarPath = SCHEME_JARFILE + file.toURI().toString();
+        String xsd = jarPath.substring(0, jarPath.lastIndexOf("/")) + "/catalog/ws-addr.xsd";
+
+        // create JAR file
+        try {
+            JarUtils.createJarFile(Paths.get(CLS_DIR + "/JDK8171243.jar"),
+                    Paths.get(SRC_DIR + "/jar"), JAR_CONTENT);
+        } catch (IOException ex) {
+            Assert.fail("Failed to create JAR: " + ex.getMessage());
+        }
+
+        return new Object[][]{
+            // URL
+            {urlFile, systemId, publicId, expected, errMsg},
+            {urlHttp, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", remoteXSD, "http test failed."},
+            // JAR file
+            {jarPath, "http://www.w3.org/2006/03/addressing/ws-addr.xsd", "", xsd, "jar file test failed."},
+        };
+    }
+
+    /*
+     *  DataProvider: invalid catalog result in empty catalog
+     *  Note: the difference from invalidInput is that invalidInput is syntactically
+     *  rejected with an IAE.
+     */
+    @DataProvider(name = "invalidCatalog")
+    public Object[][] getInvalidCatalog() throws Exception {
+        String catalogUri = getClass().getResource("catalog_invalid.xml").toExternalForm();
+        return new Object[][]{
+            {catalogUri, "-//W3C//DTD XHTML 1.0 Strict//EN",
+                "The catalog is invalid, attempting to match the public entry shall return null."}
+        };
+    }
+
+    /*
+     *  DataProvider: a list of invalid inputs, expects IAE
+     *  Note: exclude null since NPE would have been expected
+     */
+    @DataProvider(name = "invalidInput")
+    public Object[][] getFiles() throws Exception {
+        String filename = "rewriteSystem_id.xml";
+        copyFile(Paths.get(SRC_DIR + "/" + filename), Paths.get(filename));
+        String absolutePath = getClass().getResource(filename).getFile();
+
+        return new Object[][]{
+            {""},
+            {"file:a/b\\c"},
+            {"file:/../../.."},
+            {"c:/te:t"},
+            {"c:/te?t"},
+            {"c/te*t"},
+            {"in|valid.txt"},
+            {"shema:invalid.txt"},
+            // relative file path
+            {filename},
+            // absolute file path
+            {absolutePath}
+        };
+    }
+
+    /*
+       DataProvider: a list of invalid inputs
+     */
+    @DataProvider(name = "nullTest")
+    public Object[][] getNull() throws Exception {
+
+        return new Object[][]{
+            {null},
+        };
+    }
+
+    void copyFile(Path src, Path target) throws Exception {
+
+        try (InputStream in = Files.newInputStream(src);
+                BufferedReader reader
+                = new BufferedReader(new InputStreamReader(in));
+                OutputStream out = new BufferedOutputStream(
+                        Files.newOutputStream(target, CREATE, APPEND));
+                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(out))) {
+            String line = null;
+            while ((line = reader.readLine()) != null) {
+                bw.write(line);
+            }
+        } catch (IOException x) {
+            throw new Exception(x.getMessage());
+        }
+    }
+}
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogInvalidPathTest.java	Wed Jul 05 22:40:29 2017 +0200
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,66 +0,0 @@
-/*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
- * or visit www.oracle.com if you need additional information or have any
- * questions.
- */
-package catalog;
-
-import javax.xml.catalog.CatalogFeatures;
-
-import org.testng.annotations.DataProvider;
-import org.testng.annotations.Test;
-
-/*
- * @test
- * @bug 8151154
- * @run testng/othervm catalog.CatalogInvalidPathTest
- * @summary Verifies that the CatalogFeatures' builder throws
- *          IllegalArgumentException on invalid file inputs.
- *          This test was splitted from CatalogTest.java due to
- *          JDK-8168968, it has to only run without SecurityManager
- *          because an ACE will be thrown for invalid path.
- */
-public class CatalogInvalidPathTest {
-    /*
-       DataProvider: for testing the verification of file paths by
-                     the CatalogFeatures builder
-     */
-    @DataProvider(name = "invalidPaths")
-    public Object[][] getFiles() {
-        return new Object[][]{
-            {null},
-            {""},
-            {"file:a/b\\c"},
-            {"file:/../../.."},
-            {"c:/te:t"},
-            {"c:/te?t"},
-            {"c/te*t"},
-            {"in|valid.txt"},
-            {"shema:invalid.txt"},
-        };
-    }
-
-    @Test(dataProvider = "invalidPaths", expectedExceptions = IllegalArgumentException.class)
-    public void testFileInput(String file) {
-        CatalogFeatures features = CatalogFeatures.builder()
-            .with(CatalogFeatures.Feature.FILES, file)
-            .build();
-    }
-}
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogSupportBase.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2016, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -35,6 +35,13 @@
 import java.io.StringReader;
 import java.io.StringWriter;
 import java.io.UnsupportedEncodingException;
+import java.nio.file.Paths;
+import java.security.CodeSource;
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.security.Policy;
+import java.security.ProtectionDomain;
 import javax.xml.XMLConstants;
 import javax.xml.catalog.CatalogFeatures;
 import javax.xml.catalog.CatalogResolver;
@@ -133,8 +140,8 @@
         dtd_system = filepath + "system.dtd";
         dtd_systemResolved = "<!ENTITY system \"resolved by an EntityHandler, rather than a Catalog\">";
 
-        xml_catalog = filepath + "CatalogSupport.xml";
-        xml_bogus_catalog = filepath + "CatalogSupport_bogus.xml";
+        xml_catalog = Paths.get(filepath + "CatalogSupport.xml").toUri().toASCIIString();
+        xml_bogus_catalog = Paths.get(filepath + "CatalogSupport_bogus.xml").toUri().toASCIIString();
 
         xml_xInclude = "<?xml version=\"1.0\"?>\n" +
             "<xinclude:include xmlns:xinclude=\"http://www.w3.org/2001/XInclude\"\n" +
@@ -997,4 +1004,35 @@
             return null;
         }
     }
+
+    /**
+     * Simple policy implementation that grants a set of permissions to all code
+     * sources and protection domains.
+     */
+    static class SimplePolicy extends Policy {
+
+        private final Permissions perms;
+
+        public SimplePolicy(Permission... permissions) {
+            perms = new Permissions();
+            for (Permission permission : permissions) {
+                perms.add(permission);
+            }
+        }
+
+        @Override
+        public PermissionCollection getPermissions(CodeSource cs) {
+            return perms;
+        }
+
+        @Override
+        public PermissionCollection getPermissions(ProtectionDomain pd) {
+            return perms;
+        }
+
+        @Override
+        public boolean implies(ProtectionDomain pd, Permission p) {
+            return perms.implies(p);
+        }
+    }
 }
--- a/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Wed Jul 05 22:40:29 2017 +0200
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/CatalogTest.java	Wed Jan 11 13:06:04 2017 -0800
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  *
  * This code is free software; you can redistribute it and/or modify it
@@ -22,17 +22,14 @@
  */
 package catalog;
 
-import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
-import static jaxp.library.JAXPTestUtilities.setSystemProperty;
-
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.StringReader;
 import java.io.StringWriter;
+import java.net.URI;
 import java.nio.file.Paths;
-
 import javax.xml.XMLConstants;
 import javax.xml.catalog.Catalog;
 import javax.xml.catalog.CatalogException;
@@ -55,7 +52,8 @@
 import javax.xml.validation.Schema;
 import javax.xml.validation.SchemaFactory;
 import javax.xml.validation.Validator;
-
+import static jaxp.library.JAXPTestUtilities.clearSystemProperty;
+import static jaxp.library.JAXPTestUtilities.setSystemProperty;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.DataProvider;
@@ -95,10 +93,10 @@
      * CatalogException is thrown.
      */
     @Test(dataProvider = "getFeatures", expectedExceptions = CatalogException.class)
-    public void testCircularRef(CatalogFeatures cf, String xml) {
+    public void testCircularRef(CatalogFeatures cf, String xml) throws Exception {
         CatalogResolver catalogResolver = CatalogManager.catalogResolver(
                 cf,
-                getClass().getResource(xml).getFile());
+                getClass().getResource(xml).toURI());
         catalogResolver.resolve("anyuri", "");
     }
 
@@ -108,14 +106,14 @@
      */
     @DataProvider(name = "getFeatures")
     public Object[][] getFeatures() {
-
+        String self = "catalogReferCircle-itself.xml";
+        String left = "catalogReferCircle-left.xml";
         return new Object[][]{
-            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(),
-                "catalogReferCircle-itself.xml"},
-            {CatalogFeatures.defaults(), "catalogReferCircle-itself.xml"},
-            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(),
-                "catalogReferCircle-left.xml"},
-            {CatalogFeatures.defaults(), "catalogReferCircle-left.xml"},};
+            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(), self},
+            {CatalogFeatures.defaults(), self},
+            {CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "false").build(), left},
+            {CatalogFeatures.defaults(), left}
+        };
     }
 
     /*
@@ -134,7 +132,7 @@
      * Expected: the parser returns the expected string.
     */
     @Test(dataProvider = "supportXMLResolver")
-    public void supportEntityResolver(String catalogFile, String xml, String expected) throws Exception {
+    public void supportEntityResolver(URI catalogFile, String xml, String expected) throws Exception {
         String xmlSource = getClass().getResource(xml).getFile();
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
@@ -150,7 +148,7 @@
      * Expected: the parser returns the expected string.
     */
     @Test(dataProvider = "supportXMLResolver")
-    public void supportXMLResolver(String catalogFile, String xml, String expected) throws Exception {
+    public void supportXMLResolver(URI catalogFile, String xml, String expected) throws Exception {
         String xmlSource = getClass().getResource(xml).getFile();
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
@@ -159,7 +157,7 @@
         xifactory.setProperty(XMLInputFactory.IS_COALESCING, true);
         xifactory.setProperty(XMLInputFactory.RESOLVER, cr);
         File file = new File(xmlSource);
-        String systemId = file.toURI().toString();
+        String systemId = file.toURI().toASCIIString();
         InputStream entityxml = new FileInputStream(file);
         XMLStreamReader streamReader = xifactory.createXMLStreamReader(systemId, entityxml);
         String result = null;
@@ -183,7 +181,7 @@
      * Fail: throws Exception if references are not resolved (by the CatalogResolver)
     */
     @Test(dataProvider = "supportLSResourceResolver")
-    public void supportLSResourceResolver(String catalogFile, Source schemaSource) throws SAXException {
+    public void supportLSResourceResolver(URI catalogFile, Source schemaSource) throws SAXException {
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
 
@@ -199,7 +197,7 @@
      * Fail: throws Exception if references are not resolved (by the CatalogResolver)
     */
     @Test(dataProvider = "supportLSResourceResolver1")
-    public void supportLSResourceResolver1(String catalogFile, Source source) throws Exception {
+    public void supportLSResourceResolver1(URI catalogFile, Source source) throws Exception {
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
 
@@ -215,7 +213,7 @@
      * Fail: throws Exception if references are not resolved (by the CatalogResolver)
     */
     @Test(dataProvider = "supportURIResolver")
-    public void supportURIResolver(String catalogFile, Source xsl, Source xml, String expected) throws Exception {
+    public void supportURIResolver(URI catalogFile, Source xsl, Source xml, String expected) throws Exception {
 
         CatalogResolver cr = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
 
@@ -235,9 +233,9 @@
         catalog filepath, xml source file, expected result
      */
     @DataProvider(name = "supportXMLResolver")
-    public Object[][] supportXMLResolver() {
-        String catalogFile = getClass().getResource("catalog.xml").getFile();
-        String catalogFileUri = getClass().getResource("catalog_uri.xml").getFile();
+    public Object[][] supportXMLResolver() throws Exception {
+        URI catalogFile = getClass().getResource("catalog.xml").toURI();
+        URI catalogFileUri = getClass().getResource("catalog_uri.xml").toURI();
 
         return new Object[][]{
             {catalogFile, "system.xml", "Test system entry"},
@@ -263,9 +261,9 @@
         catalog filepath, schema source file
      */
     @DataProvider(name = "supportLSResourceResolver")
-    public Object[][] supportLSResourceResolver() {
-        String catalogFile = getClass().getResource("CatalogSupport.xml").getFile();
-        String catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").getFile();
+    public Object[][] supportLSResourceResolver() throws Exception {
+        URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI();
+        URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI();
 
         /*
          * XMLSchema.xsd has a reference to XMLSchema.dtd which in turn refers to
@@ -287,9 +285,9 @@
         catalog filepath, source file
      */
     @DataProvider(name = "supportLSResourceResolver1")
-    public Object[][] supportLSResourceResolver1() {
-        String catalogFile = getClass().getResource("CatalogSupport.xml").getFile();
-        String catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").getFile();
+    public Object[][] supportLSResourceResolver1() throws Exception {
+        URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI();
+        URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI();
 
         /*
          * val_test.xml has a reference to system.dtd and val_test.xsd
@@ -310,9 +308,9 @@
         catalog filepath, xsl source, xml source file
      */
     @DataProvider(name = "supportURIResolver")
-    public Object[][] supportURIResolver() {
-        String catalogFile = getClass().getResource("CatalogSupport.xml").getFile();
-        String catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").getFile();
+    public Object[][] supportURIResolver() throws Exception {
+        URI catalogFile = getClass().getResource("CatalogSupport.xml").toURI();
+        URI catalogFileUri = getClass().getResource("CatalogSupport_uri.xml").toURI();
         SAXSource xslSource = new SAXSource(new InputSource(new File(xsl_doc).toURI().toASCIIString()));
 
         /*
@@ -353,8 +351,9 @@
      * other cases in that test.
      */
     @Test(dataProvider = "resolveUri")
-    public void testMatch1(String cFile, String href, String expectedFile, String expectedUri, String msg) {
-        String catalogFile = getClass().getResource(cFile).getFile();
+    public void testMatch1(String cFile, String href, String expectedFile,
+            String expectedUri, String msg) throws Exception {
+        URI catalogFile = getClass().getResource(cFile).toURI();
         CatalogResolver cur = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalogFile);
         Source source = cur.resolve(href, null);
         Assert.assertNotNull(source, "Source returned is null");
@@ -368,15 +367,16 @@
      */
     @Test(dataProvider = "hierarchyOfCatFilesData")
     public void hierarchyOfCatFiles2(String systemId, String expectedUri) {
-        String file1 = getClass().getResource("first_cat.xml").getFile();
-        String file2 = getClass().getResource("second_cat.xml").getFile();
+        String file1 = getClass().getResource("first_cat.xml").toExternalForm();
+        String file2 = getClass().getResource("second_cat.xml").toExternalForm();
         String files = file1 + ";" + file2;
 
         try {
             setSystemProperty(KEY_FILES, files);
             CatalogResolver catalogResolver = CatalogManager.catalogResolver(CatalogFeatures.defaults());
             String sysId = catalogResolver.resolveEntity(null, systemId).getSystemId();
-            Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"), "System ID match not right");
+            Assert.assertEquals(sysId, Paths.get(filepath + expectedUri).toUri().toString().replace("///", "/"),
+                    "System ID match not right");
         } finally {
             clearSystemProperty(KEY_FILES);
         }
@@ -390,8 +390,9 @@
      * expected.
      */
     @Test(dataProvider = "resolveEntity")
-    public void testMatch1(String cfile, String prefer, String sysId, String pubId, String expectedUri, String expectedFile, String msg) {
-        String catalogFile = getClass().getResource(cfile).getFile();
+    public void testMatch1(String cfile, String prefer, String sysId, String pubId,
+            String expectedUri, String expectedFile, String msg) throws Exception {
+        URI catalogFile = getClass().getResource(cfile).toURI();
         CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build();
         CatalogResolver catalogResolver = CatalogManager.catalogResolver(features, catalogFile);
         InputSource is = catalogResolver.resolveEntity(pubId, sysId);
@@ -406,9 +407,12 @@
      * results as expected.
      */
     @Test(dataProvider = "matchWithPrefer")
-    public void matchWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) {
-        String catalogFile = getClass().getResource(cfile).getFile();
-        Catalog c = CatalogManager.catalog(CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(), catalogFile);
+    public void matchWithPrefer(String prefer, String cfile, String publicId,
+            String systemId, String expected) throws Exception {
+        URI catalogFile = getClass().getResource(cfile).toURI();
+        Catalog c = CatalogManager.catalog(
+                CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).build(),
+                catalogFile);
         String result;
         if (publicId != null && publicId.length() > 0) {
             result = c.matchPublic(publicId);
@@ -430,8 +434,9 @@
      *                  system entry is found.
      */
     @Test(dataProvider = "resolveWithPrefer")
-    public void resolveWithPrefer(String prefer, String cfile, String publicId, String systemId, String expected) {
-        String catalogFile = getClass().getResource(cfile).getFile();
+    public void resolveWithPrefer(String prefer, String cfile, String publicId,
+            String systemId, String expected) throws Exception {
+        URI catalogFile = getClass().getResource(cfile).toURI();
         CatalogFeatures f = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, prefer).with(CatalogFeatures.Feature.RESOLVE, "ignore").build();
         CatalogResolver catalogResolver = CatalogManager.catalogResolver(f, catalogFile);
         String result = catalogResolver.resolveEntity(publicId, systemId).getSystemId();
@@ -445,8 +450,8 @@
      * be loaded is determined by the defer attribute.
      */
     @Test(dataProvider = "invalidAltCatalogs", expectedExceptions = CatalogException.class)
-    public void testDeferAltCatalogs(String file) {
-        String catalogFile = getClass().getResource(file).getFile();
+    public void testDeferAltCatalogs(String file) throws Exception {
+        URI catalogFile = getClass().getResource(file).toURI();
         CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.DEFER, "true").build();
         /*
           Since the defer attribute is set to false in the specified catalog file,
@@ -462,8 +467,8 @@
      * PREFER from Features API taking precedence over catalog file
      */
     @Test
-    public void testJDK8146237() {
-        String catalogFile = getClass().getResource("JDK8146237_catalog.xml").getFile();
+    public void testJDK8146237() throws Exception {
+        URI catalogFile = getClass().getResource("JDK8146237_catalog.xml").toURI();
 
         try {
             CatalogFeatures features = CatalogFeatures.builder().with(CatalogFeatures.Feature.PREFER, "system").build();
@@ -482,8 +487,8 @@
        Verifies that the resulting systemId does not contain duplicate slashes
     */
     @Test
-    public void testRewriteSystem() {
-        String catalog = getClass().getResource("rewriteCatalog.xml").getFile();
+    public void testRewriteSystem() throws Exception {
+        URI catalog = getClass().getResource("rewriteCatalog.xml").toURI();
 
         try {
             CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), catalog);
@@ -500,8 +505,8 @@
        Verifies that the resulting systemId does not contain duplicate slashes
     */
     @Test
-    public void testRewriteUri() {
-        String catalog = getClass().getResource("rewriteCatalog.xml").getFile();
+    public void testRewriteUri() throws Exception {
+        URI catalog = getClass().getResource("rewriteCatalog.xml").toURI();
 
         try {
 
@@ -519,18 +524,18 @@
     */
     @Test(expectedExceptions = NullPointerException.class)
     public void testFeatureNull() {
-        CatalogResolver resolver = CatalogManager.catalogResolver(null, "");
+        CatalogResolver resolver = CatalogManager.catalogResolver(null, null);
 
     }
 
     /*
        @bug 8144966
-       Verifies that passing null as the path will result in a NPE.
+       Verifies that passing null as the URI will result in a NPE.
     */
     @Test(expectedExceptions = NullPointerException.class)
     public void testPathNull() {
-        String path = null;
-        CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), path);
+        URI uri = null;
+        CatalogResolver resolver = CatalogManager.catalogResolver(CatalogFeatures.defaults(), uri);
     }
 
     /*
@@ -540,10 +545,11 @@
     that matches the expected value.
      */
     @Test(dataProvider = "catalog")
-    public void testCatalogResolver(String test, String expected, String catalogFile, String xml, SAXParser saxParser) {
-        String catalog = null;
+    public void testCatalogResolver(String test, String expected, String catalogFile,
+            String xml, SAXParser saxParser) throws Exception {
+        URI catalog = null;
         if (catalogFile != null) {
-            catalog = getClass().getResource(catalogFile).getFile();
+            catalog = getClass().getResource(catalogFile).toURI();
         }
         String url = getClass().getResource(xml).getFile();
         try {
@@ -565,8 +571,8 @@
     catalog is provided, the resolver will throw an exception by default.
     */
     @Test
-    public void testInvalidCatalog() {
-        String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+    public void testInvalidCatalog() throws Exception {
+        URI catalog = getClass().getResource("catalog_invalid.xml").toURI();
 
         String test = "testInvalidCatalog";
         try {
@@ -590,7 +596,7 @@
     */
     @Test
     public void testIgnoreInvalidCatalog() {
-        String catalog = getClass().getResource("catalog_invalid.xml").getFile();
+        String catalog = getClass().getResource("catalog_invalid.xml").toExternalForm();
         CatalogFeatures f = CatalogFeatures.builder()
                 .with(Feature.FILES, catalog)
                 .with(Feature.PREFER, "public")
@@ -600,7 +606,7 @@
 
         String test = "testInvalidCatalog";
         try {
-            CatalogResolver resolver = CatalogManager.catalogResolver(f, "");
+            CatalogResolver resolver = CatalogManager.catalogResolver(f);
             String actualSystemId = resolver.resolveEntity(null, "http://remote/xml/dtd/sys/alice/docAlice.dtd").getSystemId();
             System.out.println("testIgnoreInvalidCatalog: expected [null]");
             System.out.println("testIgnoreInvalidCatalog: expected [null]");
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/MANIFEST.MF	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,3 @@
+Manifest-Version: 1.0
+Created-By: 9-ea (Oracle Corporation)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/catalog/ws-addr.xsd	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,137 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+    W3C XML Schema defined in the Web Services Addressing 1.0 specification
+    http://www.w3.org/TR/ws-addr-core
+
+   Copyright © 2005 World Wide Web Consortium,
+
+   (Massachusetts Institute of Technology, European Research Consortium for
+   Informatics and Mathematics, Keio University). All Rights Reserved. This
+   work is distributed under the W3C® Software License [1] in the hope that
+   it will be useful, but WITHOUT ANY WARRANTY; without even the implied
+   warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+   [1] http://www.w3.org/Consortium/Legal/2002/copyright-software-20021231
+
+   $Id: ws-addr.xsd,v 1.2 2008/07/23 13:38:16 plehegar Exp $
+-->
+<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:tns="http://www.w3.org/2005/08/addressing" targetNamespace="http://www.w3.org/2005/08/addressing" blockDefault="#all" elementFormDefault="qualified" finalDefault="" attributeFormDefault="unqualified">
+	
+	<!-- Constructs from the WS-Addressing Core -->
+
+	<xs:element name="EndpointReference" type="tns:EndpointReferenceType"/>
+	<xs:complexType name="EndpointReferenceType" mixed="false">
+		<xs:sequence>
+			<xs:element name="Address" type="tns:AttributedURIType"/>
+			<xs:element ref="tns:ReferenceParameters" minOccurs="0"/>
+			<xs:element ref="tns:Metadata" minOccurs="0"/>
+			<xs:any namespace="##other" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+	<xs:element name="ReferenceParameters" type="tns:ReferenceParametersType"/>
+	<xs:complexType name="ReferenceParametersType" mixed="false">
+		<xs:sequence>
+			<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+	<xs:element name="Metadata" type="tns:MetadataType"/>
+	<xs:complexType name="MetadataType" mixed="false">
+		<xs:sequence>
+			<xs:any namespace="##any" processContents="lax" minOccurs="0" maxOccurs="unbounded"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+	<xs:element name="MessageID" type="tns:AttributedURIType"/>
+	<xs:element name="RelatesTo" type="tns:RelatesToType"/>
+	<xs:complexType name="RelatesToType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:anyURI">
+				<xs:attribute name="RelationshipType" type="tns:RelationshipTypeOpenEnum" use="optional" default="http://www.w3.org/2005/08/addressing/reply"/>
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<xs:simpleType name="RelationshipTypeOpenEnum">
+		<xs:union memberTypes="tns:RelationshipType xs:anyURI"/>
+	</xs:simpleType>
+	
+	<xs:simpleType name="RelationshipType">
+		<xs:restriction base="xs:anyURI">
+			<xs:enumeration value="http://www.w3.org/2005/08/addressing/reply"/>
+		</xs:restriction>
+	</xs:simpleType>
+	
+	<xs:element name="ReplyTo" type="tns:EndpointReferenceType"/>
+	<xs:element name="From" type="tns:EndpointReferenceType"/>
+	<xs:element name="FaultTo" type="tns:EndpointReferenceType"/>
+	<xs:element name="To" type="tns:AttributedURIType"/>
+	<xs:element name="Action" type="tns:AttributedURIType"/>
+
+	<xs:complexType name="AttributedURIType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:anyURI">
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<!-- Constructs from the WS-Addressing SOAP binding -->
+
+	<xs:attribute name="IsReferenceParameter" type="xs:boolean"/>
+	
+	<xs:simpleType name="FaultCodesOpenEnumType">
+		<xs:union memberTypes="tns:FaultCodesType xs:QName"/>
+	</xs:simpleType>
+	
+	<xs:simpleType name="FaultCodesType">
+		<xs:restriction base="xs:QName">
+			<xs:enumeration value="tns:InvalidAddressingHeader"/>
+			<xs:enumeration value="tns:InvalidAddress"/>
+			<xs:enumeration value="tns:InvalidEPR"/>
+			<xs:enumeration value="tns:InvalidCardinality"/>
+			<xs:enumeration value="tns:MissingAddressInEPR"/>
+			<xs:enumeration value="tns:DuplicateMessageID"/>
+			<xs:enumeration value="tns:ActionMismatch"/>
+			<xs:enumeration value="tns:MessageAddressingHeaderRequired"/>
+			<xs:enumeration value="tns:DestinationUnreachable"/>
+			<xs:enumeration value="tns:ActionNotSupported"/>
+			<xs:enumeration value="tns:EndpointUnavailable"/>
+		</xs:restriction>
+	</xs:simpleType>
+	
+	<xs:element name="RetryAfter" type="tns:AttributedUnsignedLongType"/>
+	<xs:complexType name="AttributedUnsignedLongType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:unsignedLong">
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<xs:element name="ProblemHeaderQName" type="tns:AttributedQNameType"/>
+	<xs:complexType name="AttributedQNameType" mixed="false">
+		<xs:simpleContent>
+			<xs:extension base="xs:QName">
+				<xs:anyAttribute namespace="##other" processContents="lax"/>
+			</xs:extension>
+		</xs:simpleContent>
+	</xs:complexType>
+	
+	<xs:element name="ProblemIRI" type="tns:AttributedURIType"/>
+	
+	<xs:element name="ProblemAction" type="tns:ProblemActionType"/>
+	<xs:complexType name="ProblemActionType" mixed="false">
+		<xs:sequence>
+			<xs:element ref="tns:Action" minOccurs="0"/>
+			<xs:element name="SoapAction" minOccurs="0" type="xs:anyURI"/>
+		</xs:sequence>
+		<xs:anyAttribute namespace="##other" processContents="lax"/>
+	</xs:complexType>
+	
+</xs:schema>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jaxp/test/javax/xml/jaxp/unittest/catalog/jar/META-INF/jax-ws-catalog.xml	Wed Jan 11 13:06:04 2017 -0800
@@ -0,0 +1,4 @@
+<?xml version='1.0' encoding='UTF-8'?>
+<catalog prefer="system" xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
+  <system systemId="http://www.w3.org/2006/03/addressing/ws-addr.xsd" uri="./catalog/ws-addr.xsd"/>
+</catalog>
\ No newline at end of file