/*
* Copyright (c) 2015, 2017, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. 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.MalformedURLException;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.Map;
import jdk.xml.internal.SecuritySupport;
The CatalogFeatures holds a collection of features and properties.
Catalog Features
Feature
Description
Property Name
System Property [1]
jaxp.properties [1]
Value [2]
Action
Type
Value
FILES
A semicolon-delimited list of URIs to locate the catalog files.
The URIs must be absolute and have a URL protocol handler for the URI scheme.
javax.xml.catalog.files
javax.xml.catalog.files
javax.xml.catalog.files
String
URIs
Reads the first catalog as the current catalog; Loads others if no match
is found in the current catalog including delegate catalogs if any.
PREFER
Indicates the preference between the public and system
identifiers. The default value is public [3].
javax.xml.catalog.prefer
N/A
N/A
String
system
Searches system entries for a match; Searches public entries when
external identifier specifies only a public identifier
public
Searches system entries for a match; Searches public entries when
there is no matching system entry.
DEFER
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.
javax.xml.catalog.defer [4]
javax.xml.catalog.defer
javax.xml.catalog.defer
String
true
Loads alternative catalogs as needed.
false
Loads all catalogs[5].
RESOLVE
Determines the action if there is no matching entry found after
all of the specified catalogs are exhausted. The default is strict.
javax.xml.catalog.resolve [4]
javax.xml.catalog.resolve
javax.xml.catalog.resolve
String
strict
Throws CatalogException if there is no match.
continue
Allows the XML parser to continue as if there is no match.
ignore
Tells the XML parser to skip the external references if there no match.
[1] There is no System property for the features that marked as "N/A".
[2] The value shall be exactly as listed in this table, case-sensitive. Any unspecified value will result in IllegalArgumentException
.
[3] The Catalog specification defined complex rules on
the prefer attribute. 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).
[4] Although non-standard attributes in the OASIS Catalog specification, defer
and resolve
are recognized by the Java Catalog API the same as the 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.
[5] If the intention is to share an entire catalog store, it may be desirable to set the property javax.xml.catalog.defer
to false to allow the entire catalog to be pre-loaded.
Scope and Order
Features and properties can be set through the catalog file, the Catalog API, system properties, and jaxp.properties
, with a preference in the same order. 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 prefer
attribute is set in the catalog file as in <catalog prefer="public">
, any other input for the "prefer" property is not necessary or will be ignored.
Properties set through the Catalog API override those that may have been set by system properties and/or in jaxp.properties
. In case of multiple interfaces, the latest in a procedure shall take preference. For Feature.FILES
, this means that the URI(s) specified through the methods of the CatalogManager
will override any that may have been entered through the Builder
.
System properties when set shall override those in jaxp.properties
.
The 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 jaxp.properties
after it has been read.
A CatalogFeatures instance can be created through its builder as illustrated
in the following sample code:
CatalogFeatures f = CatalogFeatures.builder()
.with(Feature.FILES, "file:///etc/xml/catalog")
.with(Feature.PREFER, "public")
.with(Feature.DEFER, "true")
.with(Feature.RESOLVE, "ignore")
.build();
JAXP XML Processor Support
The Catalog Features are supported throughout the JAXP processors, including SAX and DOM (parsers
), and StAX parsers (stream
), Schema Validation (validation
), and XML Transformation (transform
). The features described above can be set through JAXP factories or processors that define a setProperty or setAttribute interface. For example, the following code snippet sets a URI to a catalog file on a SAX parser through the javax.xml.catalog.files
property:
SAXParserFactory spf = SAXParserFactory.newInstance();
spf.setFeature(XMLConstants.USE_CATALOG, true); [1]
SAXParser parser = spf.newSAXParser();
parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "file:///etc/xml/catalog");
[1] Note that this statement is not required since the default value of USE_CATALOG
is true.
The JAXP Processors' support for Catalog depends on both the USE_CATALOG
feature and the existence of valid Catalog file(s). A JAXP processor will use the Catalog only when the feature is true and valid Catalog file(s) are specified through the javax.xml.catalog.files
property. It will make no attempt to use the Catalog if either USE_CATALOG
is set to false, or there is no Catalog file specified.
The JAXP processors will observe the default settings of the CatalogFeatures
. The processors, for example, will report an Exception by default when no matching entry is found since the default value of the javax.xml.catalog.resolve
property is strict.
The JAXP processors give preference to user-specified custom resolvers. If such
a resolver is registered, it will be used over the CatalogResolver. If it returns
null however, the processors will continue resolving with the CatalogResolver.
If it returns an empty source, no attempt will be made by the CatalogResolver.
The Catalog support is available for any process in the JAXP library that
supports a resolver. The following table lists all such processes.
Processes with Catalog Support
Processes with Catalog Support
Process
Catalog Entry Type
Example
DTDs and external entities
public, system
The following DTD reference:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Can be resolved using the following Catalog entry:
<public publicId="-//W3C//DTD XHTML 1.0 Strict//EN" uri="catalog/xhtml1-strict.dtd"/>
or
<systemSuffix systemIdSuffix="html1-strict.dtd" uri="catalog/xhtml1-strict.dtd"/>
XInclude
uri
The following XInclude element:
<xi:include href="http://openjdk.java.net/xml/disclaimer.xml"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xml/disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
or
<uriSuffix uriSuffix="disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
XSD import
uri
The following import element:
<xsd:import namespace="http://openjdk.java.net/xsd/XSDImport_person"
schemaLocation="http://openjdk.java.net/xsd/XSDImport_person.xsd"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsd/XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
or
<uriSuffix uriSuffix="XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
or
<uriSuffix uriSuffix="http://openjdk.java.net/xsd/XSDImport_person" uri="file:///pathto/local/XSDImport_person.xsd"/>
XSD include
uri
The following include element:
<xsd:include schemaLocation="http://openjdk.java.net/xsd/XSDInclude_person.xsd"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsd/XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
or
<uriSuffix uriSuffix="XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
XSL import and include
uri
The following include element:
<xsl:include href="http://openjdk.java.net/xsl/include.xsl"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsl/include.xsl" uri="file:///pathto/local/include.xsl"/>
or
<uriSuffix uriSuffix="include.xsl" uri="file:///pathto/local/include.xsl"/>
XSL document function
uri
The document in the following element:
<xsl:variable name="dummy" select="document('http://openjdk.java.net/xsl/list.xml')"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsl/list.xml" uri="file:///pathto/local/list.xml"/>
or
<uriSuffix uriSuffix="list.xml" uri="file:///pathto/local/list.xml"/>
Since: 9
/**
* The CatalogFeatures holds a collection of features and properties.
* <p>
*
*
* <table class="plain">
* <caption>Catalog Features</caption>
* <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" style="text-align:center">Value [2]</th>
* <th rowspan="2">Action</th>
* </tr>
* <tr>
* <th>Type</th>
* <th>Value</th>
* </tr>
* </thead>
* <tbody>
*
* <tr>
* <td><a id="FILES">FILES</a></td>
* <td>A semicolon-delimited list of URIs to locate the catalog files.
* The URIs must be absolute and have a URL protocol handler for the URI scheme.
* </td>
* <td>javax.xml.catalog.files</td>
* <td>javax.xml.catalog.files</td>
* <td>javax.xml.catalog.files</td>
* <td>String</td>
* <td>URIs</td>
* <td>
* Reads the first catalog as the current catalog; Loads others if no match
* is found in the current catalog including delegate catalogs if any.
* </td>
* </tr>
*
* <tr>
* <td rowspan="2"><a id="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 id="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 id="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 URI(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, "file:///etc/xml/catalog")
.with(Feature.PREFER, "public")
.with(Feature.DEFER, "true")
.with(Feature.RESOLVE, "ignore")
.build();
* }</pre>
*
* <p>
* <h3>JAXP XML Processor Support</h3>
* The Catalog Features are supported throughout the JAXP processors, including
* SAX and DOM ({@link javax.xml.parsers}), and StAX parsers ({@link javax.xml.stream}),
* Schema Validation ({@link javax.xml.validation}), and XML Transformation
* ({@link javax.xml.transform}). The features described above can be set through JAXP
* factories or processors that define a setProperty or setAttribute interface.
* For example, the following code snippet sets a URI to a catalog file on a SAX
* parser through the {@code javax.xml.catalog.files} property:
* <p>
* <pre>{@code
* SAXParserFactory spf = SAXParserFactory.newInstance();
* spf.setFeature(XMLConstants.USE_CATALOG, true); [1]
* SAXParser parser = spf.newSAXParser();
* parser.setProperty(CatalogFeatures.Feature.FILES.getPropertyName(), "file:///etc/xml/catalog");
* }</pre>
* <p>
* [1] Note that this statement is not required since the default value of
* {@link javax.xml.XMLConstants#USE_CATALOG USE_CATALOG} is true.
*
* <p>
* The JAXP Processors' support for Catalog depends on both the
* {@link javax.xml.XMLConstants#USE_CATALOG USE_CATALOG} feature and the
* existence of valid Catalog file(s). A JAXP processor will use the Catalog
* only when the feature is true and valid Catalog file(s) are specified through
* the {@code javax.xml.catalog.files} property. It will make no attempt to use
* the Catalog if either {@link javax.xml.XMLConstants#USE_CATALOG USE_CATALOG}
* is set to false, or there is no Catalog file specified.
*
* <p>
* The JAXP processors will observe the default settings of the
* {@link javax.xml.catalog.CatalogFeatures}. The processors, for example, will
* report an Exception by default when no matching entry is found since the
* default value of the {@code javax.xml.catalog.resolve} property is strict.
*
* <p>
* The JAXP processors give preference to user-specified custom resolvers. If such
* a resolver is registered, it will be used over the CatalogResolver. If it returns
* null however, the processors will continue resolving with the CatalogResolver.
* If it returns an empty source, no attempt will be made by the CatalogResolver.
*
* <p>
* The Catalog support is available for any process in the JAXP library that
* supports a resolver. The following table lists all such processes.
*
* <p>
* <h3><a id="ProcessesWithCatalogSupport">Processes with Catalog Support</a></h3>
*
* <table class="striped">
* <caption>Processes with Catalog Support</caption>
* <thead>
* <tr>
* <th>Process</th>
* <th>Catalog Entry Type</th>
* <th>Example</th>
* </tr>
* </thead>
* <tbody>
* <tr>
* <td>DTDs and external entities</td>
* <td>public, system</td>
* <td>
* <pre>{@literal
The following DTD reference:
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
Can be resolved using the following Catalog entry:
<public publicId="-//W3C//DTD XHTML 1.0 Strict//EN" uri="catalog/xhtml1-strict.dtd"/>
or
<systemSuffix systemIdSuffix="html1-strict.dtd" uri="catalog/xhtml1-strict.dtd"/>
* }</pre>
* </td>
* </tr>
* <tr>
* <td>XInclude</td>
* <td>uri</td>
* <td>
* <pre>{@literal
The following XInclude element:
<xi:include href="http://openjdk.java.net/xml/disclaimer.xml"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xml/disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
or
<uriSuffix uriSuffix="disclaimer.xml" uri="file:///pathto/local/disclaimer.xml"/>
* }</pre>
* </td>
* </tr>
* <tr>
* <td>XSD import</td>
* <td>uri</td>
* <td>
* <pre>{@literal
The following import element:
<xsd:import namespace="http://openjdk.java.net/xsd/XSDImport_person"
schemaLocation="http://openjdk.java.net/xsd/XSDImport_person.xsd"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsd/XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
or
<uriSuffix uriSuffix="XSDImport_person.xsd" uri="file:///pathto/local/XSDImport_person.xsd"/>
or
<uriSuffix uriSuffix="http://openjdk.java.net/xsd/XSDImport_person" uri="file:///pathto/local/XSDImport_person.xsd"/>
* }</pre>
* </td>
* </tr>
* <tr>
* <td>XSD include</td>
* <td>uri</td>
* <td>
* <pre>{@literal
The following include element:
<xsd:include schemaLocation="http://openjdk.java.net/xsd/XSDInclude_person.xsd"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsd/XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
or
<uriSuffix uriSuffix="XSDInclude_person.xsd" uri="file:///pathto/local/XSDInclude_person.xsd"/>
* }</pre>
* </td>
* </tr>
* <tr>
* <td>XSL import and include</td>
* <td>uri</td>
* <td>
* <pre>{@literal
The following include element:
<xsl:include href="http://openjdk.java.net/xsl/include.xsl"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsl/include.xsl" uri="file:///pathto/local/include.xsl"/>
or
<uriSuffix uriSuffix="include.xsl" uri="file:///pathto/local/include.xsl"/>
* }</pre>
* </td>
* </tr>
* <tr>
* <td>XSL document function</td>
* <td>uri</td>
* <td>
* <pre>{@literal
The document in the following element:
<xsl:variable name="dummy" select="document('http://openjdk.java.net/xsl/list.xml')"/>
can be resolved using a URI entry:
<uri name="http://openjdk.java.net/xsl/list.xml" uri="file:///pathto/local/list.xml"/>
or
<uriSuffix uriSuffix="list.xml" uri="file:///pathto/local/list.xml"/>
* }</pre>
* </td>
* </tr>
* </tbody>
* </table>
*
* @since 9
*/
public class CatalogFeatures {
The constant name of the javax.xml.catalog.files property as described
in the property table above.
/**
* The constant name of the javax.xml.catalog.files property as described
* in the property table above.
*/
static final String CATALOG_FILES = "javax.xml.catalog.files";
The javax.xml.catalog.prefer property as described
in the property table above.
/**
* The javax.xml.catalog.prefer property as described
* in the property table above.
*/
static final String CATALOG_PREFER = "javax.xml.catalog.prefer";
The javax.xml.catalog.defer property as described
in the property table above.
/**
* The javax.xml.catalog.defer property as described
* in the property table above.
*/
static final String CATALOG_DEFER = "javax.xml.catalog.defer";
The javax.xml.catalog.resolve property as described
in the property table above.
/**
* The javax.xml.catalog.resolve property as described
* in the property table above.
*/
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
Catalog Features table.
/**
* A Feature type as defined in the
* <a href="CatalogFeatures.html#CatalogFeatures">Catalog Features table</a>.
*/
public static enum Feature {
The javax.xml.catalog.files
property as described in item FILES of the
Catalog Features table.
/**
* 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 javax.xml.catalog.prefer
property as described in item PREFER of the
Catalog Features table.
/**
* 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 javax.xml.catalog.defer
property as described in item DEFER of the
Catalog Features table.
/**
* 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 javax.xml.catalog.resolve
property as described in item RESOLVE of the
Catalog Features table.
/**
* 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.
Params: - name – the name of the feature
- value – the value of the feature
- hasSystem – a flag to indicate whether the feature is supported
with a System property
/**
* 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.
Params: - propertyName – the name of a property
Returns: true if the specified property is the current property, false
otherwise
/**
* 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.
Returns: the name of the System Property
/**
* 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.
Returns: the default value of the property
/**
* Returns the default value of the property.
* @return the default value of the property
*/
public String defaultValue() {
return defaultValue;
}
Returns the value of the property.
Returns: the value of the property
/**
* 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.
Returns: true it is supported, false otherwise
/**
* 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
/**
* 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. /** represents the default state of a feature. */
DEFAULT("default"),
indicates the value of the feature is read from jaxp.properties. /** 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. /** 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. /** 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. /** 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
/**
* Values of the properties
*/
private String[] values;
States of the settings for each property
/**
* States of the settings for each property
*/
private State[] states;
Private class constructor
/**
* Private class constructor
*/
private CatalogFeatures() {
}
Returns a CatalogFeatures instance with default settings.
Returns: a default CatalogFeatures instance
/**
* 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.
Params: - builder – the builder to build the CatalogFeatures
/**
* Constructs a new CatalogFeatures instance with the builder.
*
* @param builder the builder to build the CatalogFeatures
*/
CatalogFeatures(Builder builder) {
init();
setProperties(builder);
}
Returns the value of the specified feature.
Params: - cf – the type of the Catalog feature
Returns: the value of the feature
/**
* 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
/**
* 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, State.DEFAULT, cf.defaultValue());
}
//read system properties or jaxp.properties
readSystemProperties();
}
Sets properties by the Builder.
Params: - builder – the CatalogFeatures builder
/**
* Sets properties by the Builder.
* @param builder the CatalogFeatures builder
*/
private void setProperties(Builder builder) {
builder.values.entrySet().stream().forEach((entry) -> {
setProperty(entry.getKey(), State.APIPROPERTY, entry.getValue());
});
}
Sets the value of a property, updates only if it shall override.
Params: - index – the index of the property
- state – the state of the property
- value – the value of the property
Throws: - IllegalArgumentException – if the value is invalid
/**
* Sets the value of a property, updates only if it shall override.
*
* @param index the index of the property
* @param state the state of the property
* @param value the value of the property
* @throws IllegalArgumentException if the value is invalid
*/
private void setProperty(Feature feature, State state, String value) {
int index = feature.ordinal();
if (value != null && value.length() != 0) {
if (state != State.APIPROPERTY) {
Util.validateFeatureInput(feature, value);
}
if (states[index] == null || state.compareTo(states[index]) >= 0) {
values[index] = value;
states[index] = state;
}
}
}
Reads from system properties, or those in jaxp.properties
/**
* 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
Params: - cf – the type of the property
- sysPropertyName – the name of system property
/**
* 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, State.SYSTEMPROPERTY, value);
return true;
}
value = SecuritySupport.readJAXPProperty(sysPropertyName);
if (value != null && !value.equals("")) {
setProperty(cf, State.JAXPDOTPROPERTIES, value);
return true;
}
}
return false;
}
Returns an instance of the builder for creating the CatalogFeatures object.
Returns: an instance of the builder
/**
* 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.
/**
* The Builder class for building the CatalogFeatures object.
*/
public static class Builder {
Values of the features supported by CatalogFeatures.
/**
* Values of the features supported by CatalogFeatures.
*/
Map<Feature, String> values = new HashMap<>();
Instantiation of Builder is not allowed.
/**
* Instantiation of Builder is not allowed.
*/
private Builder() {}
Sets the value to a specified Feature.
Params: - feature – the Feature to be set
- value – the value to be set for the Feature
Throws: - IllegalArgumentException – if the value is not valid for the Feature or has the wrong syntax for the
javax.xml.catalog.files
property
Returns: this Builder instance
/**
* 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) {
Util.validateFeatureInput(feature, value);
values.put(feature, value);
return this;
}
Returns a CatalogFeatures object built by this builder.
Returns: an instance of CatalogFeatures
/**
* Returns a CatalogFeatures object built by this builder.
*
* @return an instance of CatalogFeatures
*/
public CatalogFeatures build() {
return new CatalogFeatures(this);
}
}
}