This commit is contained in:
Lana Steuck 2015-11-05 13:42:14 -08:00
commit 439ff0270f
127 changed files with 8649 additions and 0 deletions
jaxp
src/java.xml/share/classes
test/javax/xml/jaxp/functional/catalog

@ -0,0 +1,88 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
/**
* Represents an alternative catalog entry.
*
* @since 9
*/
class AltCatalog extends BaseEntry {
URI catalogURI;
AltCatalog(CatalogEntryType type, String base) {
super(type, base);
}
/**
* Set the catalog attribute. If the value of the catalog attribute is relative, it
* must be made absolute with respect to the base URI currently in effect.
*
* @param catalog The catalog attribute value.
* @throws CatalogException if converting to catalog URI failed
*/
void setCatalog(String catalog) {
URL url = verifyURI("catalog", baseURI, catalog);
try {
catalogURI = url.toURI();
} catch (URISyntaxException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
}
}
/**
* Returns the catalog attribute as an URI String.
* @return The value of the catalog attribute
*/
String getCatalogId() {
return catalogURI.toASCIIString();
}
/**
* Returns the catalog attribute as an URI.
* @return The value of the catalog attribute
*/
URI getCatalogURI() {
return catalogURI;
}
/**
* Matches the specified id with the entry. Returns the match if it
* is successful and the length of the start String is longer than the
* longest of any previous match.
*
* @param id The id to be matched.
* @param currentMatch The length of start String of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
public URI matchURI(String id, int currentMatch) {
return null;
}
}

@ -0,0 +1,275 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.util.Objects;
import jdk.xml.internal.SecuritySupport;
/**
* Represents a general Catalog entry.
*
* @since 9
*/
abstract class BaseEntry {
final String SLASH = "/";
CatalogEntryType type;
//The id attribute
String id;
//The attribute to be matched, e.g. systemId
String matchId;
//The baseURI attribute
URL baseURI;
//Indicates whether the base attribute is specified
boolean baseSpecified = false;
/**
* CatalogEntryType represents catalog entry types.
*/
static enum CatalogEntryType {
CATALOG("catalogfile"),
CATALOGENTRY("catalog"),
GROUP("group"),
PUBLIC("public"),
SYSTEM("system"),
REWRITESYSTEM("rewriteSystem"),
SYSTEMSUFFIX("systemSuffix"),
DELEGATEPUBLIC("delegatePublic"),
DELEGATESYSTEM("delegateSystem"),
URI("uri"),
REWRITEURI("rewriteURI"),
URISUFFIX("uriSuffix"),
DELEGATEURI("delegateURI"),
NEXTCATALOG("nextCatalog");
final String literal;
CatalogEntryType(String literal) {
this.literal = literal;
}
public boolean isType(String type) {
return literal.equals(type);
}
static public CatalogEntryType getType(String entryType) {
for (CatalogEntryType type : CatalogEntryType.values()) {
if (type.isType(entryType)) {
return type;
}
}
return null;
}
}
/**
* Constructs a CatalogEntry
*
* @param type The type of the entry
*/
public BaseEntry(CatalogEntryType type) {
this.type = Objects.requireNonNull(type);
}
/**
* Constructs a CatalogEntry
*
* @param type The type of the entry
* @param base The base URI
*/
public BaseEntry(CatalogEntryType type, String base) {
this.type = Objects.requireNonNull(type);
setBaseURI(base);
}
/**
* Returns the type of the entry
*
* @return The type of the entry
*/
public CatalogEntryType getType() {
return type;
}
/**
* Sets the entry type
*
* @param type The entry type
*/
public void setType(CatalogEntryType type) {
this.type = type;
}
/**
* Returns the id of the entry
*
* @return The id of the entry
*/
public String getId() {
return id;
}
/**
* Set the entry Id
*
* @param id The Id attribute
*/
public void setId(String id) {
this.id = id;
}
/**
* Sets the base URI for the entry
*
* @param base The base URI
*/
public final void setBaseURI(String base) {
baseURI = verifyURI("base", null, base);
}
/**
* Gets the base URI for the entry
*
* @return The base URI as a string.
*/
public URL getBaseURI() {
return baseURI;
}
/**
* Gets the attribute used for matching
*
* @return The value of the field
*/
public String getMatchId() {
return matchId;
}
/**
* Sets the matchId field
* @param matchId The value of the Id
*/
public void setMatchId(String matchId) {
this.matchId = matchId;
}
/**
* Matches the specified string with the identifier attribute of the entry.
*
* @param match The identifier attribute to be matched
* @return The replacement URI if a matching entry is found, null if not.
*/
public String match(String match) {
return null;
}
/**
* Try to match the specified id with the entry. Return the match if it
* is successful and the length of the start String is longer than the
* longest of any previous match.
*
* @param id The id to be matched.
* @param currentMatch The length of start String of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
public String match(String id, int currentMatch) {
return null;
}
/**
* Verifies the specified URI.
*
* @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
*/
URL verifyURI(String arg, URL base, String uri) {
if (uri == null) {
CatalogMessages.reportIAE(new Object[]{uri, arg}, null);
}
URL url = null;
uri = Normalizer.normalizeURI(uri);
try {
if (base != null) {
url = new URL(base, uri);
} else {
url = new URL(uri);
}
} catch (MalformedURLException e) {
CatalogMessages.reportIAE(new Object[]{uri, arg}, e);
}
return url;
}
/**
* Replace backslashes with forward slashes. (URLs always use forward
* slashes.)
*
* @param sysid The input system identifier.
* @return The same system identifier with backslashes turned into forward
* slashes.
*/
protected String fixSlashes(String sysid) {
return sysid.replace('\\', '/');
}
/**
* 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 = 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;
}
}
}

@ -0,0 +1,156 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.util.stream.Stream;
/**
* The Catalog class represents an entity Catalog as defined by
* <a
* href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
* XML Catalogs, OASIS Standard V1.1, 7 October 2005</a>.
* <p>
* A catalog is an XML file that contains a root {@code catalog} entry with a list
* of catalog entries. The entries can also be grouped with a {@code group} entry.
* The catalog and group entries may specify {@code prefer} and {@code xml:base}
* attributes that set preference of public or system type of entries and base URI
* to resolve relative URIs.
*
* <p>
* A catalog can be used in two situations:
* <ul>
* <li>Locate the replacement text for an external entity;
* </li>
* <li>Locate an alternate URI reference for a resource.
* </li>
* </ul>
* <p>
* For case 1, the standard defines 6 External Identifier Entries:<br>
* {@code public, system, rewriteSystem, systemSuffix, delegatePublic, and
* delegateSystem}.
* <p>
* While for case 2, it defines 4 URI Entries:<br>
* {@code uri, rewriteURI, uriSuffix and delegateURI}.
* <p>
* In addition to the above entry types, a catalog may define nextCatalog
* entries to add additional catalog entry files.
* <p>
*
* @since 9
*/
public interface Catalog {
/**
* Attempts to find a matching entry in the catalog by systemId.
*
* <p>
* The method searches through the system-type entries, including {@code system,
* rewriteSystem, systemSuffix, delegateSystem}, and {@code group} entries in the
* current catalog in order to find a match.
* <p>
* Resolution follows the steps listed below: <br>
* <ul>
* <li>If a matching {@code system} entry exists, it is returned immediately.</li>
* <li>If more than one {@code rewriteSystem} entry matches, the matching entry with
* the longest normalized {@code systemIdStartString} value is returned.</li>
* <li>If more than one {@code systemSuffix} entry matches, the matching entry
* with the longest normalized {@code systemIdSuffix} value is returned.</li>
* <li>If more than one {@code delegateSystem} entry matches, the matching entry
* with the longest matching {@code systemIdStartString} value is returned.</li>
* </ul>
*
* @param systemId the system identifier of the entity to be matched
*
* @return an URI string if a mapping is found, or null otherwise
*/
public String matchSystem(String systemId);
/**
* Attempts to find a matching entry in the catalog by publicId. The method
* searches through the public-type entries, including {@code public,
* delegatePublic}, and {@code group} entries in the current catalog in order to find
* a match.
* <p>
* Refer to the description about <a href="CatalogFeatures.html#PREFER">
* Feature PREFER in the table Catalog Features</a> in class
* {@link CatalogFeatures}. Public entries are only considered if the
* {@code prefer} is {@code public} and {@code system} entries are not found.
* <p>
* Resolution follows the steps listed below: <br>
* <ul>
* <li>If a matching {@code public} entry is found, it is returned immediately.</li>
* <li>If more than one {@code delegatePublic} entry matches, the matching entry
* with the longest matching {@code publicIdStartString} value is returned.</li>
* </ul>
*
* @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
*/
public String matchPublic(String publicId);
/**
* Attempts to find a matching entry in the catalog by the uri element.
*
* <p>
* The method searches through the uri-type entries, including {@code uri,
* rewriteURI, uriSuffix, delegateURI} and {@code group} entries in the current
* catalog in order to find a match.
*
* <p>
* Resolution follows the steps listed below: <br>
* <ul>
* <li>If a matching {@code uri} entry is found, it is returned immediately.</li>
* <li>If more than one {@code rewriteURI} entry matches, the matching entry with
* the longest normalized {@code uriStartString} value is returned.</li>
* <li>If more than one {@code uriSuffix} entry matches, the matching entry with
* the longest normalized {@code uriSuffix} value is returned.</li>
* <li>If more than one {@code delegatePublic} entry matches, the matching entry
* with the longest matching {@code uriStartString} value is returned.</li>
* </ul>
*
* @param uri the URI reference of the entity to be matched
*
* @return an URI string if a mapping is found, or null otherwise
*/
public String matchURI(String uri);
/**
* Returns a sequential Stream of alternative Catalogs specified using the
* {@code nextCatalog} entries in the current catalog, and as the input of
* catalog files excluding the current catalog (that is, the first in the
* input list) when the Catalog object is created by the {@link CatalogManager}.
* <p>
* The order of Catalogs in the returned stream is the same as the order
* in which the corresponding {@code nextCatalog} entries appear in the
* current catalog. The alternative catalogs from the input file list are
* appended to the end of the stream in the order they are entered.
*
* @return a sequential Stream of Catalogs
*/
public Stream<Catalog> catalogs();
}

@ -0,0 +1,50 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
/**
* Represents the catalog element or entry of a catalog file
*
* @since 9
*/
class CatalogEntry extends GroupEntry {
/**
* Construct a catalog entry.
*
* @param base The baseURI attribute
* @param attributes The attributes
*/
public CatalogEntry(String base, String... attributes) {
super(base, attributes);
setType(CatalogEntryType.CATALOGENTRY);
}
@Override
public String match(String match) {
throw new UnsupportedOperationException("Unsupported operation.");
}
}

@ -0,0 +1,61 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
/**
* The exception class handles errors that may happen while processing or using
* a catalog.
*
* @since 9
*/
public class CatalogException extends RuntimeException {
private static final long serialVersionUID = 653231525876459057L;
/**
* Constructs a new CatalogException with the specified detail message. The
* cause is not initialized, and may subsequently be initialized by a call
* to {@link #initCause}.
*
* @param message the detail message
*/
public CatalogException(String message) {
super(message);
}
/**
* Constructs a new CatalogException with the specified detail message and
* cause.
*
* @param message the detail message (which is saved for later retrieval by
* the {@link #getMessage()} method)
* @param cause the cause (which is saved for later retrieval by the
* {@link #getCause()} method). (A {@code null} value is permitted, and
* indicates that the cause is nonexistent or unknown.)
*/
public CatalogException(String message, Throwable cause) {
super(message, cause);
}
}

@ -0,0 +1,534 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import jdk.xml.internal.SecuritySupport;
/**
* The CatalogFeatures holds a collection of features and properties.
* <p>
*
* <center><h2><a name="CatalogFeatures">Catalog Features</a></h2></center></p>
*
* <table border="1">
* <thead>
* <tr>
* <th rowspan="2">Feature</th>
* <th rowspan="2">Description</th>
* <th rowspan="2">Property Name</th>
* <th rowspan="2">System Property [1]</th>
* <th rowspan="2">jaxp.properties [1]</th>
* <th colspan="2" align="center">Value [2]</th>
* <th rowspan="2">Action</th>
* </tr>
* <tr>
* <th>Type</th>
* <th>Value</th>
* </tr>
* </thead>
* <tbody>
*
* <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>
* <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>
* Reads the first catalog as the current catalog; Loads others if no match
* is found in the current catalog including delegate catalogs if any.
* </td>
* </tr>
*
* <tr>
* <td rowspan="2"><a name="PREFER">PREFER</a></td>
* <td rowspan="2">Indicates the preference between the public and system
* identifiers. The default value is public [3].</td>
* <td rowspan="2">javax.xml.catalog.prefer</td>
* <td rowspan="2">N/A</td>
* <td rowspan="2">N/A</td>
* <td rowspan="2">String</td>
* <td>{@code system}</td>
* <td>Searches system entries for a match; Searches public entries when
* external identifier specifies only a public identifier</td>
* </tr>
* <tr>
* <td>{@code public}</td>
* <td>Searches system entries for a match; Searches public entries when
* there is no matching system entry.</td>
* </tr>
*
* <tr>
* <td rowspan="2"><a name="DEFER">DEFER</a></td>
* <td rowspan="2">Indicates that the alternative catalogs including those
* specified in delegate entries or nextCatalog are not read until they are
* needed. The default value is true.</td>
* <td rowspan="2">javax.xml.catalog.defer [4]</td>
* <td rowspan="2">javax.xml.catalog.defer</td>
* <td rowspan="2">javax.xml.catalog.defer</td>
* <td rowspan="2">String</td>
* <td>{@code true}</td>
* <td>Loads alternative catalogs as needed.
* </td>
* </tr>
* <tr>
* <td>{@code false}</td>
* <td>Loads all catalogs[5]. </td>
* </tr>
*
* <tr>
* <td rowspan="3"><a name="RESOLVE">RESOLVE</a></td>
* <td rowspan="3">Determines the action if there is no matching entry found after
* all of the specified catalogs are exhausted. The default is strict.</td>
* <td rowspan="3">javax.xml.catalog.resolve [4]</td>
* <td rowspan="3">javax.xml.catalog.resolve</td>
* <td rowspan="3">javax.xml.catalog.resolve</td>
* <td rowspan="3">String</td>
* <td>{@code strict}</td>
* <td>Throws CatalogException if there is no match.
* </td>
* </tr>
* <tr>
* <td>{@code continue}</td>
* <td>Allows the XML parser to continue as if there is no match.
* </td>
* </tr>
* <tr>
* <td>{@code ignore}</td>
* <td>Tells the XML parser to skip the external references if there no match.
* </td>
* </tr>
*
* </tbody>
* </table>
* <p>
* <b>[1]</b> There is no System property for the features that marked as "N/A".
*
* <p>
* <b>[2]</b> The value shall be exactly as listed in this table, case-sensitive.
* Any unspecified value will result in {@link IllegalArgumentException}.
* <p>
* <b>[3]</b> The Catalog specification defined complex rules on
* <a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html#attrib.prefer">
* the prefer attribute</a>. Although the prefer can be public or system, the
* specification actually made system the preferred option, that is, no matter
* the option, a system entry is always used if found. Public entries are only
* considered if the prefer is public and system entries are not found. It is
* therefore recommended that the prefer attribute be set as public
* (which is the default).
* <p>
* <b>[4]</b> Although non-standard attributes in the OASIS Catalog specification,
* {@code defer} and {@code resolve} are recognized by the Java Catalog API the
* same as the {@code prefer} as being an attribute in the catalog entry of the
* main catalog. Note that only the attributes specified for the catalog entry
* of the main Catalog file will be used.
* <p>
* <b>[5]</b> If the intention is to share an entire catalog store, it may be desirable to
* set the property {@code javax.xml.catalog.defer} to false to allow the entire
* catalog to be pre-loaded.
* <p>
* <h3>Scope and Order</h3>
* Features and properties can be set through the catalog file, the Catalog API,
* system properties, and {@code jaxp.properties}, with a preference in the same order.
* <p>
* Properties that are specified as attributes in the catalog file for the
* catalog and group entries shall take preference over any of the other settings.
* For example, if a {@code prefer} attribute is set in the catalog file as in
* {@code <catalog prefer="public">}, any other input for the "prefer" property
* is not necessary or will be ignored.
* <p>
* 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
* of the {@link CatalogManager} will override any that may have been entered
* through the {@link Builder}.
*
* <p>
* System properties when set shall override those in {@code jaxp.properties}.
* <p>
* The {@code jaxp.properties} file is typically in the conf directory of the Java
* installation. The file is read only once by the JAXP implementation and
* its values are then cached for future use. If the file does not exist
* when the first attempt is made to read from it, no further attempts are
* made to check for its existence. It is not possible to change the value
* of any properties in {@code jaxp.properties} after it has been read.
* <p>
* A CatalogFeatures instance can be created through its builder as illustrated
* in the following sample code:
* <pre>{@code
CatalogFeatures f = CatalogFeatures.builder()
.with(Feature.FILES, "catalog.xml")
.with(Feature.PREFER, "public")
.with(Feature.DEFER, "true")
.with(Feature.RESOLVE, "ignore")
.build();
* }</pre>
*
* @since 9
*/
public class CatalogFeatures {
/**
* The constant name of the javax.xml.catalog.files property. See the property table for more details.
*/
static final String CATALOG_FILES = "javax.xml.catalog.files";
/**
* The javax.xml.catalog.prefer property. See the property table for more details.
*/
static final String CATALOG_PREFER = "javax.xml.catalog.prefer";
/**
* Determines whether or not delegated catalogs and nextCatalog will be read
* when the current catalog is loaded.
*/
static final String CATALOG_DEFER = "javax.xml.catalog.defer";
/**
* Determines the action if there is no matching entry found after
* all of the specified catalogs are exhausted.
*/
static final String CATALOG_RESOLVE = "javax.xml.catalog.resolve";
//values for the prefer property
static final String PREFER_SYSTEM = "system";
static final String PREFER_PUBLIC = "public";
//values for the defer property
static final String DEFER_TRUE = "true";
static final String DEFER_FALSE = "false";
//values for the Resolve property
static final String RESOLVE_STRICT = "strict";
static final String RESOLVE_CONTINUE = "continue";
static final String RESOLVE_IGNORE = "ignore";
/**
* A Feature type as defined in the
* <a href="CatalogFeatures.html#CatalogFeatures">Catalog Features table</a>.
*/
public static enum Feature {
/**
* The {@code javax.xml.catalog.files} property as described in
* item <a href="CatalogFeatures.html#FILES">FILES</a> of the
* Catalog Features table.
*/
FILES(CATALOG_FILES, null, true),
/**
* The {@code javax.xml.catalog.prefer} property as described in
* item <a href="CatalogFeatures.html#PREFER">PREFER</a> of the
* Catalog Features table.
*/
PREFER(CATALOG_PREFER, PREFER_PUBLIC, false),
/**
* The {@code javax.xml.catalog.defer} property as described in
* item <a href="CatalogFeatures.html#DEFER">DEFER</a> of the
* Catalog Features table.
*/
DEFER(CATALOG_DEFER, DEFER_TRUE, true),
/**
* The {@code javax.xml.catalog.resolve} property as described in
* item <a href="CatalogFeatures.html#RESOLVE">RESOLVE</a> of the
* Catalog Features table.
*/
RESOLVE(CATALOG_RESOLVE, RESOLVE_STRICT, true);
private final String name;
private final String defaultValue;
private String value;
private final boolean hasSystem;
/**
* Constructs a CatalogFeature instance.
* @param name the name of the feature
* @param value the value of the feature
* @param hasSystem a flag to indicate whether the feature is supported
* with a System property
*/
Feature(String name, String value, boolean hasSystem) {
this.name = name;
this.defaultValue = value;
this.hasSystem = hasSystem;
}
/**
* Checks whether the specified property is equal to the current property.
* @param propertyName the name of a property
* @return true if the specified property is the current property, false
* otherwise
*/
boolean equalsPropertyName(String propertyName) {
return name.equals(propertyName);
}
/**
* Returns the name of the corresponding System Property.
*
* @return the name of the System Property
*/
public String getPropertyName() {
return name;
}
/**
* Returns the default value of the property.
* @return the default value of the property
*/
String defaultValue() {
return defaultValue;
}
/**
* Returns the value of the property.
* @return the value of the property
*/
String getValue() {
return value;
}
/**
* Checks whether System property is supported for the feature.
* @return true it is supported, false otherwise
*/
boolean hasSystemProperty() {
return hasSystem;
}
}
/**
* States of the settings of a property, in the order: default value,
* jaxp.properties file, jaxp system properties, and jaxp api properties
*/
static enum State {
/** represents the default state of a feature. */
DEFAULT("default"),
/** indicates the value of the feature is read from jaxp.properties. */
JAXPDOTPROPERTIES("jaxp.properties"),
/** indicates the value of the feature is read from its System property. */
SYSTEMPROPERTY("system property"),
/** indicates the value of the feature is specified through the API. */
APIPROPERTY("property"),
/** indicates the value of the feature is specified as a catalog attribute. */
CATALOGATTRIBUTE("catalog attribute");
final String literal;
State(String literal) {
this.literal = literal;
}
String literal() {
return literal;
}
}
/**
* Values of the properties
*/
private String[] values;
/**
* States of the settings for each property
*/
private State[] states;
/**
* Private class constructor
*/
private CatalogFeatures() {
}
/**
* Returns a CatalogFeatures instance with default settings.
* @return a default CatalogFeatures instance
*/
public static CatalogFeatures defaults() {
return CatalogFeatures.builder().build();
}
/**
* Constructs a new CatalogFeatures instance with the builder.
*
* @param builder the builder to build the CatalogFeatures
*/
CatalogFeatures(Builder builder) {
init();
setProperty(Feature.FILES.ordinal(), State.APIPROPERTY, builder.files);
setProperty(Feature.PREFER.ordinal(), State.APIPROPERTY, builder.prefer);
setProperty(Feature.DEFER.ordinal(), State.APIPROPERTY, builder.defer);
setProperty(Feature.RESOLVE.ordinal(), State.APIPROPERTY, builder.resolve);
}
/**
* Returns the value of the specified feature.
*
* @param cf the type of the Catalog feature
* @return the value of the feature
*/
public String get(Feature cf) {
return values[cf.ordinal()];
}
/**
* Initializes the supported properties
*/
private void init() {
values = new String[Feature.values().length];
states = new State[Feature.values().length];
for (Feature cf : Feature.values()) {
setProperty(cf.ordinal(), State.DEFAULT, cf.defaultValue());
}
//read system properties or jaxp.properties
readSystemProperties();
}
/**
* Sets the value of a property by its index, 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) {
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);
}
}
if (states[index] == null || state.compareTo(states[index]) >= 0) {
values[index] = value;
states[index] = state;
}
}
}
/**
* Reads from system properties, or those in jaxp.properties
*/
private void readSystemProperties() {
for (Feature cf : Feature.values()) {
getSystemProperty(cf, cf.getPropertyName());
}
}
/**
* Reads from system properties, or those in jaxp.properties
*
* @param cf the type of the property
* @param sysPropertyName the name of system property
*/
private boolean getSystemProperty(Feature cf, String sysPropertyName) {
if (cf.hasSystemProperty()) {
String value = SecuritySupport.getSystemProperty(sysPropertyName);
if (value != null && !value.equals("")) {
setProperty(cf.ordinal(), State.SYSTEMPROPERTY, value);
return true;
}
value = SecuritySupport.readJAXPProperty(sysPropertyName);
if (value != null && !value.equals("")) {
setProperty(cf.ordinal(), State.JAXPDOTPROPERTIES, value);
return true;
}
}
return false;
}
/**
* Returns an instance of the builder for creating the CatalogFeatures object.
*
* @return an instance of the builder
*/
public static Builder builder() {
return new CatalogFeatures.Builder();
}
/**
* The Builder class for building the CatalogFeatures object.
*/
public static class Builder {
/**
* Variables for the features supported by CatalogFeatures.
*/
String files, prefer, defer, resolve;
/**
* Instantiation of Builder is not allowed.
*/
private Builder() {}
/**
* Sets the value to a specified Feature.
* @param feature the Feature to be set
* @param value the value to be set for the Feature
* @return this Builder instance
* @throws IllegalArgumentException if the value is not valid for the
* Feature or has the wrong syntax for the {@code javax.xml.catalog.files}
* property
*/
public Builder with(Feature feature, String value) {
switch (feature) {
case FILES :
files = value;
break;
case PREFER :
prefer = value;
break;
case DEFER :
defer = value;
break;
case RESOLVE :
resolve = value;
break;
}
return this;
}
/**
* Returns a CatalogFeatures object built by this builder.
*
* @return an instance of CatalogFeatures
*/
public CatalogFeatures build() {
return new CatalogFeatures(this);
}
}
}

@ -0,0 +1,506 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
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.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.NoSuchElementException;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import static javax.xml.catalog.BaseEntry.CatalogEntryType;
import static javax.xml.catalog.CatalogFeatures.DEFER_TRUE;
import javax.xml.catalog.CatalogFeatures.Feature;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.SAXException;
/**
* Implementation of the Catalog.
*
* @since 9
*/
class CatalogImpl extends GroupEntry implements Catalog {
//Catalog level, 0 means the top catalog
int level = 0;
//Value of the defer attribute to determine if alternative catalogs are read
boolean isDeferred = true;
//Value of the resolve attribute
ResolveType resolveType = ResolveType.STRICT;
//indicate whether the Catalog is empty
boolean isEmpty;
//Current parsed Catalog
int current = 0;
//System Id for this catalog
String systemId;
//The parent
CatalogImpl parent = null;
/*
A list of catalog entry files from the input, excluding the current catalog.
Paths in the List are normalized.
*/
List<String> inputFiles;
//A list of catalogs specified using the nextCatalog element
List<NextCatalog> nextCatalogs;
//reuse the parser
SAXParser parser;
/**
* Construct a Catalog with specified path.
*
* @param file The path to a catalog file.
* @throws CatalogException If an error happens while parsing the specified
* catalog file.
*/
public CatalogImpl(CatalogFeatures f, String... file) throws CatalogException {
this(null, f, file);
}
/**
* Construct a Catalog with specified path.
*
* @param parent The parent catalog
* @param file The path to a catalog file.
* @throws CatalogException If an error happens while parsing the specified
* catalog file.
*/
public CatalogImpl(CatalogImpl parent, CatalogFeatures f, String... file) throws CatalogException {
super(CatalogEntryType.CATALOG);
this.parent = parent;
if (parent == null) {
level = 0;
} else {
level = parent.level + 1;
}
if (f == null) {
this.features = CatalogFeatures.defaults();
} else {
this.features = f;
}
setPrefer(features.get(Feature.PREFER));
setDeferred(features.get(Feature.DEFER));
setResolve(features.get(Feature.RESOLVE));
//Path of catalog files
String[] catalogFile = file;
if (level == 0
&& (file == null || (file.length == 0 || file[0] == null))) {
String files = features.get(Feature.FILES);
if (files != null) {
catalogFile = files.split(";[ ]*");
}
}
/*
In accordance with 8. Resource Failures of the Catalog spec, missing
Catalog entry files are to be ignored.
*/
if ((catalogFile != null && catalogFile.length > 0)) {
int start = 0;
URI uri = null;
for (String temp : catalogFile) {
uri = getSystemId(temp);
start++;
if (verifyCatalogFile(uri)) {
systemId = uri.toASCIIString();
break;
}
}
//Save the rest of input files as alternative catalogs
if (level == 0 && catalogFile.length > start) {
inputFiles = new ArrayList<>();
for (int i = start; i < catalogFile.length; i++) {
if (catalogFile[i] != null) {
inputFiles.add(catalogFile[i]);
}
}
}
if (systemId != null) {
parse(systemId);
}
}
}
/**
* Resets the Catalog instance to its initial state.
*/
@Override
public void reset() {
super.reset();
current = 0;
if (level == 0) {
catalogsSearched.clear();
}
entries.stream().filter((entry) -> (entry.type == CatalogEntryType.GROUP)).forEach((entry) -> {
((GroupEntry) entry).reset();
});
if (parent != null) {
this.loadedCatalogs = parent.loadedCatalogs;
this.catalogsSearched = parent.catalogsSearched;
}
}
/**
* Returns whether this Catalog instance is the top (main) Catalog.
*
* @return true if the instance is the top Catalog, false otherwise
*/
boolean isTop() {
return level == 0;
}
/**
* Gets the parent of this catalog.
*
* @returns The parent catalog
*/
public Catalog getParent() {
return this.parent;
}
/**
* Sets the defer property. If the value is null or empty, or any String
* other than the defined, it will be assumed as the default value.
*
* @param value The value of the defer attribute
*/
public final void setDeferred(String value) {
isDeferred = DEFER_TRUE.equals(value);
}
/**
* Queries the defer attribute
*
* @return true if the prefer attribute is set to system, false if not.
*/
public boolean isDeferred() {
return isDeferred;
}
/**
* Sets the resolve property. If the value is null or empty, or any String
* other than the defined, it will be assumed as the default value.
*
* @param value The value of the resolve attribute
*/
public final void setResolve(String value) {
resolveType = ResolveType.getType(value);
}
/**
* Gets the value of the resolve attribute
*
* @return The value of the resolve attribute
*/
public final ResolveType getResolve() {
return resolveType;
}
/**
* Marks the Catalog as being searched already.
*/
void markAsSearched() {
catalogsSearched.add(systemId);
}
/**
* Parses the catalog.
*
* @param systemId The systemId of the catalog
* @throws CatalogException if parsing the catalog failed
*/
private void parse(String systemId) {
if (parser == null) {
parser = getParser();
}
try {
CatalogReader reader = new CatalogReader(this, parser);
parser.parse(systemId, reader);
} catch (SAXException | IOException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSING_FAILED, ex);
}
}
/**
* 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) {
URL filepath;
if (file != null && file.length() > 0) {
try {
File f = new File(file);
if (baseURI != null && !f.isAbsolute()) {
filepath = new URL(baseURI, fixSlashes(file));
return filepath.toURI();
} else {
return resolveURI(file);
}
} catch (MalformedURLException | URISyntaxException e) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_INVALID_PATH,
new Object[]{file}, e);
}
}
return null;
}
/**
* Resolves the specified uri. If the uri is relative, makes it absolute by
* the user.dir directory.
*
* @param uri The specified URI.
* @return The resolved URI
*/
private URI resolveURI(String uri) throws MalformedURLException {
if (uri == null) {
uri = "";
}
URI temp = toURI(uri);
String str = temp.toASCIIString();
String base = str.substring(0, str.lastIndexOf('/') + 1);
baseURI = new URL(str);
return temp;
}
/**
* Converts an URI string or file path to URI.
*
* @param uri an URI string or file path
* @return an URI
*/
private URI toURI(String uri) {
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;
}
/**
* Returns a SAXParser instance
* @return a SAXParser instance
* @throws CatalogException if constructing a SAXParser failed
*/
private SAXParser getParser() {
SAXParser p = null;
try {
SAXParserFactory spf = new SAXParserFactoryImpl();
spf.setNamespaceAware(true);
spf.setValidating(false);
spf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
p = spf.newSAXParser();
} catch (ParserConfigurationException | SAXException e) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSING_FAILED, e);
}
return p;
}
/**
* Indicate that the catalog is empty
*
* @return True if the catalog is empty; False otherwise.
*/
public boolean isEmpty() {
return isEmpty;
}
@Override
public Stream<Catalog> catalogs() {
Iterator<Catalog> iter = new Iterator<Catalog>() {
Catalog nextCatalog = null;
//Current index of the input files
int inputFilesIndex = 0;
//Next catalog
int nextCatalogIndex = 0;
@Override
public boolean hasNext() {
if (nextCatalog != null) {
return true;
} else {
nextCatalog = nextCatalog();
return (nextCatalog != null);
}
}
@Override
public Catalog next() {
if (nextCatalog != null || hasNext()) {
Catalog catalog = nextCatalog;
nextCatalog = null;
return catalog;
} else {
throw new NoSuchElementException();
}
}
/**
* Returns the next alternative catalog.
*
* @return the next catalog if any
*/
private Catalog nextCatalog() {
Catalog c = null;
//Check those specified in nextCatalogs
if (nextCatalogs != null) {
while (c == null && nextCatalogIndex < nextCatalogs.size()) {
c = getCatalog(nextCatalogs.get(nextCatalogIndex++).getCatalogURI());
}
}
//Check the input list
if (c == null && inputFiles != null) {
while (c == null && inputFilesIndex < inputFiles.size()) {
c = getCatalog(getSystemId(inputFiles.get(inputFilesIndex++)));
}
}
return c;
}
};
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
iter, Spliterator.ORDERED | Spliterator.NONNULL), false);
}
/**
* Adds the catalog to the nextCatalog list
*
* @param catalog a catalog specified in a nextCatalog entry
*/
void addNextCatalog(NextCatalog catalog) {
if (catalog == null) {
return;
}
if (nextCatalogs == null) {
nextCatalogs = new ArrayList<>();
}
nextCatalogs.add(catalog);
}
/**
* Loads all alternative catalogs.
*/
void loadNextCatalogs() {
//loads catalogs specified in nextCatalogs
if (nextCatalogs != null) {
for (NextCatalog next : nextCatalogs) {
getCatalog(next.getCatalogURI());
}
}
//loads catalogs from the input list
if (inputFiles != null) {
for (String file : inputFiles) {
getCatalog(getSystemId(file));
}
}
}
/**
* Returns a Catalog object by the specified path.
*
* @param path the path to a catalog
* @return a Catalog object
*/
Catalog getCatalog(URI uri) {
if (uri == null) {
return null;
}
Catalog c = null;
String path = uri.toASCIIString();
if (verifyCatalogFile(uri)) {
c = getLoadedCatalog(path);
if (c == null) {
c = new CatalogImpl(this, features, path);
saveLoadedCatalog(path, c);
}
}
return c;
}
/**
* Saves a loaded Catalog.
*
* @param catalogId the catalogId associated with the Catalog object
* @param c the Catalog to be saved
*/
void saveLoadedCatalog(String catalogId, Catalog c) {
loadedCatalogs.put(catalogId, c);
}
/**
* Returns a count of all loaded catalogs, including delegate catalogs.
*
* @return a count of all loaded catalogs
*/
int loadedCatalogCount() {
return loadedCatalogs.size() + delegateCatalogs.size();
}
}

@ -0,0 +1,132 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
/**
* The Catalog Manager manages the creation of XML Catalogs and Catalog Resolvers.
*
* @since 9
*/
public final class CatalogManager {
/**
* Creating CatalogManager instance is not allowed.
*/
private CatalogManager() {
}
/**
* Creates a Catalog object using the specified feature settings and path to
* a catalog file. If the features is null, the default features will be used.
* If the path is empty, System property {@code javax.xml.catalog.files} will
* be read to locate the initial list of catalog files.
* <p>
* If more than one catalog files are specified through the path 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.
*
* @param features the catalog features
* @param path path(s) to one or more catalogs.
*
* @return a catalog instance
* @throws CatalogException If no catalog can be found whether through the
* specified path or the System property {@code javax.xml.catalog.files}, or
* an error occurs while parsing the catalog
*/
public static Catalog catalog(CatalogFeatures features, String... path) {
return new CatalogImpl(features, path);
}
/**
* Creates an instance of a CatalogResolver using the specified catalog.
*
* @param catalog the catalog instance
* @return an instance of a CatalogResolver
*/
public static CatalogResolver catalogResolver(Catalog catalog) {
if (catalog == null) CatalogMessages.reportNPEOnNull("catalog", null);
return new CatalogResolverImpl(catalog);
}
/**
* Creates an instance of a CatalogUriResolver using the specified catalog.
*
* @param catalog the catalog instance
* @return an instance of a CatalogResolver
*/
public static CatalogUriResolver catalogUriResolver(Catalog catalog) {
if (catalog == null) CatalogMessages.reportNPEOnNull("catalog", null);
return new CatalogUriResolverImpl(catalog);
}
/**
* Creates an instance of a CatalogResolver using the specified feature settings
* and path to a catalog file. If the features is null, the default features will
* be used. If the path is empty, System property {@code javax.xml.catalog.files}
* will be read to locate the initial list of catalog files.
* <p>
* If more than one catalog files are specified through the path 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.
*
* @param features the catalog features
* @param path the path(s) to one or more catalogs
*
* @return an instance of a CatalogResolver
* @throws CatalogException If no catalog can be found whether through the
* specified path or the System property {@code javax.xml.catalog.files}, or
* an error occurs while parsing the catalog
*/
public static CatalogResolver catalogResolver(CatalogFeatures features, String... path) {
Catalog catalog = catalog(features, path);
return new CatalogResolverImpl(catalog);
}
/**
* Creates an instance of a CatalogUriResolver using the specified feature settings
* and path to a catalog file. If the features is null, the default features will
* be used. If the path is empty, System property {@code javax.xml.catalog.files}
* will be read to locate the initial list of catalog files.
* <p>
* If more than one catalog files are specified through the path 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.
*
* @param features the catalog features
* @param path the path(s) to one or more catalogs
*
* @return an instance of a CatalogResolver
* @throws CatalogException If no catalog can be found whether through the
* specified path or the System property {@code javax.xml.catalog.files}, or
* an error occurs while parsing the catalog
*/
public static CatalogUriResolver catalogUriResolver(CatalogFeatures features, String... path) {
Catalog catalog = catalog(features, path);
return new CatalogUriResolverImpl(catalog);
}
}

@ -0,0 +1,191 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import jdk.xml.internal.SecuritySupport;
import java.util.Locale;
import java.util.MissingResourceException;
import java.util.ResourceBundle;
/**
* Catalog Error messages
*
* @since 9
*/
final class CatalogMessages {
public static final String ERR_INVALID_CATALOG = "InvalidCatalog";
public static final String ERR_INVALID_ENTRY_TYPE = "InvalidEntryType";
public static final String ERR_INVALID_ARGUMENT = "InvalidArgument";
public static final String ERR_NULL_ARGUMENT = "NullArgument";
public static final String ERR_CIRCULAR_REFERENCE = "CircularReference";
public static final String ERR_INVALID_PATH = "InvalidPath";
public static final String ERR_PARSER_CONF = "ParserConf";
public static final String ERR_PARSING_FAILED = "ParsingFailed";
public static final String ERR_NO_CATALOG = "NoCatalogFound";
public static final String ERR_NO_MATCH = "NoMatchFound";
public static final String ERR_NO_URI_MATCH = "NoMatchURIFound";
public static final String ERR_CREATING_URI = "FailedCreatingURI";
public static final String ERR_OTHER = "OtherError";
static final String bundleName = CatalogMessages.class.getPackage().getName() + ".CatalogMessages";
static ResourceBundle resourceBundle;
/**
* Reports an error.
* @param key the message key
*/
static void reportError(String key) {
reportError(key, null);
}
/**
* Reports an error.
* @param key the message key
* @param arguments the message replacement text arguments. The order of the
* arguments must match that of the placeholders in the actual message.
*/
static void reportError(String key, Object[] arguments) {
throw new CatalogException(formatMessage(key, arguments));
}
/**
* Reports a CatalogException.
* @param key the message key
* @param arguments the message replacement text arguments. The order of the
* arguments must match that of the placeholders in the actual message.
*/
static void reportRunTimeError(String key, Object[] arguments) {
throw new CatalogException(formatMessage(key, arguments));
}
/**
* Reports a CatalogException.
* @param key the message key
* @param cause the cause if any
*/
static void reportRunTimeError(String key, Throwable cause) {
throw new CatalogException(formatMessage(key, null), cause);
}
/**
* Reports a CatalogException.
* @param key the message key
* @param arguments the message replacement text arguments. The order of the
* arguments must match that of the placeholders in the actual message.
* @param cause the cause if any
*/
static void reportRunTimeError(String key, Object[] arguments, Throwable cause) {
throw new CatalogException(formatMessage(key, arguments), cause);
}
/**
* Reports IllegalArgumentException if the argument is null.
*
* @param name the name of the argument
* @param value the value of the argument
*/
static void reportIAEOnNull(String name, String value) {
if (value == null) {
throw new IllegalArgumentException(
formatMessage(ERR_INVALID_ARGUMENT, new Object[]{null, name}));
}
}
/**
* Reports NullPointerException if the argument is null.
*
* @param name the name of the argument
* @param value the value of the argument
*/
static void reportNPEOnNull(String name, String value) {
if (value == null) {
throw new NullPointerException(
formatMessage(ERR_NULL_ARGUMENT, new Object[]{name}));
}
}
/**
* Reports IllegalArgumentException
* @param arguments the arguments for formating the error message
* @param cause the cause if any
*/
static void reportIAE(Object[] arguments, Throwable cause) {
throw new IllegalArgumentException(
formatMessage(ERR_INVALID_ARGUMENT, arguments), cause);
}
/**
* Format a message with the specified arguments using the default locale
* information.
*
* @param key the message key
* @param arguments the message replacement text arguments. The order of the
* arguments must match that of the placeholders in the actual message.
*
* @return the formatted message
*
* @throws MissingResourceException If the message with the specified key
* cannot be found
*/
static String formatMessage(String key, Object[] arguments) {
return formatMessage(key, arguments, Locale.getDefault());
}
/**
* Format a message with the specified arguments using the given locale
* information.
*
* @param key the message key
* @param arguments the message replacement text arguments. The order of the
* arguments must match that of the placeholders in the actual message.
* @param locale the locale of the message
*
* @return the formatted message
*
* @throws MissingResourceException If the message with the specified key
* cannot be found
*/
static String formatMessage(String key, Object[] arguments, Locale locale) {
return SecuritySupport.getErrorMessage(locale, bundleName, key, arguments);
}
/**
* Returns sanitized URI.
* @param uri an URI to be sanitized
*/
static String sanitize(String uri) {
if (uri == null) {
return null;
}
String temp;
int p;
p = uri.lastIndexOf("/");
if (p > 0 && p < uri.length()) {
return uri.substring(p + 1);
}
return uri;
}
}

@ -0,0 +1,43 @@
# Copyright (c) 2015, 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. Oracle designates this
# particular file as subject to the "Classpath" exception as provided
# by Oracle in the LICENSE file that accompanied this code.
#
# 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.
# Messages for message reporting
BadMessageKey = The error message corresponding to the message key can not be found.
FormatFailed = An internal error occurred while formatting the following message:\n
#invalid catalog file
InvalidCatalog = The document element of a catalog must be catalog.
InvalidEntryType = The entry type ''{0}'' is not valid.
CircularReference = Circular reference is not allowed: ''{0}''.
#errors
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.
ParserConf = Unexpected error while configuring a SAX parser.
ParsingFailed = Failed to parse the catalog file.
NoCatalogFound = No Catalog is specified.
NoMatchFound = No match found for publicId ''{0}'' and systemId ''{1}''.
NoMatchURIFound = No match found for href ''{0}'' and base ''{1}''.
FailedCreatingURI = Can not construct URI using href ''{0}'' and base ''{1}''.
OtherError = Unexpected error.

@ -0,0 +1,291 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 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;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;
import javax.xml.transform.sax.SAXSource;
import org.xml.sax.Attributes;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
/**
* CatalogReader handles SAX events while parsing through a catalog file to
* create a catalog object.
*
* @since 9
*/
class CatalogReader extends DefaultHandler implements EntityResolver, URIResolver {
/** URI of the W3C XML Schema for OASIS XML Catalog files. */
public static final String xmlCatalogXSD = "http://www.oasis-open.org/committees/entity/release/1.0/catalog.xsd";
/** Public identifier for OASIS XML Catalog files. */
public static final String xmlCatalogPubId = "-//OASIS//DTD XML Catalogs V1.0//EN";
/**
* The namespace name defined by the OASIS Standard
*/
public static final String NAMESPACE_OASIS = "urn:oasis:names:tc:entity:xmlns:xml:catalog";
//Indicate whether the root element has been found
boolean seenRoot;
//Indicate that the parser is in a group entry
boolean inGroup;
//The Catalog instance
CatalogImpl catalog;
//The parser for reading the catalog
SAXParser parser;
//The current catalog entry
CatalogEntry catalogEntry;
//The current group
GroupEntry group;
//The current entry
BaseEntry entry;
//remove this variable once 8136778 is committed
boolean ignoreTheCatalog = false;
/**
* Constructs an instance with a Catalog object and parser.
*
* @param catalog The Catalog object that represents a catalog
*/
@SuppressWarnings("unchecked")
public CatalogReader(Catalog catalog, SAXParser parser) {
this.catalog = (CatalogImpl) catalog;
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,
String qName,
Attributes atts)
throws SAXException {
//ignore the catalog if it's not compliant. See section 8, item 3 of the spec.
if (ignoreTheCatalog) return;
if (!NAMESPACE_OASIS.equals(namespaceURI)) {
//wait till 8136778 is committed
// parser.stop();
ignoreTheCatalog = true;
return;
}
CatalogEntryType type = CatalogEntryType.getType(localName);
if (type == null) {
CatalogMessages.reportError(CatalogMessages.ERR_INVALID_ENTRY_TYPE,
new Object[]{localName});
}
if (type != CatalogEntryType.CATALOGENTRY) {
if (!seenRoot) {
CatalogMessages.reportError(CatalogMessages.ERR_INVALID_CATALOG);
}
}
String base = atts.getValue("xml:base");
if (base == null) {
if (inGroup) {
base = group.getBaseURI().toString();
} else {
if (type == CatalogEntryType.CATALOGENTRY) {
base = catalog.getBaseURI().toString();
} else {
base = catalogEntry.getBaseURI().toString();
}
}
} else {
base = Normalizer.normalizeURI(base);
}
//parse the catalog and group entries
if (type == CatalogEntryType.CATALOGENTRY
|| type == CatalogEntryType.GROUP) {
String prefer = atts.getValue("prefer");
if (prefer == null) {
if (type == CatalogEntryType.CATALOGENTRY) {
//use the general setting
prefer = catalog.isPreferPublic() ?
CatalogFeatures.PREFER_PUBLIC : CatalogFeatures.PREFER_SYSTEM;
} else {
//Group inherit from the catalog entry
prefer = catalogEntry.isPreferPublic() ?
CatalogFeatures.PREFER_PUBLIC : CatalogFeatures.PREFER_SYSTEM;
}
}
if (type == CatalogEntryType.CATALOGENTRY) {
seenRoot = true;
if (catalog.isTop()) {
String defer = atts.getValue("defer");
String resolve = atts.getValue("resolve");
if (defer == null) {
defer = catalog.isDeferred() ?
CatalogFeatures.DEFER_TRUE : CatalogFeatures.DEFER_FALSE;
}
if (resolve == null) {
resolve = catalog.getResolve().literal;
}
catalog.setResolve(resolve);
catalogEntry = new CatalogEntry(base, prefer, defer, resolve);
} else {
catalogEntry = new CatalogEntry(base, prefer);
}
return;
} else {
inGroup = true;
group = new GroupEntry(catalog, base, prefer);
catalog.addEntry(group);
return;
}
}
//parse entries other than the catalog and group entries
switch (type) {
case PUBLIC:
entry = new PublicEntry(base, atts.getValue("publicId"), atts.getValue("uri"));
break;
case SYSTEM:
entry = new SystemEntry(base, atts.getValue("systemId"), atts.getValue("uri"));
break;
case REWRITESYSTEM:
entry = new RewriteSystem(base, atts.getValue("systemIdStartString"), atts.getValue("rewritePrefix"));
break;
case SYSTEMSUFFIX:
entry = new SystemSuffix(base, atts.getValue("systemIdSuffix"), atts.getValue("uri"));
break;
case DELEGATEPUBLIC:
entry = new DelegatePublic(base, atts.getValue("publicIdStartString"), atts.getValue("catalog"));
break;
case DELEGATESYSTEM:
entry = new DelegateSystem(base, atts.getValue("systemIdStartString"), atts.getValue("catalog"));
break;
case URI:
entry = new UriEntry(base, atts.getValue("name"), atts.getValue("uri"));
break;
case REWRITEURI:
entry = new RewriteUri(base, atts.getValue("uriStartString"), atts.getValue("rewritePrefix"));
break;
case URISUFFIX:
entry = new UriSuffix(base, atts.getValue("uriSuffix"), atts.getValue("uri"));
break;
case DELEGATEURI:
entry = new DelegateUri(base, atts.getValue("uriStartString"), atts.getValue("catalog"));
break;
case NEXTCATALOG:
entry = new NextCatalog(base, atts.getValue("catalog"));
break;
}
if (type == CatalogEntryType.NEXTCATALOG) {
catalog.addNextCatalog((NextCatalog) entry);
} else if (inGroup) {
group.addEntry(entry);
} else {
catalog.addEntry(entry);
}
}
/**
* Handles endElement event
*/
@Override
public void endElement(String namespaceURI, String localName, String qName)
throws SAXException {
if (ignoreTheCatalog) return;
CatalogEntryType type = CatalogEntryType.getType(localName);
if (type == CatalogEntryType.GROUP) {
inGroup = false;
} else if (type == CatalogEntryType.CATALOGENTRY) {
/*
Done reading the catalog file.
Load delegate and alternative catalogs if defer is false.
*/
if (!catalog.isDeferred()) {
catalog.loadDelegateCatalogs();
catalog.loadNextCatalogs();
}
}
}
/**
* Skips external DTD since resolving external DTD is not required
* by the specification.
*/
@Override
public InputSource resolveEntity(String publicId, String systemId) {
return new InputSource(new StringReader(""));
}
/**
* Skips external references since resolution is not required
* by the specification.
*/
@Override
public Source resolve(String href, String base)
throws TransformerException {
return new SAXSource(new InputSource(new StringReader("")));
}
}

@ -0,0 +1,73 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
/**
* A SAX EntityResolver that uses catalogs to resolve references.
*
* @since 9
*/
public interface CatalogResolver extends EntityResolver {
/**
* The method searches through the catalog entries in the main and
* alternative catalogs to attempt to find a match with the specified publicId
* or systemId.
* <p>
* For resolving external entities, system entries will be matched before
* the public entries.
* <p>
* <b>The {@code prefer} attribute</b>: if the {@code prefer} is public,
* and there is no match found through the system entries, public entries
* will be considered. If it is not specified, the {@code prefer} is public
* by default (Note that by the OASIS standard, system entries will always
* be considered first when the external system identifier is specified.
* Prefer public means that public entries will be matched when both system
* and public identifiers are specified. In general therefore, prefer
* public is recommended.)
*
* @param publicId the public identifier of the external entity being
* referenced, or null if none was supplied
*
* @param systemId the system identifier of the external entity being
* referenced. A system identifier is required on all external entities. XML
* requires a system identifier on all external entities, so this value is
* always specified.
*
* @return a {@link org.xml.sax.InputSource} object if a mapping is found. If no mapping is
* found, returns a {@link org.xml.sax.InputSource} object containing an empty
* {@link java.io.Reader} if the {@code javax.xml.catalog.resolve} property
* is set to {@code ignore}; returns null if the
* {@code javax.xml.catalog.resolve} property is set to {@code continue}.
*
* @throws CatalogException if no mapping is found and
* {@code javax.xml.catalog.resolve} is specified as strict
*/
@Override
public InputSource resolveEntity(String publicId, String systemId);
}

@ -0,0 +1,125 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.io.StringReader;
import java.util.Iterator;
import org.xml.sax.InputSource;
/**
* A SAX EntityResolver/JAXP URIResolver that uses catalogs.
*
* <p>
* This class implements both a SAX EntityResolver and a JAXP URIResolver.
*
*
* @since 9
*/
final class CatalogResolverImpl implements CatalogResolver {
Catalog catalog;
/**
* Construct an instance of the CatalogResolver from a Catalog.
*
* @param catalog A Catalog.
*/
public CatalogResolverImpl(Catalog catalog) {
this.catalog = catalog;
}
@Override
public InputSource resolveEntity(String publicId, String systemId) {
//Normalize publicId and systemId
systemId = Normalizer.normalizeURI(systemId);
publicId = Normalizer.normalizePublicId(Normalizer.decodeURN(publicId));
//check whether systemId is an urn
if (systemId != null && systemId.startsWith("urn:publicid:")) {
systemId = Normalizer.decodeURN(systemId);
if (publicId != null && !publicId.equals(systemId)) {
systemId = null;
} else {
publicId = systemId;
systemId = null;
}
}
CatalogImpl c = (CatalogImpl)catalog;
String resolvedSystemId = resolve(c, publicId, systemId);
if (resolvedSystemId != null) {
return new InputSource(resolvedSystemId);
}
GroupEntry.ResolveType resolveType = ((CatalogImpl) catalog).getResolve();
switch (resolveType) {
case IGNORE:
return new InputSource(new StringReader(""));
case STRICT:
CatalogMessages.reportError(CatalogMessages.ERR_NO_MATCH,
new Object[]{publicId, systemId});
}
//no action, allow the parser to continue
return null;
}
/**
* Resolves the publicId or systemId to one specified in the catalog.
* @param catalog the catalog
* @param publicId the publicId
* @param systemId the systemId
* @return the resolved systemId if a match is found, null otherwise
*/
String resolve(CatalogImpl catalog, String publicId, String systemId) {
String resolvedSystemId = null;
//search the current catalog
catalog.reset();
if (systemId != null) {
resolvedSystemId = catalog.matchSystem(systemId);
}
if (resolvedSystemId == null) {
resolvedSystemId = catalog.matchPublic(publicId);
}
//mark the catalog as having been searched before trying alternatives
catalog.markAsSearched();
//search alternative catalogs
if (resolvedSystemId == null) {
Iterator<Catalog> iter = catalog.catalogs().iterator();
while (iter.hasNext()) {
resolvedSystemId = resolve((CatalogImpl)iter.next(), publicId, systemId);
if (resolvedSystemId != null) {
break;
}
}
}
return resolvedSystemId;
}
}

@ -0,0 +1,58 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import javax.xml.transform.Source;
import javax.xml.transform.URIResolver;
/**
* A JAXP URIResolver that uses catalogs to resolve references.
*
* @since 9
*/
public interface CatalogUriResolver extends URIResolver {
/**
* The method searches through the catalog entries in the main and
* alternative catalogs to attempt to find a match with the specified URI.
*
* @param href an href attribute, which may be relative or absolute
* @param base The base URI against which the href attribute will be made
* absolute if the absolute URI is required
*
* @return a {@link javax.xml.transform.Source} object if a mapping is found.
* If no mapping is found, returns a {@link javax.xml.transform.Source} object
* containing an empty {@link java.io.Reader} if the
* {@code javax.xml.catalog.resolve} property is set to {@code ignore};
* returns a {@link javax.xml.transform.Source} object with the original URI
* (href, or href resolved with base if base is not null) if the
* {@code javax.xml.catalog.resolve} property is set to {@code continue}.
*
* @throws CatalogException if no mapping is found and
* {@code javax.xml.catalog.resolve} is specified as strict
*/
@Override
public Source resolve(String href, String base);
}

@ -0,0 +1,176 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl;
import java.io.StringReader;
import java.net.URL;
import java.util.Iterator;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import javax.xml.transform.Source;
import javax.xml.transform.sax.SAXSource;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
/**
* A SAX EntityResolver/JAXP URIResolver that uses catalogs.
* <p>
* This class implements both a SAX EntityResolver and a JAXP URIResolver.
*
*
* @since 9
*/
final class CatalogUriResolverImpl implements CatalogUriResolver {
Catalog catalog;
CatalogResolverImpl entityResolver;
/**
* Construct an instance of the CatalogResolver from a Catalog.
*
* @param catalog A Catalog.
*/
public CatalogUriResolverImpl(Catalog catalog) {
this.catalog = catalog;
}
@Override
public Source resolve(String href, String base) {
if (href == null) return null;
CatalogImpl c = (CatalogImpl)catalog;
String uri = Normalizer.normalizeURI(href);
String result;
//remove fragment if any.
int hashPos = uri.indexOf("#");
if (hashPos >= 0) {
uri = uri.substring(0, hashPos);
}
//search the current catalog
result = resolve(c, uri);
if (result == null) {
GroupEntry.ResolveType resolveType = c.getResolve();
switch (resolveType) {
case IGNORE:
return new SAXSource(new InputSource(new StringReader("")));
case STRICT:
CatalogMessages.reportError(CatalogMessages.ERR_NO_URI_MATCH,
new Object[]{href, base});
}
try {
URL url = null;
if (base == null) {
url = new URL(uri);
result = url.toString();
} else {
URL baseURL = new URL(base);
url = (href.length() == 0 ? baseURL : new URL(baseURL, uri));
result = url.toString();
}
} catch (java.net.MalformedURLException mue) {
CatalogMessages.reportError(CatalogMessages.ERR_CREATING_URI,
new Object[]{href, base});
}
}
SAXSource source = new SAXSource();
source.setInputSource(new InputSource(result));
setEntityResolver(source);
return source;
}
/**
* Resolves the publicId or systemId to one specified in the catalog.
* @param catalog the catalog
* @param href an href attribute, which may be relative or absolute
* @return the resolved systemId if a match is found, null otherwise
*/
String resolve(CatalogImpl catalog, String href) {
String result = null;
//search the current catalog
catalog.reset();
if (href != null) {
result = catalog.matchURI(href);
}
//mark the catalog as having been searched before trying alternatives
catalog.markAsSearched();
//search alternative catalogs
if (result == null) {
Iterator<Catalog> iter = catalog.catalogs().iterator();
while (iter.hasNext()) {
result = resolve((CatalogImpl)iter.next(), href);
if (result != null) {
break;
}
}
}
return result;
}
/**
* Establish an entityResolver for newly resolved URIs.
* <p>
* This is called from the URIResolver to set an EntityResolver on the SAX
* parser to be used for new XML documents that are encountered as a result
* of the document() function, xsl:import, or xsl:include. This is done
* because the XSLT processor calls out to the SAXParserFactory itself to
* create a new SAXParser to parse the new document. The new parser does not
* automatically inherit the EntityResolver of the original (although
* arguably it should). Quote from JAXP specification on Class
* SAXTransformerFactory:
* <p>
* {@code If an application wants to set the ErrorHandler or EntityResolver
* for an XMLReader used during a transformation, it should use a URIResolver
* to return the SAXSource which provides (with getXMLReader) a reference to
* the XMLReader}
*
*/
private void setEntityResolver(SAXSource source) {
XMLReader reader = source.getXMLReader();
if (reader == null) {
SAXParserFactory spFactory = new SAXParserFactoryImpl();
spFactory.setNamespaceAware(true);
try {
reader = spFactory.newSAXParser().getXMLReader();
} catch (ParserConfigurationException | SAXException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_PARSER_CONF, ex);
}
}
if (entityResolver != null) {
entityResolver = new CatalogResolverImpl(catalog);
}
reader.setEntityResolver(entityResolver);
source.setXMLReader(reader);
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URI;
/**
* Represents a delegatePublic entry.
*
* @since 9
*/
final class DelegatePublic extends AltCatalog {
String publicIdStartString;
/**
* Construct a delegatePublic entry.
* @param startString The publicIdStartString attribute.
* @param catalog The catalog attribute.
*/
public DelegatePublic(String base, String startString, String catalog) {
super(CatalogEntryType.DELEGATEPUBLIC, base);
setPublicIdStartString(startString);
setCatalog(catalog);
}
/**
* Set the publicIdStartString attribute.
* @param startString The publicIdStartString attribute value.
*/
public void setPublicIdStartString (String startString) {
CatalogMessages.reportNPEOnNull("publicIdStartString", startString);
this.publicIdStartString = Normalizer.normalizePublicId(startString);
setMatchId(publicIdStartString);
}
/**
* Get the publicIdStartString attribute.
* @return The publicIdStartString
*/
public String getPublicIdStartString () {
return publicIdStartString;
}
/**
* Try to match the specified publicId with the entry.
*
* @param publicId The publicId to be matched.
* @return The URI of the catalog.
*/
@Override
public String match(String publicId) {
return match(publicId, 0);
}
/**
* Try to match the specified publicId with the entry. Return the match if it
* is successful and the length of the publicIdStartString is longer than the
* longest of any previous match.
*
* @param publicId The publicId to be matched.
* @param currentMatch The length of publicIdStartString of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public URI matchURI(String publicId, int currentMatch) {
if (publicIdStartString.length() <= publicId.length() &&
publicIdStartString.equals(publicId.substring(0, publicIdStartString.length()))) {
if (currentMatch < publicIdStartString.length()) {
return catalogURI;
}
}
return null;
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URI;
/**
* Represents a delegateSystem entry.
*
* @since 9
*/
final class DelegateSystem extends AltCatalog {
String systemIdStartString;
/**
* Construct a delegateSystem entry.
* @param systemIdStartString The systemIdStartString attribute.
* @param catalog The catalog attribute.
*/
public DelegateSystem(String base, String systemIdStartString, String catalog) {
super(CatalogEntryType.DELEGATESYSTEM, base);
setSystemIdStartString(systemIdStartString);
setCatalog(catalog);
}
/**
* Set the systemIdStartString attribute.
* @param systemIdStartString The systemIdStartString attribute value.
*/
public void setSystemIdStartString (String systemIdStartString) {
CatalogMessages.reportNPEOnNull("systemIdStartString", systemIdStartString);
this.systemIdStartString = Normalizer.normalizeURI(systemIdStartString);
setMatchId(this.systemIdStartString);
}
/**
* Get the systemIdStartString attribute.
* @return The systemIdStartString
*/
public String getSystemIdStartString () {
return systemIdStartString;
}
/**
* Try to match the specified systemId with the entry.
*
* @param systemId The systemId to be matched.
* @return The URI of the catalog.
*/
@Override
public String match(String systemId) {
return match(systemId, 0);
}
/**
* Matches the specified publicId with the entry. Return the match if it
* is successful and the length of the systemIdStartString is longer than the
* longest of any previous match.
*
* @param systemId The systemId to be matched.
* @param currentMatch The length of systemIdStartString of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public URI matchURI(String systemId, int currentMatch) {
if (systemIdStartString.length() <= systemId.length() &&
systemIdStartString.equals(systemId.substring(0, systemIdStartString.length()))) {
if (currentMatch < systemIdStartString.length()) {
return catalogURI;
}
}
return null;
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URI;
/**
* Represents a delegateURI entry.
*
* @since 9
*/
final class DelegateUri extends AltCatalog {
String uriStartString;
/**
* Construct a delegateURI entry.
* @param uriStartString The uriStartString attribute.
* @param catalog The catalog attribute.
*/
public DelegateUri(String base, String uriStartString, String catalog) {
super(CatalogEntryType.DELEGATEURI, base);
setURIStartString (uriStartString);
setCatalog(catalog);
}
/**
* Set the uriStartString attribute.
*
* @param uriStartString The uriStartString attribute value.
*/
public void setURIStartString (String uriStartString) {
CatalogMessages.reportNPEOnNull("uriStartString", uriStartString);
this.uriStartString = Normalizer.normalizeURI(uriStartString);
setMatchId(this.uriStartString);
}
/**
* Get the uriStartString attribute.
* @return The uriStartString
*/
public String getURIStartString () {
return uriStartString;
}
/**
* Try to match the specified systemId with the entry.
*
* @param systemId The systemId to be matched.
* @return The URI of the catalog.
*/
@Override
public String match(String systemId) {
return match(systemId, 0);
}
/**
* Matches the specified systemId with the entry. Return the match if it
* is successful and the length of the uriStartString is longer than the
* longest of any previous match.
*
* @param systemId The systemId to be matched.
* @param currentMatch The length of uriStartString of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public URI matchURI(String systemId, int currentMatch) {
if (uriStartString.length() <= systemId.length() &&
uriStartString.equals(systemId.substring(0, uriStartString.length()))) {
if (currentMatch < uriStartString.length()) {
return catalogURI;
}
}
return null;
}
}

@ -0,0 +1,503 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 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;
import java.util.Map;
/**
* Represents a group entry.
*
* @since 9
*/
class GroupEntry extends BaseEntry {
static final int ATTRIBUTE_PREFER = 0;
static final int ATTRIBUTE_DEFFER = 1;
static final int ATTRIBUTE_RESOLUTION = 2;
//Unmodifiable features when the Catalog is created
CatalogFeatures features;
//Value of the prefer attribute
boolean isPreferPublic = true;
//The catalog instance this group belongs to
CatalogImpl catalog;
//A list of all entries in a catalog or group
List<BaseEntry> entries = new ArrayList<>();
//loaded delegated catalog by system id
Map<String, Catalog> delegateCatalogs = new HashMap<>();
//A list of all loaded Catalogs, including this, and next catalogs
Map<String, Catalog> loadedCatalogs = new HashMap<>();
/*
A list of Catalog Ids that have already been searched in a matching
operation. Check this list before constructing new Catalog to avoid circular
reference.
*/
List<String> catalogsSearched = new ArrayList<>();
//A flag to indicate whether the current match is a system or uri
boolean isInstantMatch = false;
//A match of a rewrite type
String rewriteMatch = null;
//The length of the longest match of a rewrite type
int longestRewriteMatch = 0;
//A match of a suffix type
String suffixMatch = null;
//The length of the longest match of a suffix type
int longestSuffixMatch = 0;
/**
* PreferType represents possible values of the prefer property
*/
public static enum PreferType {
PUBLIC("public"),
SYSTEM("system");
final String literal;
PreferType(String literal) {
this.literal = literal;
}
public boolean prefer(String prefer) {
return literal.equals(prefer);
}
}
/**
* PreferType represents possible values of the resolve property
*/
public static enum ResolveType {
STRICT(CatalogFeatures.RESOLVE_STRICT),
CONTINUE(CatalogFeatures.RESOLVE_CONTINUE),
IGNORE(CatalogFeatures.RESOLVE_IGNORE);
final String literal;
ResolveType(String literal) {
this.literal = literal;
}
static public ResolveType getType(String resolveType) {
for (ResolveType type : ResolveType.values()) {
if (type.isType(resolveType)) {
return type;
}
}
return null;
}
public boolean isType(String type) {
return literal.equals(type);
}
}
/**
* Constructs a GroupEntry
*
* @param type The type of the entry
*/
public GroupEntry(CatalogEntryType type) {
super(type);
}
/**
* Constructs a group entry.
*
* @param base The baseURI attribute
* @param attributes The attributes
*/
public GroupEntry(String base, String... attributes) {
this(null, base, attributes);
}
/**
* Resets the group entry to its initial state.
*/
public void reset() {
isInstantMatch = false;
rewriteMatch = null;
longestRewriteMatch = 0;
suffixMatch = null;
longestSuffixMatch = 0;
}
/**
* Constructs a group entry.
* @param catalog The parent catalog
* @param base The baseURI attribute
* @param attributes The attributes
*/
public GroupEntry(CatalogImpl catalog, String base, String... attributes) {
super(CatalogEntryType.GROUP, base);
setPrefer(attributes[ATTRIBUTE_PREFER]);
this.catalog = catalog;
}
/**
* Adds an entry.
*
* @param entry The entry to be added.
*/
public void addEntry(BaseEntry entry) {
entries.add(entry);
}
/**
* Sets the prefer property. If the value is null or empty, or any String
* other than the defined, it will be assumed as the default value.
*
* @param value The value of the prefer attribute
*/
public final void setPrefer(String value) {
isPreferPublic = PreferType.PUBLIC.prefer(value);
}
/**
* Queries the prefer attribute
*
* @return true if the prefer attribute is set to system, false if not.
*/
public boolean isPreferPublic() {
return isPreferPublic;
}
/**
* Attempt to find a matching entry in the catalog by systemId.
*
* <p>
* The method searches through the system-type entries, including system,
* rewriteSystem, systemSuffix, delegateSystem, and group entries in the
* current catalog in order to find a match.
*
*
* @param systemId The system identifier of the external entity being
* referenced.
*
* @return An URI string if a mapping is found, or null otherwise.
*/
public String matchSystem(String systemId) {
String match = null;
for (BaseEntry entry : entries) {
switch (entry.type) {
case SYSTEM:
match = ((SystemEntry) entry).match(systemId);
//if there's a matching system entry, use it
if (match != null) {
isInstantMatch = true;
return match;
}
break;
case REWRITESYSTEM:
match = ((RewriteSystem) entry).match(systemId, longestRewriteMatch);
if (match != null) {
rewriteMatch = match;
longestRewriteMatch = ((RewriteSystem) entry).getSystemIdStartString().length();
}
break;
case SYSTEMSUFFIX:
match = ((SystemSuffix) entry).match(systemId, longestSuffixMatch);
if (match != null) {
suffixMatch = match;
longestSuffixMatch = ((SystemSuffix) entry).getSystemIdSuffix().length();
}
break;
case GROUP:
GroupEntry grpEntry = (GroupEntry) entry;
match = grpEntry.matchSystem(systemId);
if (grpEntry.isInstantMatch) {
//use it if there is a match of the system type
return match;
} else if (grpEntry.longestRewriteMatch > longestRewriteMatch) {
rewriteMatch = match;
} else if (grpEntry.longestSuffixMatch > longestSuffixMatch) {
suffixMatch = match;
}
break;
}
}
if (longestRewriteMatch > 0) {
return rewriteMatch;
} else if (longestSuffixMatch > 0) {
return suffixMatch;
}
//if no single match is found, try delegates
return matchDelegate(CatalogEntryType.DELEGATESYSTEM, systemId);
}
/**
* Attempt to find a matching entry in the catalog by publicId.
*
* <p>
* The method searches through the public-type entries, including public,
* delegatePublic, and group entries in the current catalog in order to find
* a match.
*
*
* @param publicId The public identifier of the external entity being
* referenced.
*
* @return An URI string if a mapping is found, or null otherwise.
*/
public String matchPublic(String publicId) {
//as the specification required
if (!isPreferPublic) {
return null;
}
//match public entries
String match = null;
for (BaseEntry entry : entries) {
switch (entry.type) {
case PUBLIC:
match = ((PublicEntry) entry).match(publicId);
break;
case GROUP:
match = ((GroupEntry) entry).matchPublic(publicId);
break;
}
if (match != null) {
return match;
}
}
//if no single match is found, try delegates
return matchDelegate(CatalogEntryType.DELEGATEPUBLIC, publicId);
}
/**
* Attempt to find a matching entry in the catalog by the uri element.
*
* <p>
* The method searches through the uri-type entries, including uri,
* rewriteURI, uriSuffix, delegateURI and group entries in the current
* catalog in order to find a match.
*
*
* @param uri The URI reference of a resource.
*
* @return An URI string if a mapping is found, or null otherwise.
*/
public String matchURI(String uri) {
String match = null;
for (BaseEntry entry : entries) {
switch (entry.type) {
case URI:
match = ((UriEntry) entry).match(uri);
if (match != null) {
isInstantMatch = true;
return match;
}
break;
case REWRITEURI:
match = ((RewriteUri) entry).match(uri, longestRewriteMatch);
if (match != null) {
rewriteMatch = match;
longestRewriteMatch = ((RewriteUri) entry).getURIStartString().length();
}
break;
case URISUFFIX:
match = ((UriSuffix) entry).match(uri, longestSuffixMatch);
if (match != null) {
suffixMatch = match;
longestSuffixMatch = ((UriSuffix) entry).getURISuffix().length();
}
break;
case GROUP:
GroupEntry grpEntry = (GroupEntry) entry;
match = grpEntry.matchURI(uri);
if (grpEntry.isInstantMatch) {
//use it if there is a match of the uri type
return match;
} else if (grpEntry.longestRewriteMatch > longestRewriteMatch) {
rewriteMatch = match;
} else if (grpEntry.longestSuffixMatch > longestSuffixMatch) {
suffixMatch = match;
}
break;
}
}
if (longestRewriteMatch > 0) {
return rewriteMatch;
} else if (longestSuffixMatch > 0) {
return suffixMatch;
}
//if no single match is found, try delegates
return matchDelegate(CatalogEntryType.DELEGATEURI, uri);
}
/**
* Matches delegatePublic or delegateSystem against the specified id
*
* @param isSystem The flag to indicate whether the delegate is system or
* public
* @param id The system or public id to be matched
* @return The URI string if a mapping is found, or null otherwise.
*/
private String matchDelegate(CatalogEntryType type, String id) {
String match = null;
int longestMatch = 0;
URI catalogId = null;
URI temp;
//Check delegate types in the current catalog
for (BaseEntry entry : entries) {
if (entry.type == type) {
if (type == CatalogEntryType.DELEGATESYSTEM) {
temp = ((DelegateSystem)entry).matchURI(id, longestMatch);
} else if (type == CatalogEntryType.DELEGATEPUBLIC) {
temp = ((DelegatePublic)entry).matchURI(id, longestMatch);
} else {
temp = ((DelegateUri)entry).matchURI(id, longestMatch);
}
if (temp != null) {
longestMatch = entry.getMatchId().length();
catalogId = temp;
}
}
}
//Check delegate Catalogs
if (catalogId != null) {
Catalog delegateCatalog = loadCatalog(catalogId);
if (delegateCatalog != null) {
if (type == CatalogEntryType.DELEGATESYSTEM) {
match = delegateCatalog.matchSystem(id);
} else if (type == CatalogEntryType.DELEGATEPUBLIC) {
match = delegateCatalog.matchPublic(id);
} else {
match = delegateCatalog.matchURI(id);
}
}
}
return match;
}
/**
* Loads all delegate catalogs.
*/
void loadDelegateCatalogs() {
entries.stream()
.filter((entry) -> (entry.type == CatalogEntryType.DELEGATESYSTEM ||
entry.type == CatalogEntryType.DELEGATEPUBLIC ||
entry.type == CatalogEntryType.DELEGATEURI))
.map((entry) -> (AltCatalog)entry)
.forEach((altCatalog) -> {
loadCatalog(altCatalog.getCatalogURI());
});
}
/**
* Loads a delegate catalog by the catalogId specified.
* @param catalogId the catalog Id
*/
Catalog loadCatalog(URI catalogURI) {
Catalog delegateCatalog = null;
if (catalogURI != null) {
String catalogId = catalogURI.toASCIIString();
delegateCatalog = getLoadedCatalog(catalogId);
if (delegateCatalog == null) {
if (verifyCatalogFile(catalogURI)) {
delegateCatalog = new CatalogImpl(catalog, features, catalogId);
delegateCatalogs.put(catalogId, delegateCatalog);
}
}
}
return delegateCatalog;
}
/**
* Returns a previously loaded Catalog object if found.
*
* @param catalogId The systemId of a catalog
* @return a Catalog object previously loaded, or null if none in the saved
* list
*/
Catalog getLoadedCatalog(String catalogId) {
Catalog c = null;
//checl delegate Catalogs
c = delegateCatalogs.get(catalogId);
if (c == null) {
//check other loaded Catalogs
c = loadedCatalogs.get(catalogId);
}
return c;
}
/**
* Verifies that the catalog file represented by the catalogId exists. If it
* doesn't, returns false to ignore it as specified in the Catalog
* specification, section 8. Resource Failures.
* <p>
* Verifies that the catalog represented by the catalogId has not been
* searched or is not circularly referenced.
*
* @param catalogId The URI to a catalog
* @throws CatalogException if circular reference is found.
* @return true if the catalogId passed verification, false otherwise
*/
final boolean verifyCatalogFile(URI catalogURI) {
if (catalogURI == null) {
return false;
}
//Ignore it if it doesn't exist
if (!Files.exists(Paths.get(catalogURI))) {
return false;
}
String catalogId = catalogURI.toASCIIString();
if (catalogsSearched.contains(catalogId)) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_CIRCULAR_REFERENCE,
new Object[]{CatalogMessages.sanitize(catalogId)});
}
return true;
}
}

@ -0,0 +1,48 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
/**
* Represents a nextCatalog entry.
*
* @since 9
*/
final class NextCatalog extends AltCatalog {
/**
* Construct a nextCatalog entry.
* @param catalog The catalog attribute.
*/
public NextCatalog(String base, String catalog) {
super(CatalogEntryType.NEXTCATALOG, base);
setCatalog(catalog);
}
@Override
public String match(String match) {
throw new UnsupportedOperationException("Not supported.");
}
}

@ -0,0 +1,177 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.net.URLEncoder;
/**
* The Normalizer is responsible for normalizing Public and System Identifiers
* as specified in section 6.2, 6.3 and 6.4 of the specification
* * <a
* href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
* XML Catalogs, OASIS Standard V1.1, 7 October 2005</a>.
*
* @since 9
*/
class Normalizer {
/**
* Normalize a public identifier in accordance with section 6.2 of the
* Catalog specification.
*
* <p>
* All strings of white space in public identifiers must be normalized to
* single space characters (#x20), and leading and trailing white space must
* be removed.
*
* @param publicId The unnormalized public identifier
*
* @return The normalized identifier
*/
static String normalizePublicId(String publicId) {
if (publicId == null) return null;
StringBuilder sb = new StringBuilder(publicId.length());
char last = 'a';
for (char c : publicId.toCharArray()) {
//skip beginning and duplicate space
if ((c == ' ') && (sb.length() == 0 || last == ' ')) {
continue;
}
//replace whitespace with space
if (c == '\t' || c == '\r' || c == '\n') {
if (last != ' ') {
sb.append(' ');
last = ' ';
}
} else {
sb.append(c);
last = c;
}
}
//remove the last space
if (last == ' ') {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
/**
* Encode a public identifier as a "publicid" URN.
*
* @param publicId The unnormalized public identifier
*
* @return The normalized identifier
* @throws CatalogException if encoding failed
*/
static String encodeURN(String publicId) {
String urn = normalizePublicId(publicId);
try {
urn = URLEncoder.encode(urn, "UTF-8");
urn = urn.replace("::", ";");
urn = urn.replace("//", ":");
} catch (UnsupportedEncodingException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
}
return "urn:publicid:" + urn;
}
/**
* Decode a "publicid" URN into a public identifier.
*
* @param urn The urn:publicid: URN
*
* @return The normalized identifier
* @throws CatalogException if decoding failed
*/
static String decodeURN(String urn) {
String publicId;
if (urn != null && urn.startsWith("urn:publicid:")) {
publicId = urn.substring(13);
} else {
return urn;
}
try {
publicId = publicId.replace(":", "//");
publicId = publicId.replace(";", "::");
publicId = URLDecoder.decode(publicId, "UTF-8");
} catch (UnsupportedEncodingException ex) {
CatalogMessages.reportRunTimeError(CatalogMessages.ERR_OTHER, ex);
}
return publicId;
}
/**
* Perform character normalization on a URI reference.
*
* @param uriref The URI reference
* @return The normalized URI reference
*/
static String normalizeURI(String uriref) {
if (uriref == null) {
return null;
}
byte[] bytes;
uriref = uriref.trim();
try {
bytes = uriref.getBytes("UTF-8");
} catch (UnsupportedEncodingException uee) {
// this can't happen
return uriref;
}
StringBuilder newRef = new StringBuilder(bytes.length);
for (int count = 0; count < bytes.length; count++) {
int ch = bytes[count] & 0xFF;
if ((ch <= 0x20) // ctrl
|| (ch > 0x7F) // high ascii
|| (ch == 0x22) // "
|| (ch == 0x3C) // <
|| (ch == 0x3E) // >
|| (ch == 0x5C) // \
|| (ch == 0x5E) // ^
|| (ch == 0x60) // `
|| (ch == 0x7B) // {
|| (ch == 0x7C) // |
|| (ch == 0x7D) // }
|| (ch == 0x7F)) {
newRef.append("%").append(String.format("%02X", ch));
} else {
newRef.append((char) bytes[count]);
}
}
return newRef.toString().trim();
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents a public entry.
*
* @since 9
*/
final class PublicEntry extends BaseEntry {
String publicId;
URL uri;
/**
* Construct a public entry.
* @param publicId The publicId attribute.
* @param uri The uri attribute.
*/
public PublicEntry(String base, String publicId, String uri) {
super(CatalogEntryType.PUBLIC, base);
setPublicId(publicId);
setURI(uri);
}
/**
* Set the publicId attribute.
* @param publicId The publicId attribute value.
*/
public void setPublicId(String publicId) {
CatalogMessages.reportNPEOnNull("publicId", publicId);
this.publicId = Normalizer.normalizePublicId(publicId);
}
/**
* Set the uri attribute. If the value of the uri attribute is relative, it
* must be made absolute with respect to the base URI currently in effect.
* The URI reference should not include a fragment identifier.
* @param uri The uri attribute value.
*/
public void setURI(String uri) {
this.uri = verifyURI("uri", baseURI, uri);
}
/**
* Get the publicId attribute.
* @return The publicId
*/
public String getPublicId() {
return publicId;
}
/**
* Get the uri attribute.
* @return The uri attribute value.
*/
public URL getURI() {
return uri;
}
@Override
public String match(String publicId) {
if (this.publicId.equals(publicId)) {
return uri.toString();
}
return null;
}
}

@ -0,0 +1,118 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents a rewriteSystem entry.
*
* @since 9
*/
final class RewriteSystem extends BaseEntry {
String systemIdStartString;
URL rewritePrefix;
/**
* Construct a rewriteSystem entry.
*
* @param systemIdStartString The systemIdStartString attribute.
* @param rewritePrefix The rewritePrefix attribute.
*/
public RewriteSystem(String base, String systemIdStartString, String rewritePrefix) {
super(CatalogEntryType.REWRITESYSTEM, base);
setSystemIdStartString (systemIdStartString);
setRewritePrefix(rewritePrefix);
}
/**
* Set the systemIdStartString attribute.
* @param systemIdStartString The systemIdStartString attribute value.
*/
public void setSystemIdStartString (String systemIdStartString) {
CatalogMessages.reportNPEOnNull("systemIdStartString", systemIdStartString);
this.systemIdStartString = Normalizer.normalizeURI(systemIdStartString);
}
/**
* Set the rewritePrefix attribute. If the value of the rewritePrefix attribute
* is relative, it must be made absolute with respect to the base URI currently in effect.
* @param rewritePrefix The rewritePrefix attribute value.
*/
public void setRewritePrefix(String rewritePrefix) {
this.rewritePrefix = verifyURI("setRewritePrefix", baseURI, rewritePrefix);
}
/**
* Get the systemIdStartString attribute.
* @return The systemIdStartString
*/
public String getSystemIdStartString () {
return systemIdStartString;
}
/**
* Get the rewritePrefix attribute.
* @return The rewritePrefix attribute value.
*/
public URL getRewritePrefix() {
return rewritePrefix;
}
/**
* Try to match the specified systemId with the entry. Return the match if it
* is successful and the length of the systemIdStartString is longer than the
* longest of any previous match.
*
* @param systemId The systemId to be matched.
* @param currentMatch The length of systemIdStartString of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
public String match(String systemId, int currentMatch) {
if (systemIdStartString.length() <= systemId.length() &&
systemIdStartString.equals(systemId.substring(0, systemIdStartString.length()))) {
if (currentMatch < systemIdStartString.length()) {
String prefix = rewritePrefix.toExternalForm();
if (!prefix.endsWith(SLASH) && !systemId.startsWith(SLASH)) {
return prefix + SLASH + systemId.substring(systemIdStartString.length());
} else {
return prefix + systemId.substring(systemIdStartString.length());
}
}
}
return null;
}
/**
* Try to match the specified systemId with the entry.
*
* @param systemId The systemId to be matched.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public String match(String systemId) {
return match(systemId, 0);
}
}

@ -0,0 +1,113 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents a rewriteURI entry.
*
* @since 9
*/
final class RewriteUri extends BaseEntry {
String uriStartString;
URL rewritePrefix;
/**
* Construct a rewriteURI entry.
* @param uriStartString The uriStartString attribute.
* @param rewritePrefix The rewritePrefix attribute.
*/
public RewriteUri(String base, String uriStartString, String rewritePrefix) {
super(CatalogEntryType.REWRITEURI, base);
setURIStartString (uriStartString);
setRewritePrefix(rewritePrefix);
}
/**
* Set the uriStartString attribute.
* @param uriStartString The uriStartString attribute value.
*/
public void setURIStartString (String uriStartString) {
CatalogMessages.reportNPEOnNull("uriStartString", uriStartString);
this.uriStartString = Normalizer.normalizeURI(uriStartString);
}
/**
* Set the rewritePrefix attribute. If the value of the rewritePrefix attribute
* is relative, it must be made absolute with respect to the base URI currently in effect.
*
* @param rewritePrefix The rewritePrefix attribute value.
*/
public void setRewritePrefix(String rewritePrefix) {
this.rewritePrefix = verifyURI("setRewritePrefix", baseURI, rewritePrefix);
}
/**
* Get the uriStartString attribute.
* @return The uriStartString
*/
public String getURIStartString () {
return uriStartString;
}
/**
* Get the rewritePrefix attribute.
* @return The rewritePrefix attribute value.
*/
public URL getRewritePrefix() {
return rewritePrefix;
}
/**
* Try to match the specified systemId with the entry. Return the match if it
* is successful and the length of the systemIdStartString is longer than the
* longest of any previous match.
*
* @param systemId The systemId to be matched.
* @param currentMatch The length of uriStartString of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public String match(String systemId, int currentMatch) {
if (uriStartString.length() <= systemId.length() &&
uriStartString.equals(systemId.substring(0, uriStartString.length()))) {
if (currentMatch < uriStartString.length()) {
String prefix = rewritePrefix.toExternalForm();
if (!prefix.endsWith(SLASH) && !systemId.startsWith(SLASH)) {
return prefix + SLASH + systemId.substring(uriStartString.length());
} else {
return prefix + systemId.substring(uriStartString.length());
}
}
}
return null;
}
@Override
public String match(String systemId) {
return match(systemId, 0);
}
}

@ -0,0 +1,97 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents a system entry.
*
* @since 9
*/
final class SystemEntry extends BaseEntry {
String systemId;
URL uri;
/**
* Construct a system entry.
*
* @param systemId The systemId attribute.
* @param uri The uri attribute.
*/
public SystemEntry(String base, String systemId, String uri) {
super(CatalogEntryType.SYSTEM, base);
setSystemId(systemId);
setURI(uri);
}
/**
* Set the systemId attribute.
* @param systemId The systemId attribute value.
*/
public void setSystemId(String systemId) {
CatalogMessages.reportNPEOnNull("systemId", systemId);
this.systemId = Normalizer.normalizeURI(systemId);
}
/**
* Set the uri attribute. If the value of the uri attribute is relative, it
* must be made absolute with respect to the base URI currently in effect.
* The URI reference should not include a fragment identifier.
* @param uri The uri attribute value.
*/
public void setURI(String uri) {
this.uri = verifyURI("setURI", baseURI, uri);
}
/**
* Get the systemId attribute.
* @return The systemId
*/
public String getSystemId() {
return systemId;
}
/**
* Get the uri attribute.
* @return The uri attribute value.
*/
public URL getURI() {
return uri;
}
/**
* Try to match the specified string with the entry
*
* @param systemId The systemId to be matched
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public String match(String systemId) {
if (this.systemId.equals(systemId)) {
return uri.toString();
}
return null;
}
}

@ -0,0 +1,112 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents a systemSuffix entry.
*
* @since 9
*/
final class SystemSuffix extends BaseEntry {
String systemIdSuffix;
URL uri;
/**
* Construct a systemSuffix entry.
* @param systemIdSuffix The systemIdSuffix attribute.
* @param uri The uri attribute.
*/
public SystemSuffix(String base, String systemIdSuffix, String uri) {
super(CatalogEntryType.SYSTEMSUFFIX, base);
setSystemIdSuffix(systemIdSuffix);
setURI(uri);
}
/**
* Set the systemIdSuffix attribute.
* @param systemIdSuffix The systemIdSuffix attribute value.
*/
public void setSystemIdSuffix(String systemIdSuffix) {
CatalogMessages.reportNPEOnNull("systemIdSuffix", systemIdSuffix);
this.systemIdSuffix = Normalizer.normalizeURI(systemIdSuffix);
}
/**
* Set the uri attribute. If the value of the uri attribute is relative, it
* must be made absolute with respect to the base URI currently in effect.
* The URI reference should not include a fragment identifier.
* @param uri The uri attribute value.
*/
public void setURI(String uri) {
this.uri = verifyURI("setURI", baseURI, uri);
}
/**
* Get the systemIdSuffix attribute.
* @return The systemIdSuffix
*/
public String getSystemIdSuffix () {
return systemIdSuffix;
}
/**
* Get the uri attribute.
* @return The uri attribute value.
*/
public URL getURI() {
return uri;
}
/**
* Try to match the specified systemId with the entry. Return the match if it
* is successful and the length of the systemIdSuffix is longer than the longest
* of any previous match.
*
* @param systemId The systemId to be matched.
* @param currentMatch The length of systemIdSuffix of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public String match(String systemId, int currentMatch) {
if (systemId.endsWith(systemIdSuffix)) {
if (currentMatch < systemIdSuffix.length()) {
return uri.toString();
}
}
return null;
}
/**
* Try to match the specified systemId with the entry.
*
* @param systemId The systemId to be matched.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public String match(String systemId) {
return match(systemId, 0);
}
}

@ -0,0 +1,90 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents an uriEntry entry.
*
* @since 9
*/
final class UriEntry extends BaseEntry {
String name;
URL uri;
/**
* Construct a group entry.
* @param name The name attribute.
* @param uri The uri attribute.
*/
public UriEntry(String base, String name, String uri) {
super(CatalogEntryType.URI, base);
setName(name);
setURI(uri);
}
/**
* Set the name attribute.
* @param name The name attribute value.
*/
public void setName(String name) {
CatalogMessages.reportNPEOnNull("name", name);
this.name = Normalizer.normalizeURI(name);
}
/**
* Set the uri attribute. If the value of the uri attribute is relative, it
* must be made absolute with respect to the base URI currently in effect.
*
* @param uri The uri attribute value.
*/
public void setURI(String uri) {
this.uri = verifyURI("setURI", baseURI, uri);
}
/**
* Get the name attribute.
* @return The name
*/
public String getName() {
return name;
}
/**
* Get the uri attribute.
* @return The uri attribute value.
*/
public URL getURI() {
return uri;
}
@Override
public String match(String name) {
if (this.name.equals(name)) {
return uri.toString();
}
return null;
}
}

@ -0,0 +1,107 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import java.net.URL;
/**
* Represents a uriSuffix entry.
*
* @since 9
*/
final class UriSuffix extends BaseEntry {
String uriSuffix;
URL uri;
/**
* Construct a group entry.
* @param uriSuffix The uriSuffix attribute.
* @param uri The uri attribute.
*/
public UriSuffix(String base, String uriSuffix, String uri) {
super(CatalogEntryType.URISUFFIX, base);
setURISuffix (uriSuffix);
setURI(uri);
}
/**
* Set the uriSuffix attribute.
* @param uriSuffix The uriSuffix attribute value.
*/
public void setURISuffix(String uriSuffix) {
CatalogMessages.reportNPEOnNull("uriSuffix", uriSuffix);
this.uriSuffix = Normalizer.normalizeURI(uriSuffix);
}
/**
* Set the uri attribute. If the value of the uri attribute is relative, it
* must be made absolute with respect to the base URI currently in effect.
* The URI reference should not include a fragment identifier.
* @param uri The uri attribute value.
*/
public void setURI(String uri) {
this.uri = verifyURI("setURI", baseURI, uri);
}
/**
* Get the uriSuffix attribute.
* @return The uriSuffix
*/
public String getURISuffix () {
return uriSuffix;
}
/**
* Get the uri attribute.
* @return The uri attribute value.
*/
public String getURI() {
return uri.toString();
}
/**
* Try to match the specified systemId with the entry. Return the match if it
* is successful and the length of the uriSuffix is longer than the longest
* of any previous match.
*
* @param systemId The systemId to be matched.
* @param currentMatch The length of uriSuffix of previous match if any.
* @return The replacement URI if the match is successful, null if not.
*/
@Override
public String match(String systemId, int currentMatch) {
if (systemId.endsWith(uriSuffix)) {
if (currentMatch < uriSuffix.length()) {
return uri.toString();
}
}
return null;
}
@Override
public String match(String systemId) {
return match(systemId, 0);
}
}

@ -0,0 +1,48 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 javax.xml.catalog;
import jdk.xml.internal.SecuritySupport;
/**
*
* @since 9
*/
class Util {
/**
* Find catalog file paths by reading the system property, and then
* jaxp.properties if the system property is not specified.
*
* @param sysPropertyName the name of system property
* @return the catalog file paths, or null if not found.
*/
static public String[] getCatalogFiles(String sysPropertyName) {
String value = SecuritySupport.getJAXPSystemProperty(sysPropertyName);
if (value != null && !value.equals("")) {
return value.split(";");
}
return null;
}
}

@ -0,0 +1,44 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<!--
Copyright (c) 2015, 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. Oracle designates this
particular file as subject to the "Classpath" exception as provided
by Oracle in the LICENSE file that accompanied this code.
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.
-->
</head>
<body bgcolor="white">
Provides the classes for implementing
<a href="https://www.oasis-open.org/committees/download.php/14809/xml-catalogs.html">
XML Catalogs OASIS Standard V1.1, 7 October 2005</a>.
<p>
Unless otherwise noted, passing a null argument to
a constructor or method in any class or interface in this package will
cause a <tt>NullPointerException</tt> to be thrown.
</p>
@since 9
</body>
</html>

@ -0,0 +1,153 @@
/*
* Copyright (c) 2015, 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. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* 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 jdk.xml.internal;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.text.MessageFormat;
import java.util.Locale;
import java.util.Properties;
import java.util.ResourceBundle;
/**
* This class contains utility methods for reading resources in the JAXP packages
*/
public class SecuritySupport {
/**
* Cache for properties in java.home/conf/jaxp.properties
*/
static final Properties cacheProps = new Properties();
/**
* Flag indicating whether java.home/conf/jaxp.properties has been read
*/
static volatile boolean firstTime = true;
private SecuritySupport() {}
public static String getErrorMessage(Locale locale, String bundle, String key,
Object[] arguments) {
ResourceBundle rb;
if (locale != null) {
rb = ResourceBundle.getBundle(bundle,locale);
} else {
rb = ResourceBundle.getBundle(bundle);
}
String msg = rb.getString(key);
if (arguments != null) {
msg = MessageFormat.format(msg, arguments);
}
return msg;
}
/**
* Reads JAXP system property with privilege
*
* @param propName the name of the property
* @return the value of the property
*/
public static String getSystemProperty(final String propName) {
return
AccessController.doPrivileged(
(PrivilegedAction<String>) () -> (String)System.getProperty(propName));
}
/**
* Reads JAXP system property in this order: system property,
* $java.home/conf/jaxp.properties if the system property is not specified
*
* @param propName the name of the property
* @return the value of the property
*/
public static String getJAXPSystemProperty(String propName) {
String value = getSystemProperty(propName);
if (value == null) {
value = readJAXPProperty(propName);
}
return value;
}
/**
* Reads the specified property from $java.home/conf/jaxp.properties
*
* @param propName the name of the property
* @return the value of the property
*/
public static String readJAXPProperty(String propName) {
String value = null;
InputStream is = null;
try {
if (firstTime) {
synchronized (cacheProps) {
if (firstTime) {
String configFile = getSystemProperty("java.home") + File.separator
+ "conf" + File.separator + "jaxp.properties";
File f = new File(configFile);
if (getFileExists(f)) {
is = getFileInputStream(f);
cacheProps.load(is);
}
firstTime = false;
}
}
}
value = cacheProps.getProperty(propName);
} catch (IOException ex) {
} finally {
if (is != null) {
try {
is.close();
} catch (IOException ex) {}
}
}
return value;
}
//------------------- private methods ---------------------------
static boolean getFileExists(final File f) {
return (AccessController.doPrivileged((PrivilegedAction<Boolean>) ()
-> f.exists() ? Boolean.TRUE : Boolean.FALSE));
}
static FileInputStream getFileInputStream(final File file)
throws FileNotFoundException {
try {
return AccessController.doPrivileged((PrivilegedExceptionAction<FileInputStream>) ()
-> new FileInputStream(file));
} catch (PrivilegedActionException e) {
throw (FileNotFoundException) e.getException();
}
}
}

@ -0,0 +1,62 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import javax.xml.catalog.CatalogException;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Via nextCatalog entry, the catalog reference chain may be
* a (partial) closed circuit. For instance, a catalog may use itself
* as an additional catalog specified in its own nextCatalog entry.
* This case tests if the implementation handles this issue.
* @compile ../../libs/catalog/CatalogTestUtils.java
*/
public class CatalogReferCircularityTest {
@Test(dataProvider = "catalogName",
expectedExceptions = CatalogException.class)
public void testReferCircularity(String catalogFile) {
catalogResolver(catalogFile).resolveEntity(null,
"http://remote/dtd/ghost/docGhost.dtd");
}
@DataProvider(name = "catalogName")
private Object[][] catalogName() {
return new Object[][] {
// This catalog defines itself as next catalog.
{ "catalogReferCircle-itself.xml" },
// This catalog defines catalogReferCircle-right.xml as its next
// catalog. And catalogReferCircle-right.xml also defines
// catalogReferCircle-left.xml as its next catalog, too.
{ "catalogReferCircle-left.xml" } };
}
}

@ -0,0 +1,66 @@
/*
* Copyright (c) 2015, 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 javax.xml.catalog.CatalogFeatures.Feature;
import org.testng.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary This case tests if the default feature values are expected.
*/
public class DefaultFeaturesTest {
private CatalogFeatures defaultFeature;
@BeforeClass
public void init() {
defaultFeature = CatalogFeatures.defaults();
}
@Test(dataProvider="feature-value")
public void testDefaultFeatures(Feature feature, String expected) {
String featureValue = defaultFeature.get(feature);
if (expected != null) {
Assert.assertEquals(featureValue, expected);
} else {
Assert.assertNull(featureValue);
}
}
@DataProvider(name = "feature-value")
private Object[][] data() {
return new Object[][] {
{ Feature.FILES, null },
{ Feature.PREFER, CatalogTestUtils.PREFER_PUBLIC },
{ Feature.DEFER, CatalogTestUtils.DEFER_TRUE },
{ Feature.RESOLVE, CatalogTestUtils.RESOLVE_STRICT } };
}
}

@ -0,0 +1,92 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.DEFER_FALSE;
import static catalog.CatalogTestUtils.DEFER_TRUE;
import static catalog.CatalogTestUtils.getCatalogPath;
import static javax.xml.catalog.CatalogFeatures.Feature.DEFER;
import static javax.xml.catalog.CatalogManager.catalog;
import java.lang.reflect.Method;
import javax.xml.catalog.Catalog;
import javax.xml.catalog.CatalogFeatures;
import org.testng.Assert;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary This case tests whether the catalogs specified in delegateSystem,
* delegatePublic, delegateURI and nextCatalog entries are used lazily
* in resolution via defer feature.
* @compile ../../libs/catalog/CatalogTestUtils.java
*/
public class DeferFeatureTest {
@Test(dataProvider = "catalog-countOfLoadedCatalogFile")
public void testDeferFeature(Catalog catalog, int catalogCount)
throws Exception {
Assert.assertEquals(loadedCatalogCount(catalog), catalogCount);
}
@DataProvider(name = "catalog-countOfLoadedCatalogFile")
private Object[][] data() {
return new Object[][] {
// This catalog specifies null catalog explicitly,
// and the count of loaded catalogs should be 0.
{ createCatalog(null), 0 },
// This catalog specifies null catalog implicitly,
// and the count of loaded catalogs should be 0.
{ createCatalog(CatalogFeatures.defaults()), 0 },
// This catalog loads null catalog with true DEFER,
// and the count of loaded catalogs should be 0.
{ createCatalog(createDeferFeature(DEFER_TRUE)), 0 },
// This catalog loads null catalog with false DEFER.
// It should load all of none-current catalogs and the
// count of loaded catalogs should be 3.
{ createCatalog(createDeferFeature(DEFER_FALSE)), 3 } };
}
private CatalogFeatures createDeferFeature(String defer) {
return CatalogFeatures.builder().with(DEFER, defer).build();
}
private Catalog createCatalog(CatalogFeatures feature) {
return catalog(feature, getCatalogPath("deferFeature.xml"));
}
private int loadedCatalogCount(Catalog catalog) throws Exception {
Method method = catalog.getClass().getDeclaredMethod(
"loadedCatalogCount");
method.setAccessible(true);
return (int) method.invoke(catalog);
}
}

@ -0,0 +1,99 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkPubIdResolution;
import static catalog.ResolutionChecker.expectExceptionOnPubId;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from DelegatePublic entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class DelegatePublicTest {
@Test(dataProvider = "publicId-matchedUri")
public void testMatch(String publicId, String matchedUri) {
checkPubIdResolution(createResolver(), publicId, matchedUri);
}
@DataProvider(name = "publicId-matchedUri")
private Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified public id is defined in
// a delegate catalog file of the current catalog file.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://local/dtd/docAlicePub.dtd" },
// The current catalog file defines two delegatePublic entries
// with the same publicIdStartString, and both of them match the
// specified public id. But the matched URI should be in the
// delegate catalog file, which is defined in the upper
// delegatePublic entry.
{ "-//REMOTE//DTD BOB DOCBOB XML//EN",
"http://local/base/dtd/bob/docBobPub.dtd" },
// The current catalog file defines two delegatePublic entries,
// and both of them match the specified public id. But the
// matched URI should be in the delegate catalog file, which is
// defined in the longest matched delegatePublic entry.
{ "-//REMOTE//DTD CARL DOCCARL XML//EN",
"http://local/base/dtd/carl/docCarlPub.dtd" } };
}
@Test(dataProvider = "publicId-expectedExceptionClass")
public void testException(String publicId,
Class<? extends Throwable> expectedExceptionClass) {
expectExceptionOnPubId(createResolver(), publicId,
expectedExceptionClass);
}
@DataProvider(name = "publicId-expectedExceptionClass")
private Object[][] dataOnException() {
return new Object[][] {
// The matched delegatePublic entry of the specified public id
// defines a non-existing delegate catalog file. That should
// raise a RuntimeException.
{ "-//REMOTE//DTD DAVID DOCDAVID XML//EN",
RuntimeException.class },
// There's no match of the specified public id in the catalog
// structure. That should raise a CatalogException.
{ "-//REMOTE//DTD GHOST DOCGHOST XML//EN",
CatalogException.class } };
}
private CatalogResolver createResolver() {
return catalogResolver("delegatePublic.xml");
}
}

@ -0,0 +1,99 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.expectExceptionOnSysId;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from delegateSystem entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class DelegateSystemTest {
@Test(dataProvider = "systemId-matchedUri")
public void testMatch(String systemId, String matchedUri) {
checkSysIdResolution(createResolver(), systemId, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
private Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified system id is defined in
// a delegate catalog file of the current catalog file.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/alice/docAliceDS.dtd" },
// The current catalog file defines two delegateSystem entries
// with the same systemIdStartString, and both of them match the
// specified system id. But the matched URI should be in the
// delegate catalog file, which is defined in the upper
// delegateSystem entry.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/bob/docBobDS.dtd" },
// The current catalog file defines two delegateSystem entries,
// and both of them match the specified system id. But the
// matched URI should be in the delegate catalog file, which is
// defined in the longest matched delegateSystem entry.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/base/dtd/carl/docCarlDS.dtd"} };
}
@Test(dataProvider = "systemId-expectedExceptionClass")
public void testException(String systemId,
Class<? extends Throwable> expectedExceptionClass) {
expectExceptionOnSysId(createResolver(), systemId,
expectedExceptionClass);
}
@DataProvider(name = "systemId-expectedExceptionClass")
private Object[][] dataOnException() {
return new Object[][] {
// The matched delegateSystem entry of the specified system id
// defines a non-existing delegate catalog file. That should
// raise a RuntimeException.
{ "http://remote/dtd/david/docDavidDS.dtd",
RuntimeException.class },
// There's no match of the specified system id in the catalog
// structure. That should raise a CatalogException.
{ "http://ghost/xml/dtd/ghost/docGhostDS.dtd",
CatalogException.class } };
}
private CatalogResolver createResolver() {
return catalogResolver("delegateSystem.xml");
}
}

@ -0,0 +1,98 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkUriResolution;
import static catalog.ResolutionChecker.expectExceptionOnUri;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from delegateURI entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class DelegateUriTest {
@Test(dataProvider = "uri-matchedUri")
public void testMatch(String uri, String matchedUri) {
checkUriResolution(createResolver(), uri, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
private Object[][] data() {
return new Object[][] {
// The matched URI of the specified URI reference is defined in
// a delegate catalog file of the current catalog file.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/alice/docAliceDU.dtd" },
// The current catalog file defines two delegateURI entries
// with the same uriStartString, and both of them match the
// specified URI reference. But the matched URI should be in
// the delegate catalog file, which is defined in the upper
// delegateURI entry.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/bob/docBobDU.dtd" },
// The current catalog file defines two delegateURI entries,
// and both of them match the specified URI reference. But the
// matched URI should be in the delegate catalog file, which is
// defined in the longest matched delegateURI entry.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/base/dtd/carl/docCarlDU.dtd"} };
}
@Test(dataProvider = "uri-expectedExceptionClass")
public void testException(String uri,
Class<? extends Throwable> expectedExceptionClass) {
expectExceptionOnUri(createResolver(), uri, expectedExceptionClass);
}
@DataProvider(name = "uri-expectedExceptionClass")
private Object[][] dataOnException() {
return new Object[][] {
// The matched delegateURI entry of the specified URI reference
// defines a non-existing delegate catalog file. That should
// raise a RuntimeException.
{ "http://remote/dtd/david/docDavidDU.dtd",
RuntimeException.class },
// There's no match of the specified URI reference in the
// catalog structure. That should raise a CatalogException.
{ "http://ghost/xml/dtd/ghost/docGhostDS.dtd",
CatalogException.class } };
}
private CatalogUriResolver createResolver() {
return catalogUriResolver("delegateUri.xml");
}
}

@ -0,0 +1,130 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkPubIdResolution;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from system, public and uri entries respectively,
* and some of the entries are enclosed by group entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class GroupTest {
private static final String CATALOG_GROUP = "group.xml";
@Test(dataProvider = "systemId-matchedUri")
public void testMatchOnSysId(String uri, String matchedUri) {
checkSysIdResolution(createResolver(), uri, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
private Object[][] dataOnSysId() {
return new Object[][] {
// The matched URI of the specified system id is enclosed by a
// group entry.
{ "http://remote/dtd/sys/alice/docAlice.dtd",
"http://local/base/dtd/docAliceSys.dtd" },
// The matched URI of the specified system id is enclosed by a
// group entry, which defines another base.
{ "http://remote/dtd/sys/bob/docBob.dtd",
"http://local/bobBase/dtd/docBobSys.dtd" },
// The catalog file defines a set of system entries. Some of
// them are enclosed by a group entry, and others are out of the
// group entry. All of them can match the specified system id.
// But the returned matched URI should be in the first one.
{ "http://remote/dtd/sys/carl/docCarl.dtd",
"http://local/base/dtd/docCarlSys1.dtd" } };
}
@Test(dataProvider = "publicId-matchedUri")
public void testMatchOnPubId(String uri, String matchedUri) {
checkPubIdResolution(createResolver(), uri, matchedUri);
}
@DataProvider(name = "publicId-matchedUri")
private Object[][] dataOnPubId() {
return new Object[][] {
// The matched URI of the specified public id is enclosed by a
// group entry.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://local/base/dtd/docAlicePub.dtd" },
// The matched URI of the specified public id is enclosed by a
// group entry, which defines another base.
{ "-//REMOTE//DTD BOB DOCBOB XML//EN",
"http://local/bobBase/dtd/docBobPub.dtd" },
// The catalog file defines a set of public entries. Some of
// them are enclosed by a group entry, and others are out of the
// group entry. All of them can match the specified public id.
// But the returned matched URI should be in the first one.
{ "-//REMOTE//DTD CARL DOCCARL XML//EN",
"http://local/base/dtd/docCarlPub1.dtd" } };
}
@Test(dataProvider = "uri-matchedUri")
public void testMatchOnUri(String uri, String matchedUri) {
checkUriResolution(catalogUriResolver(CATALOG_GROUP), uri, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
private Object[][] dataOnUri() {
return new Object[][] {
// The matched URI of the specified URI reference is enclosed by
// a group entry.
{ "http://remote/dtd/uri/alice/docAlice.dtd",
"http://local/base/dtd/docAliceURI.dtd" },
// The matched URI of the specified URI reference is enclosed by
// a group entry, which defines another base.
{ "http://remote/dtd/uri/bob/docBob.dtd",
"http://local/bobBase/dtd/docBobURI.dtd" },
// The catalog file defines a set of uri entries. Some of
// them are enclosed by a group entry, and others are out of the
// group entry. All of them can match the specified URI reference.
// But the returned matched URI should be in the first one.
{ "http://remote/dtd/uri/alice/docAlice.dtd",
"http://local/base/dtd/docAliceURI.dtd" } };
}
private CatalogResolver createResolver() {
return catalogResolver(CATALOG_GROUP);
}
}

@ -0,0 +1,120 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.CATALOG_PUBLIC;
import static catalog.CatalogTestUtils.CATALOG_SYSTEM;
import static catalog.CatalogTestUtils.CATALOG_URI;
import static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary When catalog resolver loads catalog files, the current catalog file
* and the catalog files specified by the nextCatalog entries may not
* accessible. This case tests how does the resolver handle this issue.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class LoadCatalogTest {
private static final String CATALOG_LOADCATALOGFILES = "loadCatalogFiles.xml";
private static final String CATALOG_DUMMY = "dummy.xml";
private static final String ID_ALICE = "http://remote/dtd/alice/docAlice.dtd";
private static final String ID_DUMMY = "http://remote/dtd/doc.dtd";
@Test(dataProvider = "entityResolver")
public void testMatchOnEntityResolver(CatalogResolver resolver) {
checkSysIdResolution(resolver, ID_ALICE,
"http://local/dtd/docAliceSys.dtd");
}
@DataProvider(name = "entityResolver")
private Object[][] entityResolver() {
return new Object[][] {
// This EntityResolver loads multiple catalog files one by one.
// All of the files are available.
{ catalogResolver(CATALOG_PUBLIC, CATALOG_URI,
CATALOG_SYSTEM) },
// This EntityResolver loads multiple catalog files one by one,
// but the middle one isn't existing.
{ catalogResolver(CATALOG_PUBLIC, CATALOG_DUMMY,
CATALOG_SYSTEM) } };
}
@Test(dataProvider = "uriResolver")
public void testMatchOnUriResolver(CatalogUriResolver resolver) {
checkUriResolution(resolver, ID_ALICE,
"http://local/dtd/docAliceURI.dtd");
}
@DataProvider(name = "uriResolver")
private Object[][] uriResolver() {
return new Object[][] {
// This URIResolver loads multiple catalog files one by one.
// All of the files are available.
{ catalogUriResolver(CATALOG_PUBLIC, CATALOG_SYSTEM,
CATALOG_URI) },
// This URIResolver loads multiple catalog files one by one,
// but the middle one isn't existing.
{ catalogUriResolver(CATALOG_PUBLIC, CATALOG_DUMMY,
CATALOG_URI) } };
}
@Test(dataProvider = "catalogName",
expectedExceptions = CatalogException.class)
public void testExceptionOnEntityResolver(String[] catalogName) {
catalogResolver(catalogName).resolveEntity(null, ID_DUMMY);
}
@Test(dataProvider = "catalogName",
expectedExceptions = CatalogException.class)
public void testExceptionOnUriResolver(String[] catalogName) {
catalogUriResolver(catalogName).resolve(ID_DUMMY, null);
}
@DataProvider(name = "catalogName")
private Object[][] catalogName() {
return new Object[][] {
// This catalog file set includes null catalog files.
{ (String[]) null },
// This catalog file set includes one catalog file, but this
// catalog defines a non-existing next catalog.
{ new String[] { CATALOG_LOADCATALOGFILES } } };
}
}

@ -0,0 +1,158 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkPubIdResolution;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogResolver;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from system, public and uri entries respectively,
* but some of the entries are defined in none-current catalog files.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class NextCatalogTest {
private static final String CATALOG_NEXTCATALOGLEFT
= "nextCatalog-left.xml";
private static final String CATALOG_NEXTCATALOGRIGHT
= "nextCatalog-right.xml";
@Test(dataProvider = "systemId-matchedUri")
public void testNextCatalogOnSysId(String sytemId, String matchedUri) {
checkSysIdResolution(createEntityResolver(), sytemId, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
private Object[][] dataOnSysId() {
return new Object[][] {
// This matched URI of the specified system id is defined in a
// next catalog file.
{ "http://remote/dtd/sys/docAlice.dtd",
"http://local/base/dtd/docAliceNextLeftSys.dtd" },
// There are two matches of the specified system id. One is in
// the current catalog file, and the other is in a next catalog
// file. But finally, the returned matched URI is the one in the
// current catalog file.
{ "http://remote/dtd/sys/docBob.dtd",
"http://local/base/dtd/docBobLeftSys.dtd" },
// The matched URI of the specified system id is defined in a
// two-level next catalog file.
{ "http://remote/dtd/sys/docCarl.dtd",
"http://local/base/dtd/docCarlSys.dtd" },
// Multiple catalog files, which are defined as next catalog,
// have the matched system entries of the specified system id.
// But finally, the returned matched URI is the first found.
{ "http://remote/dtd/sys/docDuplicate.dtd",
"http://local/base/dtd/docDuplicateLeftSys.dtd" } };
}
@Test(dataProvider = "publicId-matchedUri")
public void testNextCatalogOnPubId(String publicId, String matchedUri) {
checkPubIdResolution(createEntityResolver(), publicId, matchedUri);
}
@DataProvider(name = "publicId-matchedUri")
private Object[][] dataOnPubId() {
return new Object[][] {
// This matched URI of the specified public id is defined in a
// next catalog file.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://local/base/dtd/docAliceNextLeftPub.dtd" },
// There are two matches of the specified public id. One is in
// the current catalog file, and the other is in a next catalog
// file. But finally, the returned matched URI is the one in the
// current catalog file.
{ "-//REMOTE//DTD BOB DOCBOB XML//EN",
"http://local/base/dtd/docBobLeftPub.dtd" },
// The matched URI of the specified public id is defined in a
// two-level next catalog file.
{ "-//REMOTE//DTD CARL DOCCARL XML//EN",
"http://local/base/dtd/docCarlPub.dtd" },
// Multiple catalog files, which are defined as next catalog,
// have the matched public entries of the specified public id.
// But finally, the returned matched URI is the first found.
{ "-//REMOTE//DTD DUPLICATE DOCDUPLICATE XML//EN",
"http://local/base/dtd/docDuplicateLeftPub.dtd" } };
}
@Test(dataProvider = "uri-matchedUri")
public void testNextCatalogOnUri(String uri, String matchedUri) {
checkUriResolution(createUriResolver(), uri, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
private Object[][] dataOnUri() {
return new Object[][] {
// This matched URI of the specified URI reference is defined in
// a next catalog file.
{ "http://remote/dtd/uri/docAlice.dtd",
"http://local/base/dtd/docAliceNextLeftURI.dtd" },
// There are two matches of the specified URI reference. One is
// in the current catalog file, and the other is in a next
// catalog file. But finally, the returned matched URI is the
// one in the current catalog file.
{ "http://remote/dtd/uri/docBob.dtd",
"http://local/base/dtd/docBobLeftURI.dtd" },
// The matched URI of the specified URI reference is defined in
// a two-level next catalog file.
{ "http://remote/dtd/uri/docCarl.dtd",
"http://local/base/dtd/docCarlURI.dtd" },
// Multiple catalog files, which are defined as next catalog,
// have the matched uri entries of the specified URI reference.
// But finally, the returned matched URI is the first found.
{ "http://remote/dtd/uri/docDuplicate.dtd",
"http://local/base/dtd/docDuplicateLeftURI.dtd" } };
}
private CatalogResolver createEntityResolver() {
return catalogResolver(CATALOG_NEXTCATALOGLEFT,
CATALOG_NEXTCATALOGRIGHT);
}
private CatalogUriResolver createUriResolver() {
return catalogUriResolver(CATALOG_NEXTCATALOGLEFT,
CATALOG_NEXTCATALOGRIGHT);
}
}

@ -0,0 +1,114 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkPubIdResolution;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogResolver;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Before matching identifiers and URI references, it has to normalize
* the passed identifiers and URI references. And then the catalog
* resolver uses the normalized stuff to search the counterparts in
* catalog files.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class NormalizationTest {
private static final String CATALOG_NORMALIZATION = "normalization.xml";
@Test(dataProvider = "systemId_uri-matchedUri")
public void testNormalizationOnSysId(String sytemId, String matchedUri) {
checkSysIdResolution(createEntityResolver(), sytemId, matchedUri);
}
@Test(dataProvider = "publicId-matchedUri")
public void testNormalizationOnPubId(String publicId, String matchedUri) {
checkPubIdResolution(createEntityResolver(), publicId, matchedUri);
}
@Test(dataProvider = "systemId_uri-matchedUri")
public void testNormalizationOnUri(String uri, String matchedUri) {
checkUriResolution(createUriResolver(), uri, matchedUri);
}
@DataProvider(name = "systemId_uri-matchedUri")
private Object[][] dataOnSysIdAndUri() {
return new Object[][] {
// The specified system id/URI reference contains spaces. And
// the counterparts in system/uri entries also contain spaces.
{ " http://remote/dtd/alice/docAlice.dtd ",
"http://local/base/dtd/docAliceSys.dtd" },
// The specified system id/URI reference doesn't contain space.
// But the counterparts in system/uri entries contain spaces.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/docAliceSys.dtd" },
// The specified system id/URI reference contains special chars.
{ "http://remote/dtd/bob/docBob<>\\^`{|}.dtd",
"http://local/base/dtd/docBobSys.dtd" },
// The specified system identifier/uri contains normalized chars.
{ "http://remote/dtd/bob/docBob%3C%3E%5C%5E%60%7B%7C%7D.dtd",
"http://local/base/dtd/docBobSys.dtd" } };
}
@DataProvider(name = "publicId-matchedUri")
private Object[][] dataOnPubId() {
return new Object[][] {
// The specified public id contains spaces. And the counterparts
// in public entry also contains spaces.
{ " -//REMOTE//DTD ALICE DOCALICE XML//EN ",
"http://local/base/dtd/docAlicePub.dtd" },
// The specified public id doesn't contain space. But the
// counterpart in public entry contains spaces.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://local/base/dtd/docAlicePub.dtd" },
// The specified public id contains spaces.
{ " -//REMOTE//DTD BOB DOCBOB XML//EN",
"http://local/base/dtd/docBobPub.dtd" } };
}
private CatalogResolver createEntityResolver() {
return catalogResolver(CATALOG_NORMALIZATION);
}
private CatalogUriResolver createUriResolver() {
return catalogUriResolver(CATALOG_NORMALIZATION);
}
}

@ -0,0 +1,79 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.PREFER_PUBLIC;
import static catalog.CatalogTestUtils.PREFER_SYSTEM;
import static catalog.CatalogTestUtils.catalogResolver;
import static javax.xml.catalog.CatalogFeatures.Feature.PREFER;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary This case tests how does the feature affect the catalog resolution,
* and tests the priority between this feature and attribute prefer
* in catalog file.
* @compile ../../libs/catalog/CatalogTestUtils.java
*/
public class PreferFeatureTest {
@Test(dataProvider = "prefer-publicId-systemId",
expectedExceptions = CatalogException.class)
public void testPreferFeature(String prefer, String systemId,
String publicId) {
createResolver(prefer).resolveEntity(systemId, publicId);
}
@DataProvider(name = "prefer-publicId-systemId")
private Object[][] data() {
return new Object[][] {
// The feature prefer is system. There's a match for the
// specified public id, and no match for the specified system id.
// But the resolver cannot find the expected match, and raises a
// CatalogException.
{ PREFER_SYSTEM, "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://remote/dtd/alice/docAliceDummy.dtd" },
// The feature prefer is public, and the prefer attribute of a
// group entry is system. There's a match for the specified
// public id, and no match for the specified system id. But the
// resolver still cannot find the expected match, and raises a
// CatalogException.
{ PREFER_PUBLIC, "-//REMOTE//DTD BOB DOCBOB XML//EN",
"http://remote/dtd/bob/docBobDummy.dtd"} };
}
private CatalogResolver createResolver(String prefer) {
return catalogResolver(
CatalogFeatures.builder().with(PREFER, prefer).build(),
"preferFeature.xml");
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkExtIdResolution;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from system and public family entries, which
* specify the prefer attribute. It tests how does the prefer attribute
* affect the resolution procedure. The test rule is based on OASIS
* Standard V1.1 section 4.1.1. "The prefer attribute".
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class PreferTest {
@Test(dataProvider = "publicId-systemId-matchedUri")
public void testPrefer(String publicId, String systemId,
String expected) {
checkExtIdResolution(createResolver(), publicId, systemId, expected);
}
@DataProvider(name = "publicId-systemId-matchedUri")
private Object[][] data() {
return new Object[][] {
// The prefer attribute is public. Both of the specified public
// id and system id have matches in the catalog file. But
// finally, the returned URI is the system match.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/docAliceSys.dtd" },
// The prefer attribute is public, and only the specified system
// id has match. The returned URI is the system match.
{ "-//REMOTE//DTD ALICE DOCALICEDUMMY XML//EN",
"http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/docAliceSys.dtd"},
// The prefer attribute is public, and only the specified public
// id has match. The returned URI is the system match.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://remote/dtd/alice/docAliceDummy.dtd",
"http://local/base/dtd/docAlicePub.dtd" },
// The prefer attribute is system, and both of the specified
// system id and public id have matches. But the returned URI is
// the system match.
{ "-//REMOTE//DTD BOB DOCBOB XML//EN",
"http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobSys.dtd" },
// The prefer attribute is system, and only system id has match.
// The returned URI is the system match.
{ "-//REMOTE//DTD BOB DOCBOBDUMMY XML//EN",
"http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobSys.dtd" } };
}
private CatalogResolver createResolver() {
return catalogResolver("prefer.xml");
}
}

@ -0,0 +1,69 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkPubIdResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from public and delegatePublic entries.
* It tests the resolution priorities among the public family entries.
* The test rule is based on OASIS Standard V1.1 section 7.1.2.
* "Resolution of External Identifiers".
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class PublicFamilyTest {
/*
* Gets the best match from public and delegatePublic entries.
* The match in public entry is prior to the match in delegatePublic entry.
*/
@Test
public void testMatch() {
checkPubIdResolution(createResolver(),
"-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://local/base/dtd/docAlicePub.dtd");
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatched() {
checkNoMatch(createResolver());
}
private CatalogResolver createResolver() {
return catalogResolver("publicFamily.xml");
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.CATALOG_PUBLIC;
import static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkPubIdResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from public entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class PublicTest {
@Test(dataProvider = "publicId-matchedUri")
public void testPublic(String publicId, String matchedUri) {
checkPubIdResolution(createResolver(), publicId, matchedUri);
}
@DataProvider(name = "publicId-matchedUri")
public Object[][] data() {
return new Object[][] {
// The matched URI of the specified public id is defined in a
// public entry. The match is an absolute path.
{ "-//REMOTE//DTD ALICE DOCALICE XML//EN",
"http://local/dtd/docAlicePub.dtd" },
// The matched URI of the specified public id is defined in a
// public entry. But the match isn't an absolute path, so the
// returned URI should include the base, which is defined by the
// catalog file, as the prefix.
{ "-//REMOTE//DTD BOB DOCBOB XML//EN",
"http://local/base/dtd/docBobPub.dtd" },
// The matched URI of the specified public id is defined in a
// public entry. The match isn't an absolute path, and the
// public entry defines alternative base. So the returned URI
// should include the alternative base.
{ "-//REMOTE//DTD CARL DOCCARL XML//EN",
"http://local/carlBase/dtd/docCarlPub.dtd" },
// The catalog file defines two public entries, and both of them
// match the specified public id. But the first matched URI
// should be returned.
{ "-//REMOTE//DTD DAVID DOCDAVID XML//EN",
"http://local/base/dtd/docDavidPub1.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogResolver createResolver() {
return catalogResolver(CATALOG_PUBLIC);
}
}

@ -0,0 +1,130 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.CATALOG_SYSTEM;
import static catalog.CatalogTestUtils.CATALOG_URI;
import static catalog.CatalogTestUtils.RESOLVE_CONTINUE;
import static catalog.CatalogTestUtils.RESOLVE_IGNORE;
import static catalog.CatalogTestUtils.RESOLVE_STRICT;
import static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import static javax.xml.catalog.CatalogFeatures.builder;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.catalog.CatalogFeatures.Feature;
import javax.xml.catalog.CatalogResolver;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary This case tests how does resolve feature affect the catalog
* resolution.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class ResolveFeatureTest {
/*
* For strict external identifier resolution, if no match is found,
* it should throw CatalogException.
*/
@Test(expectedExceptions = CatalogException.class)
public void testStrictResolutionOnEntityResolver() {
createEntityResolver(RESOLVE_STRICT).resolveEntity(null,
"http://remote/dtd/alice/docAliceDummy.dtd");
}
/*
* For strict URI reference resolution, if no match is found,
* it should throw CatalogException.
*/
@Test(expectedExceptions = CatalogException.class)
public void testStrictResolutionOnUriResolver() {
createUriResolver(RESOLVE_STRICT).resolve(
"http://remote/dtd/alice/docAliceDummy.dtd", null);
}
/*
* For continue external identifier resolution, if no match is found,
* it should continue the process.
*/
@Test
public void testContinueResolutionOnEntityResolver() {
CatalogResolver resolver = createEntityResolver(RESOLVE_CONTINUE);
resolver.resolveEntity(null, "http://remote/dtd/bob/docBobDummy.dtd");
checkSysIdResolution(resolver, "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobSys.dtd");
}
/*
* For continue URI reference resolution, if no match is found,
* it should continue the process.
*/
@Test
public void testContinueResolutionOnUriResolver() {
CatalogUriResolver resolver = createUriResolver(RESOLVE_CONTINUE);
resolver.resolve("http://remote/dtd/bob/docBobDummy.dtd", null);
checkUriResolution(resolver, "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobURI.dtd");
}
/*
* For ignore external identifier resolution, if no match is found,
* it should break the process and return null.
*/
@Test
public void testIgnoreResolutionOnEntityResolver() {
checkSysIdResolution(createEntityResolver(RESOLVE_IGNORE),
"http://remote/dtd/carl/docCarlDummy.dtd", null);
}
/*
* For ignore URI reference resolution, if no match is found,
* it should break the process and return null.
*/
@Test
public void testIgnoreResolutionOnUriResolver() {
checkUriResolution(createUriResolver(RESOLVE_IGNORE),
"http://remote/dtd/carl/docCarlDummy.dtd", null);
}
private CatalogResolver createEntityResolver(String resolve) {
return catalogResolver(createFeature(resolve), CATALOG_SYSTEM);
}
private CatalogUriResolver createUriResolver(String resolve) {
return catalogUriResolver(createFeature(resolve), CATALOG_URI);
}
private CatalogFeatures createFeature(String resolve) {
return builder().with(Feature.RESOLVE, resolve).build();
}
}

@ -0,0 +1,94 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkSysIdResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from rewriteSystem entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class RewriteSystemTest {
@Test(dataProvider = "systemId-matchedUri")
public void testMatch(String systemId, String matchedUri) {
checkSysIdResolution(createResolver(), systemId, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified system id is defined in a
// rewriteSystem entry. The match is an absolute path.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/alice/rs/docAlice.dtd" },
// The matched URI of the specified system id is defined in a
// rewriteSystem entry. The match isn't an absolute path.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/bob/rs/docBob.dtd" },
// The matched URI of the specified system id is defined in a
// rewriteSystem entry. The match isn't an absolute path, and
// the rewriteSystem entry defines alternative base. So the
// returned URI should include the alternative base.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/carlBase/dtd/carl/rs/docCarl.dtd" },
// The catalog file defines two rewriteSystem entries, and both
// of them match the specified system id. But the first matched
// URI should be returned.
{ "http://remote/dtd/david/docDavid.dtd",
"http://local/base/dtd/david1/rs/docDavid.dtd" },
// The catalog file defines two rewriteSystem entries, and both
// of them match the specified system id. But the longest match
// should be used.
{ "http://remote/dtd/ella/docElla.dtd",
"http://local/base/dtd/ella/rs/docElla.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogResolver createResolver() {
return catalogResolver("rewriteSystem.xml");
}
}

@ -0,0 +1,94 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from rewriteURI entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class RewriteUriTest {
@Test(dataProvider = "uri-matchedUri")
public void testMatch(String uri, String matchedUri) {
checkUriResolution(createResolver(), uri, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified URI reference is defined in
// a rewriteURI entry. The match is an absolute path.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/alice/ru/docAlice.dtd" },
// The matched URI of the specified URI reference is defined in
// a rewriteURI entry. The match isn't an absolute path.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/bob/ru/docBob.dtd" },
// The matched URI of the specified URI reference is defined in
// a rewriteURI entry. The match isn't an absolute path, and the
// rewriteURI entry defines alternative base. So the returned
// URI should include the alternative base.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/carlBase/dtd/carl/ru/docCarl.dtd" },
// The catalog file defines two rewriteURI entries, and both of
// them match the specified URI reference. But the first matched
// URI should be returned.
{ "http://remote/dtd/david/docDavid.dtd",
"http://local/base/dtd/david1/ru/docDavid.dtd" },
// The catalog file defines two rewriteURI entries, and both
// of them match the specified URI reference. But the longest
// match should be used.
{ "http://remote/dtd/ella/docElla.dtd",
"http://local/base/dtd/ella/ru/docElla.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogUriResolver createResolver() {
return catalogUriResolver("rewriteUri.xml");
}
}

@ -0,0 +1,108 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.FEATURE_FILES;
import static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.CatalogTestUtils.getCatalogPath;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import static javax.xml.catalog.CatalogFeatures.builder;
import static javax.xml.catalog.CatalogFeatures.Feature.FILES;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.catalog.CatalogResolver;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary This case tests how to specify the catalog files.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class SpecifyCatalogTest {
private static final String ID_URI = "http://remote/dtd/uri/doc.dtd";
private static final String ID_SYS = "http://remote/dtd/sys/doc.dtd";
private static final CatalogFeatures FILES_FEATURE = createFeature(
"specifyCatalog-feature.xml");
/*
* CatalogResolver specifies catalog via feature javax.xml.catalog.files.
*/
@Test
public void specifyCatalogOnEntityResolver() {
checkSysIdResolution(catalogResolver(FILES_FEATURE, (String[]) null),
ID_SYS, "http://local/base/dtd/docFeatureSys.dtd");
}
/*
* CatalogUriResolver specifies catalog via feature javax.xml.catalog.files.
*/
@Test
public void specifyCatalogOnUriResolver() {
checkUriResolution(catalogUriResolver(FILES_FEATURE, (String[]) null),
ID_URI, "http://local/base/dtd/docFeatureURI.dtd");
}
/*
* Resolver specifies catalog via system property javax.xml.catalog.files.
*/
@Test
public void specifyCatalogViaSysProps() {
System.setProperty(FEATURE_FILES,
getCatalogPath("specifyCatalog-sysProps.xml"));
checkResolutionOnEntityResolver(catalogResolver((String[]) null),
"http://local/base/dtd/docSysPropsSys.dtd");
checkResolutionOnEntityResolver(
catalogResolver(FILES_FEATURE, "specifyCatalog-api.xml"),
"http://local/base/dtd/docAPISys.dtd");
checkResolutionOnUriResolver(catalogUriResolver((String[]) null),
"http://local/base/dtd/docSysPropsURI.dtd");
checkResolutionOnUriResolver(
catalogUriResolver(FILES_FEATURE, "specifyCatalog-api.xml"),
"http://local/base/dtd/docAPIURI.dtd");
}
private void checkResolutionOnEntityResolver(CatalogResolver resolver,
String matchedUri) {
checkSysIdResolution(resolver, ID_SYS, matchedUri);
}
private void checkResolutionOnUriResolver(CatalogUriResolver resolver,
String matchedUri) {
checkUriResolution(resolver, ID_URI, matchedUri);
}
private static CatalogFeatures createFeature(String catalogName) {
return builder().with(FILES, getCatalogPath(catalogName)).build();
}
}

@ -0,0 +1,83 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkSysIdResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from system, rewriteSystem, systemSuffix and
* delegateSystem entries. It tests the resolution priorities among
* the system family entries. The test rule is based on OASIS
* Standard V1.1 section 7.1.2. "Resolution of External Identifiers".
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class SystemFamilyTest {
@Test(dataProvider = "systemId-matchedUri")
public void testMatch(String systemId, String matchedUri) {
checkSysIdResolution(createResolver(), systemId, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified system id is defined in a
// system entry.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/docAliceSys.dtd" },
// The matched URI of the specified system id is defined in a
// rewriteSystem entry.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/rs/docBob.dtd" },
// The matched URI of the specified system id is defined in a
// systemSuffix entry.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/base/dtd/docCarlSS.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogResolver createResolver() {
return catalogResolver("systemFamily.xml");
}
}

@ -0,0 +1,94 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkSysIdResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from systemSuffix entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class SystemSuffixTest {
@Test(dataProvider = "systemId-matchedUri")
public void testMatch(String systemId, String matchedUri) {
checkSysIdResolution(createResolver(), systemId, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified system id is defined in a
// systemIdSuffix entry. The match is an absolute path.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/docAliceSS.dtd" },
// The matched URI of the specified system id is defined in a
// systemIdSuffix entry. The match isn't an absolute path.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobSS.dtd" },
// The matched URI of the specified system id is defined in a
// systemIdSuffix entry. The match isn't an absolute path, and
// the systemIdSuffix entry defines alternative base. So the
// returned URI should include the alternative base.
{ "http://remote/dtd/carl/cdocCarl.dtd",
"http://local/carlBase/dtd/docCarlSS.dtd" },
// The catalog file defines two systemIdSuffix entries, and both
// of them match the specified system id. But the first matched
// URI should be returned.
{ "http://remote/dtd/david/docDavid.dtd",
"http://local/base/dtd/docDavidSS1.dtd" },
// The catalog file defines two systemIdSuffix entries, and both
// of them match the specified system id. But the longest match
// should be used.
{ "http://remote/dtd/ella/docElla.dtd",
"http://local/base/dtd/docEllaSS.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogResolver createResolver() {
return catalogResolver("systemSuffix.xml");
}
}

@ -0,0 +1,91 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.CATALOG_SYSTEM;
import static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkSysIdResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from system entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class SystemTest {
@Test(dataProvider = "systemId-matchedUri")
public void testMatch(String systemId, String matchedUri) {
checkSysIdResolution(createResolver(), systemId, matchedUri);
}
@DataProvider(name = "systemId-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified system id is defined in a
// system entry. The match is an absolute path.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/docAliceSys.dtd" },
// The matched URI of the specified system id is defined in a
// public entry. But the match isn't an absolute path, so the
// returned URI should include the base, which is defined by the
// catalog file, as the prefix.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobSys.dtd" },
// The matched URI of the specified system id is defined in a
// system entry. The match isn't an absolute path, and the
// system entry defines alternative base. So the returned URI
// should include the alternative base.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/carlBase/dtd/docCarlSys.dtd" },
// The catalog file defines two system entries, and both of them
// match the specified system id. But the first matched URI
// should be returned.
{ "http://remote/dtd/david/docDavid.dtd",
"http://local/base/dtd/docDavidSys1.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogResolver createResolver() {
return catalogResolver(CATALOG_SYSTEM);
}
}

@ -0,0 +1,83 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from uri, rewriteURI, uriSuffix and delegateURI
* entries. It tests the resolution priorities among the uri family
* entries. The test rule is based on OASIS Standard V1.1 section
* 7.2.2. "Resolution of External Identifiers".
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class UriFamilyTest {
@Test(dataProvider = "uri-matchedUri")
public void testMatch(String systemId, String matchedUri) {
checkUriResolution(createResolver(), systemId, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified URI reference is defined in
// a uri entry.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/base/dtd/docAliceURI.dtd" },
// The matched URI of the specified URI reference is defined in
// a rewriteURI entry.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/ru/docBob.dtd" },
// The matched URI of the specified URI reference is defined in
// a uriSuffix entry.
{ "http://remote/dtd/carl/docCarl.dtd",
"http://local/base/dtd/docCarlUS.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogUriResolver createResolver() {
return catalogUriResolver("uriFamily.xml");
}
}

@ -0,0 +1,94 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from rewriteURI entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class UriSuffixTest {
@Test(dataProvider = "uri-matchedUri")
public void testMatch(String uri, String matchedUri) {
checkUriResolution(createResolver(), uri, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified URI reference is defined in
// a uriSuffix entry. The match is an absolute path.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/docAliceUS.dtd" },
// The matched URI of the specified URI reference is defined in
// a uriSuffix entry. The match isn't an absolute path.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobUS.dtd" },
// The matched URI of the specified URI reference is defined in
// a uriSuffix entry. The match isn't an absolute path, and the
// uriSuffix entry defines alternative base. So the returned
// URI should include the alternative base.
{ "http://remote/dtd/carl/cdocCarl.dtd",
"http://local/carlBase/dtd/docCarlUS.dtd" },
// The catalog file defines two uriSuffix entries, and both of
// them match the specified URI reference. But the first matched
// URI should be returned.
{ "http://remote/dtd/david/docDavid.dtd",
"http://local/base/dtd/docDavidUS1.dtd" },
// The catalog file defines two uriSuffix entries, and both
// of them match the specified URI reference. But the longest
// match should be used.
{ "http://remote/dtd/ella/docElla.dtd",
"http://local/base/dtd/docEllaUS.dtd" } };
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogUriResolver createResolver() {
return catalogUriResolver("uriSuffix.xml");
}
}

@ -0,0 +1,103 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.CATALOG_URI;
import static catalog.CatalogTestUtils.RESOLVE_CONTINUE;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkNoMatch;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogException;
import javax.xml.catalog.CatalogFeatures;
import javax.xml.catalog.CatalogUriResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary Get matched URIs from uri entries.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class UriTest {
@Test(dataProvider = "uri-matchedUri")
public void testMatch(String uri, String matchedUri) {
checkUriResolution(createResolver(), uri, matchedUri);
}
@DataProvider(name = "uri-matchedUri")
public Object[][] dataOnMatch() {
return new Object[][] {
// The matched URI of the specified URI reference is defined in
// a uri entry. The match is an absolute path.
{ "http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/docAliceURI.dtd" },
// The matched URI of the specified URI reference is defined in
// a uri entry. But the match isn't an absolute path, so the
// returned URI should include the base, which is defined by the
// catalog file, as the prefix.
{ "http://remote/dtd/bob/docBob.dtd",
"http://local/base/dtd/docBobURI.dtd" },
// The catalog file defines two uri entries, and both of them
// match the specified URI reference. But the first matched URI
// should be returned.
{ "http://remote/dtd/david/docDavid.dtd",
"http://local/base/dtd/docDavidURI1.dtd" } };
}
/*
* Specify base location via method CatalogUriResolver.resolve(href, base).
*/
@Test
public void testSpecifyBaseByAPI() {
checkUriResolution(createResolver(),
"http://remote/dtd/carl/docCarl.dtd",
"http://local/carlBase/dtd/docCarlURI.dtd");
CatalogUriResolver continueResolver = catalogUriResolver(
CatalogFeatures.builder().with(CatalogFeatures.Feature.RESOLVE,
RESOLVE_CONTINUE).build(), CATALOG_URI);
checkUriResolution(continueResolver, "docCarl.dtd",
"http://local/alternativeBase/dtd/",
"http://local/alternativeBase/dtd/docCarl.dtd");
}
/*
* If no match is found, a CatalogException should be thrown.
*/
@Test(expectedExceptions = CatalogException.class)
public void testNoMatch() {
checkNoMatch(createResolver());
}
private CatalogUriResolver createResolver() {
return catalogUriResolver(CATALOG_URI);
}
}

@ -0,0 +1,66 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.catalogResolver;
import static catalog.ResolutionChecker.checkPubIdResolution;
import javax.xml.catalog.CatalogResolver;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary If the passed public identifier is started with "urn:publicid:",
* it has to be regarded as URN and normalized. And then the catalog
* resolver uses the normalized stuff to do matching.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class UrnUnwrappingTest {
@Test(dataProvider = "urn-matchedUri")
public void testUnwrapping(String urn, String matchedUri) {
checkPubIdResolution(createResolver(), urn, matchedUri);
}
@DataProvider(name = "urn-matchedUri")
private Object[][] data() {
return new Object[][] {
// The specified public id is URN format.
{ "urn:publicid:-:REMOTE:DTD+ALICE+DOCALICE+XML:EN",
"http://local/base/dtd/docAlicePub.dtd" },
// The specified public id includes some special URN chars.
{ "urn:publicid:-:REMOTE:DTD+BOB+DOCBOB+;+%2B+%3A+%2F+%3B+%27"
+ "+%3F+%23+%25:EN",
"http://local/base/dtd/docBobPub.dtd" } };
}
private CatalogResolver createResolver() {
return catalogResolver("urnUnwrapping.xml");
}
}

@ -0,0 +1,101 @@
/*
* Copyright (c) 2015, 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 static catalog.CatalogTestUtils.CATALOG_SYSTEM;
import static catalog.CatalogTestUtils.CATALOG_URI;
import static catalog.CatalogTestUtils.catalogResolver;
import static catalog.CatalogTestUtils.catalogUriResolver;
import static catalog.ResolutionChecker.checkSysIdResolution;
import static catalog.ResolutionChecker.checkUriResolution;
import javax.xml.catalog.CatalogException;
import org.testng.annotations.Test;
/*
* @test
* @bug 8077931
* @summary A legal catalog file must be well-formed XML, the root element
* must be catalog, and the naming space of the root element must be
* urn:oasis:names:tc:entity:xmlns:xml:catalog.
* @compile ../../libs/catalog/CatalogTestUtils.java
* @compile ../../libs/catalog/ResolutionChecker.java
*/
public class ValidateCatalogTest {
private static final String CATALOG_WRONGROOT = "validateCatalog-wrongRoot.xml";
private static final String CATALOG_MALFORMED = "validateCatalog-malformed.xml";
/*
* EntityResolver tries to load catalog with wrong root,
* it should throw CatalogException.
*/
@Test(expectedExceptions = CatalogException.class)
public void validateWrongRootCatalogOnEntityResolver() {
catalogResolver(CATALOG_WRONGROOT);
}
/*
* URIResolver tries to load catalog with wrong root,
* it should throw CatalogException.
*/
@Test(expectedExceptions = CatalogException.class)
public void validateWrongRootCatalogOnUriResolver() {
catalogUriResolver(CATALOG_WRONGROOT);
}
/*
* EntityResolver tries to load malformed catalog,
* it should throw RuntimeException.
*/
@Test(expectedExceptions = RuntimeException.class)
public void validateMalformedCatalogOnEntityResolver() {
catalogResolver(CATALOG_MALFORMED);
}
/*
* UriResolver tries to load malformed catalog,
* it should throw RuntimeException.
*/
@Test(expectedExceptions = RuntimeException.class)
public void validateMalformedCatalogOnUriResolver() {
catalogUriResolver(CATALOG_MALFORMED);
}
/*
* Resolver should ignore the catalog which doesn't declare the correct
* naming space.
*/
@Test
public void validateWrongNamingSpaceCatalog() {
String catalogName = "validateCatalog-noNamingSpace.xml";
checkSysIdResolution(catalogResolver(catalogName, CATALOG_SYSTEM),
"http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/docAliceSys.dtd");
checkUriResolution(catalogUriResolver(catalogName, CATALOG_URI),
"http://remote/dtd/alice/docAlice.dtd",
"http://local/dtd/docAliceURI.dtd");
}
}

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<nextCatalog catalog="catalogReferCircle-itself.xml" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<nextCatalog catalog="catalogReferCircle-right.xml" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<nextCatalog catalog="catalogReferCircle-left.xml" />
</catalog>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceSys.dtd" />
<uri name="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceURI.dtd" />
<delegateSystem systemIdStartString="http://remote/dtd/alice/" catalog="delegateSystem-alice.xml" />
<delegatePublic publicIdStartString="-//REMOTE//DTD ALICE DOCALICE" catalog="delegatePublic-alice.xml" />
<nextCatalog catalog="nextCatalog-rightAlice.xml" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="http://local/dtd/docAlicePub.dtd" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/bob/">
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/carl/">
<public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub.dtd" />
</catalog>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<delegatePublic publicIdStartString="-//REMOTE//DTD ALICE DOCALICE" catalog="delegatePublic-alice.xml" />
<!-- delegateSystem-bobDummy.xml is not existing -->
<delegatePublic publicIdStartString="-//REMOTE//DTD BOB DOCBOB" catalog="delegatePublic-bob.xml" />
<delegatePublic publicIdStartString="-//REMOTE//DTD BOB DOCBOB" catalog="delegatePublic-bobDummy.xml" />
<!-- delegateSystem-carlDummy.xml is not existing -->
<delegatePublic publicIdStartString="-//REMOTE//DTD CARL DOCCARL" catalog="delegatePublic-carlDummy.xml" />
<delegatePublic publicIdStartString="-//REMOTE//DTD CARL DOCCARL XML" catalog="delegatePublic-carl.xml" />
<!-- delegateSystem-david.xml is not existing -->
<delegatePublic publicIdStartString="-//REMOTE//DTD DAVID DOCDAVID" catalog="delegatePublic-david.xml" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/alice/">
<system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceDS.dtd" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/bob/">
<system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobDS.dtd" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/carl/">
<system systemId="http://remote/dtd/carl/docCarl.dtd" uri="docCarlDS.dtd" />
</catalog>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<delegateSystem systemIdStartString="http://remote/dtd/alice/" catalog="delegateSystem-alice.xml" />
<!-- delegateSystem-bobDummy.xml is not existing -->
<delegateSystem systemIdStartString="http://remote/dtd/" catalog="delegateSystem-bobDummy.xml" />
<delegateSystem systemIdStartString="http://remote/dtd/bob/" catalog="delegateSystem-bob.xml" />
<!-- delegateSystem-carlDummy.xml is not existing -->
<delegateSystem systemIdStartString="http://remote/dtd/carl/" catalog="delegateSystem-carl.xml" />
<delegateSystem systemIdStartString="http://remote/dtd/carl/" catalog="delegateSystem-carlDummy.xml" />
<!-- delegateSystem-carlDummy.xml is not existing -->
<delegateSystem systemIdStartString="http://remote/dtd/david/" catalog="delegateSystem-davidDummy.xml" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/alice/">
<uri name="http://remote/dtd/alice/docAlice.dtd" uri="docAliceDU.dtd" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/bob/">
<uri name="http://remote/dtd/bob/docBob.dtd" uri="docBobDU.dtd" />
</catalog>

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/carl/">
<uri name="http://remote/dtd/carl/docCarl.dtd" uri="docCarlDU.dtd" />
</catalog>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<delegateURI uriStartString="http://remote/dtd/alice/" catalog="delegateUri-alice.xml" />
<delegateURI uriStartString="http://remote/dtd/" catalog="delegateUri-bobDummy.xml" />
<delegateURI uriStartString="http://remote/dtd/bob/" catalog="delegateUri-bob.xml" />
<delegateURI uriStartString="http://remote/dtd/carl/" catalog="delegateUri-carl.xml" />
<delegateURI uriStartString="http://remote/dtd/carl/" catalog="delegateUri-carlDummy.xml" />
<delegateURI uriStartString="http://remote/dtd/david/" catalog="delegateUri-davidDummy.xml" />
</catalog>

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<group>
<system systemId="http://remote/dtd/sys/alice/docAlice.dtd" uri="docAliceSys.dtd" />
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
<uri name="http://remote/dtd/uri/alice/docAlice.dtd" uri="docAliceURI.dtd" />
</group>
<group xml:base="http://local/bobBase/dtd/">
<system systemId="http://remote/dtd/sys/bob/docBob.dtd" uri="docBobSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
<uri name="http://remote/dtd/uri/bob/docBob.dtd" uri="docBobURI.dtd" />
</group>
<system systemId="http://remote/dtd/sys/carl/docCarl.dtd" uri="docCarlSys1.dtd" />
<public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub1.dtd" />
<uri name="http://remote/dtd/uri/carl/docCarl.dtd" uri="docCarlURI1.dtd" />
<group>
<system systemId="http://remote/dtd/sys/carl/docCarl.dtd" uri="docCarlSys2.dtd" />
<public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub2.dtd" />
<uri name="http://remote/dtd/uri/carl/docCarl.dtd" uri="docCarlURI2.dtd" />
</group>
<system systemId="http://remote/dtd/sys/carl/docCarl.dtd" uri="docCarlSys3.dtd" />
<public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub3.dtd" />
<uri name="http://remote/dtd/uri/carl/docCarl.dtd" uri="docCarlURI3.dtd" />
</catalog>

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE catalog
PUBLIC "-//OASIS//DTD XML Catalogs V1.1//EN"
"http://www.oasis-open.org/committees/entity/release/1.1/catalog.dtd">
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<nextCatalog catalog="nextCatalog-dummy.xml" />
</catalog>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<nextCatalog catalog="nextCatalog-leftAlice.xml" />
<nextCatalog catalog="nextCatalog-leftBob.xml" />
<group xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobLeftSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobLeftPub.dtd" />
<uri name="http://remote/dtd/uri/docBob.dtd" uri="docBobLeftURI.dtd" />
</group>
</catalog>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docAlice.dtd" uri="docAliceNextLeftSys.dtd" />
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAliceNextLeftPub.dtd" />
<uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextLeftURI.dtd" />
<system systemId="http://remote/dtd/sys/docDuplicate.dtd" uri="docDuplicateLeftSys.dtd" />
<public publicId="-//REMOTE//DTD DUPLICATE DOCDUPLICATE XML//EN" uri="docDuplicateLeftPub.dtd" />
<uri name="http://remote/dtd/uri/docDuplicate.dtd" uri="docDuplicateLeftURI.dtd" />
<systemSuffix systemIdSuffix="ss/doc.dtd" uri="docSSShorter.dtd" />
<rewriteSystem systemIdStartString="http://remote/dtd/rs/" rewritePrefix="http://local/base/dtd/rsShorter/" />
<uriSuffix uriSuffix="us/doc.dtd" uri="docUSShorter.dtd" />
<rewriteURI uriStartString="http://remote/dtd/ru/" rewritePrefix="http://local/base/dtd/ruShorter/" />
</catalog>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<group xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobNextLeftSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobNextLeftPub.dtd" />
<uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextLeftURI.dtd" />
</group>
<nextCatalog catalog="nextCatalog-leftCarl.xml" />
</catalog>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docCarl.dtd" uri="docCarlSys.dtd" />
<public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub.dtd" />
<uri name="http://remote/dtd/uri/docCarl.dtd" uri="docCarlURI.dtd" />
</catalog>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<nextCatalog catalog="nextCatalog-rightAlice.xml" />
<nextCatalog catalog="nextCatalog-rightAlice.xml" />
<group xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobLeftSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobLeftPub.dtd" />
<uri name="http://remote/dtd/uri/docBob.dtd" uri="docBobLeftURI.dtd" />
</group>
<system systemId="http://remote/dtd/sys/docDuplicate.dtd" uri="docDuplicateRightSys.dtd" />
<public publicId="-//REMOTE//DTD DUPLICATE DOCDUPLICATE XML//EN" uri="docDuplicateRightPub.dtd" />
<uri name="http://remote/dtd/uri/docDuplicate.dtd" uri="docDuplicateRightURI.dtd" />
</catalog>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docAlice.dtd" uri="docAliceNextRightSys.dtd" />
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAliceNextRightPub.dtd" />
<uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextRightURI.dtd" />
</catalog>

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/docBob.dtd" uri="docBobNextRightSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobNextRightPub.dtd" />
<uri name="http://remote/dtd/uri/docAlice.dtd" uri="docAliceNextRightURI.dtd" />
</catalog>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId=" http://remote/dtd/alice/docAlice.dtd " uri="docAliceSys.dtd" />
<system systemId="http://remote/dtd/bob/docBob&lt;&gt;\^`{|}.dtd" uri="docBobSys.dtd" />
<uri name=" http://remote/dtd/alice/docAlice.dtd " uri="docAliceSys.dtd" />
<uri name="http://remote/dtd/bob/docBob&lt;&gt;\^`{|}.dtd" uri="docBobSys.dtd" />
<public publicId=" -//REMOTE//DTD ALICE DOCALICE XML//EN " uri="docAlicePub.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
</catalog>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<group prefer="public">
<system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceSys.dtd" />
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
</group>
<group prefer="system">
<system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
</group>
</catalog>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceSys.dtd" />
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
<group prefer="system">
<system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobSys.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
</group>
</catalog>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="http://local/dtd/docAlicePub.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB XML//EN" uri="docBobPub.dtd" />
<public publicId="-//REMOTE//DTD CARL DOCCARL XML//EN" uri="docCarlPub.dtd" xml:base="http://local/carlBase/dtd/" />
<public publicId="-//REMOTE//DTD DAVID DOCDAVID XML//EN" uri="docDavidPub1.dtd" />
<public publicId="-//REMOTE//DTD DAVID DOCDAVID XML//EN" uri="docDavidPub2.dtd" />
</catalog>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<delegatePublic publicIdStartString="-//REMOTE//DTD ALICE DOCALICE" catalog="delegatePublic-alice.xml" />
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
</catalog>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<rewriteSystem systemIdStartString="http://remote/dtd/alice/" rewritePrefix="http://local/dtd/alice/rs/" />
<rewriteSystem systemIdStartString="http://remote/dtd/bob/" rewritePrefix="bob/rs/" />
<rewriteSystem systemIdStartString="http://remote/dtd/carl/" rewritePrefix="carl/rs/"
xml:base="http://local/carlBase/dtd/" />
<rewriteSystem systemIdStartString="http://remote/dtd/david/" rewritePrefix="david1/rs/" />
<rewriteSystem systemIdStartString="http://remote/dtd/david/" rewritePrefix="david2/rs/" />
<rewriteSystem systemIdStartString="http://remote/dtd/" rewritePrefix="ella/" />
<rewriteSystem systemIdStartString="http://remote/dtd/ella/" rewritePrefix="ella/rs/" />
</catalog>

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<rewriteURI uriStartString="http://remote/dtd/alice/" rewritePrefix="http://local/dtd/alice/ru/" />
<rewriteURI uriStartString="http://remote/dtd/bob/" rewritePrefix="bob/ru/" />
<rewriteURI uriStartString="http://remote/dtd/carl/" rewritePrefix="carl/ru/"
xml:base="http://local/carlBase/dtd/" />
<rewriteURI uriStartString="http://remote/dtd/david/" rewritePrefix="david1/ru/" />
<rewriteURI uriStartString="http://remote/dtd/david/" rewritePrefix="david2/ru/" />
<rewriteURI uriStartString="http://remote/dtd/" rewritePrefix="ella/" />
<rewriteURI uriStartString="http://remote/dtd/ella/" rewritePrefix="ella/ru/" />
</catalog>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/doc.dtd" uri="docAPISys.dtd" />
<uri name="http://remote/dtd/uri/doc.dtd" uri="docAPIURI.dtd" />
</catalog>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/doc.dtd" uri="docFeatureSys.dtd" />
<uri name="http://remote/dtd/uri/doc.dtd" uri="docFeatureURI.dtd" />
</catalog>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/sys/doc.dtd" uri="docSysPropsSys.dtd" />
<uri name="http://remote/dtd/uri/doc.dtd" uri="docSysPropsURI.dtd" />
</catalog>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<system systemId="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceSys.dtd" />
<system systemId="http://remote/dtd/bob/docBob.dtd" uri="docBobSys.dtd" />
<system systemId="http://remote/dtd/carl/docCarl.dtd" uri="docCarlSys.dtd" xml:base="http://local/carlBase/dtd/" />
<system systemId="http://remote/dtd/david/docDavid.dtd" uri="docDavidSys1.dtd" />
<system systemId="http://remote/dtd/david/docDavid.dtd" uri="docDavidSys2.dtd" />
</catalog>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<delegateSystem systemIdStartString="http://remote/dtd/alice/" catalog="delegateSystem-alice.xml" />
<systemSuffix systemIdSuffix="docAlice.dtd" uri="docAliceSS.dtd" />
<rewriteSystem systemIdStartString="http://remote/dtd/alice/" rewritePrefix="http://local/base/rs/" />
<system systemId="http://remote/dtd/alice/docAlice.dtd" uri="docAliceSys.dtd" />
<delegateSystem systemIdStartString="http://remote/dtd/bob/" catalog="delegateSystem-bob.xml" />
<systemSuffix systemIdSuffix="docBob.dtd" uri="docBobSS.dtd" />
<rewriteSystem systemIdStartString="http://remote/dtd/bob/" rewritePrefix="http://local/base/dtd/rs/" />
<delegateSystem systemIdStartString="http://remote/dtd/carl/" catalog="delegateSystem-carl.xml" />
<systemSuffix systemIdSuffix="docCarl.dtd" uri="docCarlSS.dtd" />
</catalog>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<systemSuffix systemIdSuffix="docAlice.dtd" uri="http://local/dtd/docAliceSS.dtd" />
<systemSuffix systemIdSuffix="docBob.dtd" uri="docBobSS.dtd" />
<systemSuffix systemIdSuffix="docCarl.dtd" uri="docCarlSS.dtd" xml:base="http://local/carlBase/dtd/" />
<systemSuffix systemIdSuffix="docDavid.dtd" uri="docDavidSS1.dtd" />
<systemSuffix systemIdSuffix="docDavid.dtd" uri="docDavidSS2.dtd" />
<systemSuffix systemIdSuffix="docElla.dtd" uri="/" />
<systemSuffix systemIdSuffix="ella/docElla.dtd" uri="docEllaSS.dtd" />
</catalog>

@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<uri name="http://remote/dtd/alice/docAlice.dtd" uri="http://local/dtd/docAliceURI.dtd" />
<uri name="http://remote/dtd/bob/docBob.dtd" uri="docBobURI.dtd" />
<uri name="http://remote/dtd/carl/docCarl.dtd" uri="docCarlURI.dtd" xml:base="http://local/carlBase/dtd/" />
<uri name="http://remote/dtd/david/docDavid.dtd" uri="docDavidURI1.dtd" />
<uri name="http://remote/dtd/david/docDavid.dtd" uri="docDavidURI2.dtd" />
</catalog>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<delegateURI uriStartString="http://remote/dtd/alice/" catalog="delegateURI-alice.xml" />
<uriSuffix uriSuffix="docAlice.dtd" uri="docAliceUS.dtd" />
<rewriteURI uriStartString="http://remote/dtd/alice/" rewritePrefix="http://local/base/ru/" />
<uri name="http://remote/dtd/alice/docAlice.dtd" uri="docAliceURI.dtd" />
<delegateURI uriStartString="http://remote/dtd/bob/" catalog="delegateURI-bob.xml" />
<uriSuffix uriSuffix="docBob.dtd" uri="docBobUS.dtd" />
<rewriteURI uriStartString="http://remote/dtd/bob/" rewritePrefix="http://local/base/dtd/ru/" />
<delegateURI uriStartString="http://remote/dtd/carl/" catalog="delegateURI-carl.xml" />
<uriSuffix uriSuffix="docCarl.dtd" uri="docCarlUS.dtd" />
</catalog>

@ -0,0 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<uriSuffix uriSuffix="docAlice.dtd" uri="http://local/dtd/docAliceUS.dtd" />
<uriSuffix uriSuffix="docBob.dtd" uri="docBobUS.dtd" />
<uriSuffix uriSuffix="docCarl.dtd" uri="docCarlUS.dtd" xml:base="http://local/carlBase/dtd/" />
<uriSuffix uriSuffix="docDavid.dtd" uri="docDavidUS1.dtd" />
<uriSuffix uriSuffix="docDavid.dtd" uri="docDavidUS2.dtd" />
<uriSuffix uriSuffix="docElla.dtd" uri="/" />
<uriSuffix uriSuffix="ella/docElla.dtd" uri="docEllaUS.dtd" />
</catalog>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog" xml:base="http://local/base/dtd/">
<public publicId="-//REMOTE//DTD ALICE DOCALICE XML//EN" uri="docAlicePub.dtd" />
<public publicId="-//REMOTE//DTD BOB DOCBOB :: + : / ; ' ? # %//EN" uri="docBobPub.dtd" />
</catalog>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- This catalog is malformed XML -->
<catalog xmlns="urn:oasis:names:tc:entity:xmlns:xml:catalog">
<system systemId="http://remote/dtd/doc.dtd" uri="docSys.dtd" />
</cat>

Some files were not shown because too many files have changed in this diff Show More