8005954: JAXP Plugability Layer should use java.util.ServiceLoader
This fix replaces manual processing of files under META-INF/services in JAXP factories by calls to java.util.ServiceLoader. Reviewed-by: alanb, joehw, mchung
This commit is contained in:
parent
b10f2efea3
commit
9a94591b8e
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2004, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,14 +26,12 @@
|
|||||||
package javax.xml.datatype;
|
package javax.xml.datatype;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
import java.security.AccessController;
|
||||||
import java.io.IOException;
|
import java.security.PrivilegedAction;
|
||||||
import java.io.InputStream;
|
import java.util.Iterator;
|
||||||
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.io.BufferedReader;
|
import java.util.ServiceConfigurationError;
|
||||||
import java.io.InputStreamReader;
|
import java.util.ServiceLoader;
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Implements pluggable Datatypes.</p>
|
* <p>Implements pluggable Datatypes.</p>
|
||||||
@ -54,19 +52,19 @@ class FactoryFinder {
|
|||||||
/**
|
/**
|
||||||
* Cache for properties in java.home/lib/jaxp.properties
|
* Cache for properties in java.home/lib/jaxp.properties
|
||||||
*/
|
*/
|
||||||
static Properties cacheProps = new Properties();
|
private final static Properties cacheProps = new Properties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag indicating if properties from java.home/lib/jaxp.properties
|
* Flag indicating if properties from java.home/lib/jaxp.properties
|
||||||
* have been cached.
|
* have been cached.
|
||||||
*/
|
*/
|
||||||
static volatile boolean firstTime = true;
|
private static volatile boolean firstTime = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security support class use to check access control before
|
* Security support class use to check access control before
|
||||||
* getting certain system resources.
|
* getting certain system resources.
|
||||||
*/
|
*/
|
||||||
static SecuritySupport ss = new SecuritySupport();
|
private final static SecuritySupport ss = new SecuritySupport();
|
||||||
|
|
||||||
// Define system property "jaxp.debug" to get output
|
// Define system property "jaxp.debug" to get output
|
||||||
static {
|
static {
|
||||||
@ -99,31 +97,31 @@ class FactoryFinder {
|
|||||||
*
|
*
|
||||||
* Use bootstrap classLoader if cl = null and useBSClsLoader is true
|
* Use bootstrap classLoader if cl = null and useBSClsLoader is true
|
||||||
*/
|
*/
|
||||||
static private Class getProviderClass(String className, ClassLoader cl,
|
static private Class<?> getProviderClass(String className, ClassLoader cl,
|
||||||
boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
|
boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
if (useBSClsLoader) {
|
if (useBSClsLoader) {
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
} else {
|
} else {
|
||||||
cl = ss.getContextClassLoader();
|
cl = ss.getContextClassLoader();
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
throw new ClassNotFoundException();
|
throw new ClassNotFoundException();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e1) {
|
catch (ClassNotFoundException e1) {
|
||||||
if (doFallback) {
|
if (doFallback) {
|
||||||
// Use current class loader - should always be bootstrap CL
|
// Use current class loader - should always be bootstrap CL
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e1;
|
throw e1;
|
||||||
@ -135,6 +133,9 @@ class FactoryFinder {
|
|||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to
|
||||||
|
* instantiate.
|
||||||
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
*
|
*
|
||||||
@ -144,16 +145,19 @@ class FactoryFinder {
|
|||||||
* @param doFallback True if the current ClassLoader should be tried as
|
* @param doFallback True if the current ClassLoader should be tried as
|
||||||
* a fallback if the class is not found using cl
|
* a fallback if the class is not found using cl
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl, boolean doFallback)
|
||||||
throws ConfigurationError
|
throws DatatypeConfigurationException
|
||||||
{
|
{
|
||||||
return newInstance(className, cl, doFallback, false);
|
return newInstance(type, className, cl, doFallback, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to
|
||||||
|
* instantiate.
|
||||||
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
*
|
*
|
||||||
@ -166,9 +170,12 @@ class FactoryFinder {
|
|||||||
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
||||||
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
|
||||||
throws ConfigurationError
|
boolean doFallback, boolean useBSClsLoader)
|
||||||
|
throws DatatypeConfigurationException
|
||||||
{
|
{
|
||||||
|
assert type != null;
|
||||||
|
|
||||||
// make sure we have access to restricted packages
|
// make sure we have access to restricted packages
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
||||||
@ -178,20 +185,23 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
||||||
|
if (!type.isAssignableFrom(providerClass)) {
|
||||||
|
throw new ClassCastException(className + " cannot be cast to " + type.getName());
|
||||||
|
}
|
||||||
Object instance = providerClass.newInstance();
|
Object instance = providerClass.newInstance();
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
if (debug) { // Extra check to avoid computing cl strings
|
||||||
dPrint("created new instance of " + providerClass +
|
dPrint("created new instance of " + providerClass +
|
||||||
" using ClassLoader: " + cl);
|
" using ClassLoader: " + cl);
|
||||||
}
|
}
|
||||||
return instance;
|
return type.cast(instance);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException x) {
|
catch (ClassNotFoundException x) {
|
||||||
throw new ConfigurationError(
|
throw new DatatypeConfigurationException(
|
||||||
"Provider " + className + " not found", x);
|
"Provider " + className + " not found", x);
|
||||||
}
|
}
|
||||||
catch (Exception x) {
|
catch (Exception x) {
|
||||||
throw new ConfigurationError(
|
throw new DatatypeConfigurationException(
|
||||||
"Provider " + className + " could not be instantiated: " + x,
|
"Provider " + className + " could not be instantiated: " + x,
|
||||||
x);
|
x);
|
||||||
}
|
}
|
||||||
@ -202,16 +212,17 @@ class FactoryFinder {
|
|||||||
* entry point.
|
* entry point.
|
||||||
* @return Class object of factory, never null
|
* @return Class object of factory, never null
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param type Base class / Service interface of the
|
||||||
* a property name
|
* factory to find.
|
||||||
* @param fallbackClassName Implementation class name, if nothing else
|
* @param fallbackClassName Implementation class name, if nothing else
|
||||||
* is found. Use null to mean no fallback.
|
* is found. Use null to mean no fallback.
|
||||||
*
|
*
|
||||||
* Package private so this code can be shared.
|
* Package private so this code can be shared.
|
||||||
*/
|
*/
|
||||||
static Object find(String factoryId, String fallbackClassName)
|
static <T> T find(Class<T> type, String fallbackClassName)
|
||||||
throws ConfigurationError
|
throws DatatypeConfigurationException
|
||||||
{
|
{
|
||||||
|
final String factoryId = type.getName();
|
||||||
dPrint("find factoryId =" + factoryId);
|
dPrint("find factoryId =" + factoryId);
|
||||||
|
|
||||||
// Use the system property first
|
// Use the system property first
|
||||||
@ -219,7 +230,7 @@ class FactoryFinder {
|
|||||||
String systemProp = ss.getSystemProperty(factoryId);
|
String systemProp = ss.getSystemProperty(factoryId);
|
||||||
if (systemProp != null) {
|
if (systemProp != null) {
|
||||||
dPrint("found system property, value=" + systemProp);
|
dPrint("found system property, value=" + systemProp);
|
||||||
return newInstance(systemProp, null, true);
|
return newInstance(type, systemProp, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SecurityException se) {
|
catch (SecurityException se) {
|
||||||
@ -228,7 +239,6 @@ class FactoryFinder {
|
|||||||
|
|
||||||
// try to read from $java.home/lib/jaxp.properties
|
// try to read from $java.home/lib/jaxp.properties
|
||||||
try {
|
try {
|
||||||
String factoryClassName = null;
|
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
synchronized (cacheProps) {
|
synchronized (cacheProps) {
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
@ -243,11 +253,11 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
factoryClassName = cacheProps.getProperty(factoryId);
|
final String factoryClassName = cacheProps.getProperty(factoryId);
|
||||||
|
|
||||||
if (factoryClassName != null) {
|
if (factoryClassName != null) {
|
||||||
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
|
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
|
||||||
return newInstance(factoryClassName, null, true);
|
return newInstance(type, factoryClassName, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
@ -255,112 +265,46 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try Jar Service Provider Mechanism
|
// Try Jar Service Provider Mechanism
|
||||||
Object provider = findJarServiceProvider(factoryId);
|
final T provider = findServiceProvider(type);
|
||||||
if (provider != null) {
|
if (provider != null) {
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
if (fallbackClassName == null) {
|
if (fallbackClassName == null) {
|
||||||
throw new ConfigurationError(
|
throw new DatatypeConfigurationException(
|
||||||
"Provider for " + factoryId + " cannot be found", null);
|
"Provider for " + factoryId + " cannot be found");
|
||||||
}
|
}
|
||||||
|
|
||||||
dPrint("loaded from fallback value: " + fallbackClassName);
|
dPrint("loaded from fallback value: " + fallbackClassName);
|
||||||
return newInstance(fallbackClassName, null, true);
|
return newInstance(type, fallbackClassName, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find provider using Jar Service Provider Mechanism
|
* Try to find provider using the ServiceLoader API
|
||||||
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to find.
|
||||||
*
|
*
|
||||||
* @return instance of provider class if found or null
|
* @return instance of provider class if found or null
|
||||||
*/
|
*/
|
||||||
private static Object findJarServiceProvider(String factoryId)
|
private static <T> T findServiceProvider(final Class<T> type)
|
||||||
throws ConfigurationError
|
throws DatatypeConfigurationException
|
||||||
{
|
{
|
||||||
String serviceId = "META-INF/services/" + factoryId;
|
|
||||||
InputStream is = null;
|
|
||||||
|
|
||||||
// First try the Context ClassLoader
|
|
||||||
ClassLoader cl = ss.getContextClassLoader();
|
|
||||||
boolean useBSClsLoader = false;
|
|
||||||
if (cl != null) {
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
|
|
||||||
// If no provider found then try the current ClassLoader
|
|
||||||
if (is == null) {
|
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
useBSClsLoader = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No Context ClassLoader, try the current ClassLoader
|
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
useBSClsLoader = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is == null) {
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
|
||||||
dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedReader rd;
|
|
||||||
try {
|
try {
|
||||||
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
return AccessController.doPrivileged(new PrivilegedAction<T>() {
|
||||||
}
|
public T run() {
|
||||||
catch (java.io.UnsupportedEncodingException e) {
|
final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
|
||||||
rd = new BufferedReader(new InputStreamReader(is));
|
final Iterator<T> iterator = serviceLoader.iterator();
|
||||||
}
|
if (iterator.hasNext()) {
|
||||||
|
return iterator.next();
|
||||||
String factoryClassName = null;
|
} else {
|
||||||
try {
|
return null;
|
||||||
// XXX Does not handle all possible input as specified by the
|
}
|
||||||
// Jar Service Provider specification
|
}
|
||||||
factoryClassName = rd.readLine();
|
});
|
||||||
rd.close();
|
} catch(ServiceConfigurationError e) {
|
||||||
} catch (IOException x) {
|
final DatatypeConfigurationException error =
|
||||||
// No provider found
|
new DatatypeConfigurationException(
|
||||||
return null;
|
"Provider for " + type + " cannot be found", e);
|
||||||
}
|
throw error;
|
||||||
|
|
||||||
if (factoryClassName != null && !"".equals(factoryClassName)) {
|
|
||||||
dPrint("found in resource, value=" + factoryClassName);
|
|
||||||
|
|
||||||
// Note: here we do not want to fall back to the current
|
|
||||||
// ClassLoader because we want to avoid the case where the
|
|
||||||
// resource file was found using one ClassLoader and the
|
|
||||||
// provider class was instantiated using a different one.
|
|
||||||
return newInstance(factoryClassName, cl, false, useBSClsLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ConfigurationError extends Error {
|
|
||||||
private Exception exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new instance with the specified detail string and
|
|
||||||
* exception.
|
|
||||||
*/
|
|
||||||
ConfigurationError(String msg, Exception x) {
|
|
||||||
super(msg);
|
|
||||||
this.exception = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exception getException() {
|
|
||||||
return exception;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* use the exception chaining mechanism of JDK1.4
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Throwable getCause() {
|
|
||||||
return exception;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -40,9 +40,6 @@ import javax.xml.validation.Schema;
|
|||||||
|
|
||||||
public abstract class DocumentBuilderFactory {
|
public abstract class DocumentBuilderFactory {
|
||||||
|
|
||||||
/** The default property name according to the JAXP spec */
|
|
||||||
private static final String DEFAULT_PROPERTY_NAME = "javax.xml.parsers.DocumentBuilderFactory";
|
|
||||||
|
|
||||||
private boolean validating = false;
|
private boolean validating = false;
|
||||||
private boolean namespaceAware = false;
|
private boolean namespaceAware = false;
|
||||||
private boolean whitespace = false;
|
private boolean whitespace = false;
|
||||||
@ -50,8 +47,6 @@ public abstract class DocumentBuilderFactory {
|
|||||||
private boolean ignoreComments = false;
|
private boolean ignoreComments = false;
|
||||||
private boolean coalescing = false;
|
private boolean coalescing = false;
|
||||||
|
|
||||||
private boolean canonicalState = false;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Protected constructor to prevent instantiation.
|
* <p>Protected constructor to prevent instantiation.
|
||||||
* Use {@link #newInstance()}.</p>
|
* Use {@link #newInstance()}.</p>
|
||||||
@ -85,14 +80,12 @@ public abstract class DocumentBuilderFactory {
|
|||||||
* of any property in jaxp.properties after it has been read for the first time.
|
* of any property in jaxp.properties after it has been read for the first time.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Use the Services API (as detailed in the JAR specification), if
|
* Uses the service-provider loading facilities, defined by the
|
||||||
* available, to determine the classname. The Services API will look
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* for a classname in the file
|
* implementation of the service.
|
||||||
* <code>META-INF/services/javax.xml.parsers.DocumentBuilderFactory</code>
|
|
||||||
* in jars available to the runtime.
|
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Platform default <code>DocumentBuilderFactory</code> instance.
|
* Otherwise, the system-default implementation is returned.
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -113,21 +106,16 @@ public abstract class DocumentBuilderFactory {
|
|||||||
*
|
*
|
||||||
* @return New instance of a <code>DocumentBuilderFactory</code>
|
* @return New instance of a <code>DocumentBuilderFactory</code>
|
||||||
*
|
*
|
||||||
* @throws FactoryConfigurationError if the implementation is not
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
* available or cannot be instantiated.
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static DocumentBuilderFactory newInstance() {
|
public static DocumentBuilderFactory newInstance() {
|
||||||
try {
|
return FactoryFinder.find(
|
||||||
return (DocumentBuilderFactory) FactoryFinder.find(
|
|
||||||
/* The default property name according to the JAXP spec */
|
/* The default property name according to the JAXP spec */
|
||||||
"javax.xml.parsers.DocumentBuilderFactory",
|
DocumentBuilderFactory.class, // "javax.xml.parsers.DocumentBuilderFactory"
|
||||||
/* The fallback implementation class name */
|
/* The fallback implementation class name */
|
||||||
"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
"com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl");
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -165,13 +153,9 @@ public abstract class DocumentBuilderFactory {
|
|||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){
|
public static DocumentBuilderFactory newInstance(String factoryClassName, ClassLoader classLoader){
|
||||||
try {
|
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
return (DocumentBuilderFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
|
return FactoryFinder.newInstance(DocumentBuilderFactory.class,
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
factoryClassName, classLoader, false);
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -391,75 +375,64 @@ public abstract class DocumentBuilderFactory {
|
|||||||
public abstract Object getAttribute(String name)
|
public abstract Object getAttribute(String name)
|
||||||
throws IllegalArgumentException;
|
throws IllegalArgumentException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Set a feature for this <code>DocumentBuilderFactory</code> and <code>DocumentBuilder</code>s created by this factory.</p>
|
* <p>Set a feature for this <code>DocumentBuilderFactory</code> and <code>DocumentBuilder</code>s created by this factory.</p>
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Feature names are fully qualified {@link java.net.URI}s.
|
|
||||||
* Implementations may define their own features.
|
|
||||||
* A {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
|
|
||||||
* <code>DocumentBuilder</code>s it creates cannot support the feature.
|
|
||||||
* It is possible for a <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
|
|
||||||
* When the feature is:</p>
|
|
||||||
* <ul>
|
|
||||||
* <li>
|
|
||||||
* <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
|
|
||||||
* Examples include enity expansion limits and XML Schema constructs that would consume large amounts of resources.
|
|
||||||
* If XML processing is limited for security reasons, it will be reported via a call to the registered
|
|
||||||
* {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
|
|
||||||
* See {@link DocumentBuilder#setErrorHandler(org.xml.sax.ErrorHandler errorHandler)}.
|
|
||||||
* </li>
|
|
||||||
* <li>
|
|
||||||
* <code>false</code>: the implementation will processing XML according to the XML specifications without
|
|
||||||
* regard to possible implementation limits.
|
|
||||||
* </li>
|
|
||||||
* </ul>
|
|
||||||
*
|
|
||||||
* @param name Feature name.
|
|
||||||
* @param value Is feature state <code>true</code> or <code>false</code>.
|
|
||||||
*
|
|
||||||
* @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code> or the <code>DocumentBuilder</code>s
|
|
||||||
* it creates cannot support this feature.
|
|
||||||
* @throws NullPointerException If the <code>name</code> parameter is null.
|
|
||||||
*/
|
|
||||||
public abstract void setFeature(String name, boolean value)
|
|
||||||
throws ParserConfigurationException;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Get the state of the named feature.</p>
|
|
||||||
*
|
|
||||||
* <p>
|
|
||||||
* Feature names are fully qualified {@link java.net.URI}s.
|
|
||||||
* Implementations may define their own features.
|
|
||||||
* An {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
|
|
||||||
* <code>DocumentBuilder</code>s it creates cannot support the feature.
|
|
||||||
* It is possible for an <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
|
|
||||||
* </p>
|
|
||||||
*
|
|
||||||
* @param name Feature name.
|
|
||||||
*
|
|
||||||
* @return State of the named feature.
|
|
||||||
*
|
|
||||||
* @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code>
|
|
||||||
* or the <code>DocumentBuilder</code>s it creates cannot support this feature.
|
|
||||||
*/
|
|
||||||
public abstract boolean getFeature(String name)
|
|
||||||
throws ParserConfigurationException;
|
|
||||||
|
|
||||||
|
|
||||||
/** <p>Get current state of canonicalization.</p>
|
|
||||||
*
|
*
|
||||||
* @return current state canonicalization control
|
* <p>
|
||||||
|
* Feature names are fully qualified {@link java.net.URI}s.
|
||||||
|
* Implementations may define their own features.
|
||||||
|
* A {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
|
||||||
|
* <code>DocumentBuilder</code>s it creates cannot support the feature.
|
||||||
|
* It is possible for a <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
|
||||||
|
* When the feature is:</p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
|
||||||
|
* Examples include enity expansion limits and XML Schema constructs that would consume large amounts of resources.
|
||||||
|
* If XML processing is limited for security reasons, it will be reported via a call to the registered
|
||||||
|
* {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
|
||||||
|
* See {@link DocumentBuilder#setErrorHandler(org.xml.sax.ErrorHandler errorHandler)}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* <code>false</code>: the implementation will processing XML according to the XML specifications without
|
||||||
|
* regard to possible implementation limits.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
*
|
||||||
|
* @param name Feature name.
|
||||||
|
* @param value Is feature state <code>true</code> or <code>false</code>.
|
||||||
|
*
|
||||||
|
* @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code> or the <code>DocumentBuilder</code>s
|
||||||
|
* it creates cannot support this feature.
|
||||||
|
* @throws NullPointerException If the <code>name</code> parameter is null.
|
||||||
*/
|
*/
|
||||||
/*
|
public abstract void setFeature(String name, boolean value)
|
||||||
public boolean getCanonicalization() {
|
throws ParserConfigurationException;
|
||||||
return canonicalState;
|
|
||||||
}
|
/**
|
||||||
*/
|
* <p>Get the state of the named feature.</p>
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Feature names are fully qualified {@link java.net.URI}s.
|
||||||
|
* Implementations may define their own features.
|
||||||
|
* An {@link ParserConfigurationException} is thrown if this <code>DocumentBuilderFactory</code> or the
|
||||||
|
* <code>DocumentBuilder</code>s it creates cannot support the feature.
|
||||||
|
* It is possible for an <code>DocumentBuilderFactory</code> to expose a feature value but be unable to change its state.
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @param name Feature name.
|
||||||
|
*
|
||||||
|
* @return State of the named feature.
|
||||||
|
*
|
||||||
|
* @throws ParserConfigurationException if this <code>DocumentBuilderFactory</code>
|
||||||
|
* or the <code>DocumentBuilder</code>s it creates cannot support this feature.
|
||||||
|
*/
|
||||||
|
public abstract boolean getFeature(String name)
|
||||||
|
throws ParserConfigurationException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -488,17 +461,6 @@ public abstract class DocumentBuilderFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* <p>Set canonicalization control to <code>true</code> or
|
|
||||||
* </code>false</code>.</p>
|
|
||||||
*
|
|
||||||
* @param state of canonicalization
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
public void setCanonicalization(boolean state) {
|
|
||||||
canonicalState = state;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Set the {@link Schema} to be used by parsers created
|
* <p>Set the {@link Schema} to be used by parsers created
|
||||||
* from this factory.
|
* from this factory.
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,15 +25,16 @@
|
|||||||
|
|
||||||
package javax.xml.parsers;
|
package javax.xml.parsers;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.security.AccessController;
|
||||||
import java.io.InputStream;
|
import java.security.PrivilegedAction;
|
||||||
import java.io.InputStreamReader;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Implements pluggable Datatypes.</p>
|
* <p>Implements pluggable Parsers.</p>
|
||||||
*
|
*
|
||||||
* <p>This class is duplicated for each JAXP subpackage so keep it in
|
* <p>This class is duplicated for each JAXP subpackage so keep it in
|
||||||
* sync. It is package private for secure class loading.</p>
|
* sync. It is package private for secure class loading.</p>
|
||||||
@ -51,7 +52,7 @@ class FactoryFinder {
|
|||||||
/**
|
/**
|
||||||
* Cache for properties in java.home/lib/jaxp.properties
|
* Cache for properties in java.home/lib/jaxp.properties
|
||||||
*/
|
*/
|
||||||
static Properties cacheProps = new Properties();
|
private static final Properties cacheProps = new Properties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag indicating if properties from java.home/lib/jaxp.properties
|
* Flag indicating if properties from java.home/lib/jaxp.properties
|
||||||
@ -63,7 +64,7 @@ class FactoryFinder {
|
|||||||
* Security support class use to check access control before
|
* Security support class use to check access control before
|
||||||
* getting certain system resources.
|
* getting certain system resources.
|
||||||
*/
|
*/
|
||||||
static SecuritySupport ss = new SecuritySupport();
|
private static final SecuritySupport ss = new SecuritySupport();
|
||||||
|
|
||||||
// Define system property "jaxp.debug" to get output
|
// Define system property "jaxp.debug" to get output
|
||||||
static {
|
static {
|
||||||
@ -96,31 +97,31 @@ class FactoryFinder {
|
|||||||
*
|
*
|
||||||
* Use bootstrap classLoader if cl = null and useBSClsLoader is true
|
* Use bootstrap classLoader if cl = null and useBSClsLoader is true
|
||||||
*/
|
*/
|
||||||
static private Class getProviderClass(String className, ClassLoader cl,
|
static private Class<?> getProviderClass(String className, ClassLoader cl,
|
||||||
boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
|
boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
if (useBSClsLoader) {
|
if (useBSClsLoader) {
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
} else {
|
} else {
|
||||||
cl = ss.getContextClassLoader();
|
cl = ss.getContextClassLoader();
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
throw new ClassNotFoundException();
|
throw new ClassNotFoundException();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e1) {
|
catch (ClassNotFoundException e1) {
|
||||||
if (doFallback) {
|
if (doFallback) {
|
||||||
// Use current class loader - should always be bootstrap CL
|
// Use current class loader - should always be bootstrap CL
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e1;
|
throw e1;
|
||||||
@ -132,6 +133,9 @@ class FactoryFinder {
|
|||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to
|
||||||
|
* instantiate.
|
||||||
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
*
|
*
|
||||||
@ -141,16 +145,20 @@ class FactoryFinder {
|
|||||||
* @param doFallback True if the current ClassLoader should be tried as
|
* @param doFallback True if the current ClassLoader should be tried as
|
||||||
* a fallback if the class is not found using cl
|
* a fallback if the class is not found using cl
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
|
||||||
throws ConfigurationError
|
boolean doFallback)
|
||||||
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return newInstance(className, cl, doFallback, false);
|
return newInstance(type, className, cl, doFallback, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to
|
||||||
|
* instantiate.
|
||||||
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
*
|
*
|
||||||
@ -163,9 +171,11 @@ class FactoryFinder {
|
|||||||
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
||||||
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
|
||||||
throws ConfigurationError
|
boolean doFallback, boolean useBSClsLoader)
|
||||||
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
|
assert type != null;
|
||||||
// make sure we have access to restricted packages
|
// make sure we have access to restricted packages
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
||||||
@ -175,22 +185,24 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
||||||
|
if (!type.isAssignableFrom(providerClass)) {
|
||||||
|
throw new ClassCastException(className + " cannot be cast to " + type.getName());
|
||||||
|
}
|
||||||
Object instance = providerClass.newInstance();
|
Object instance = providerClass.newInstance();
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
if (debug) { // Extra check to avoid computing cl strings
|
||||||
dPrint("created new instance of " + providerClass +
|
dPrint("created new instance of " + providerClass +
|
||||||
" using ClassLoader: " + cl);
|
" using ClassLoader: " + cl);
|
||||||
}
|
}
|
||||||
return instance;
|
return type.cast(instance);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException x) {
|
catch (ClassNotFoundException x) {
|
||||||
throw new ConfigurationError(
|
throw new FactoryConfigurationError(x,
|
||||||
"Provider " + className + " not found", x);
|
"Provider " + className + " not found");
|
||||||
}
|
}
|
||||||
catch (Exception x) {
|
catch (Exception x) {
|
||||||
throw new ConfigurationError(
|
throw new FactoryConfigurationError(x,
|
||||||
"Provider " + className + " could not be instantiated: " + x,
|
"Provider " + className + " could not be instantiated: " + x);
|
||||||
x);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -199,16 +211,17 @@ class FactoryFinder {
|
|||||||
* entry point.
|
* entry point.
|
||||||
* @return Class object of factory, never null
|
* @return Class object of factory, never null
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param type Base class / Service interface of the
|
||||||
* a property name
|
* factory to find.
|
||||||
* @param fallbackClassName Implementation class name, if nothing else
|
* @param fallbackClassName Implementation class name, if nothing else
|
||||||
* is found. Use null to mean no fallback.
|
* is found. Use null to mean no fallback.
|
||||||
*
|
*
|
||||||
* Package private so this code can be shared.
|
* Package private so this code can be shared.
|
||||||
*/
|
*/
|
||||||
static Object find(String factoryId, String fallbackClassName)
|
static <T> T find(Class<T> type, String fallbackClassName)
|
||||||
throws ConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
|
final String factoryId = type.getName();
|
||||||
dPrint("find factoryId =" + factoryId);
|
dPrint("find factoryId =" + factoryId);
|
||||||
|
|
||||||
// Use the system property first
|
// Use the system property first
|
||||||
@ -216,7 +229,7 @@ class FactoryFinder {
|
|||||||
String systemProp = ss.getSystemProperty(factoryId);
|
String systemProp = ss.getSystemProperty(factoryId);
|
||||||
if (systemProp != null) {
|
if (systemProp != null) {
|
||||||
dPrint("found system property, value=" + systemProp);
|
dPrint("found system property, value=" + systemProp);
|
||||||
return newInstance(systemProp, null, true);
|
return newInstance(type, systemProp, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SecurityException se) {
|
catch (SecurityException se) {
|
||||||
@ -225,7 +238,6 @@ class FactoryFinder {
|
|||||||
|
|
||||||
// try to read from $java.home/lib/jaxp.properties
|
// try to read from $java.home/lib/jaxp.properties
|
||||||
try {
|
try {
|
||||||
String factoryClassName = null;
|
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
synchronized (cacheProps) {
|
synchronized (cacheProps) {
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
@ -240,11 +252,11 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
factoryClassName = cacheProps.getProperty(factoryId);
|
final String factoryClassName = cacheProps.getProperty(factoryId);
|
||||||
|
|
||||||
if (factoryClassName != null) {
|
if (factoryClassName != null) {
|
||||||
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
|
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
|
||||||
return newInstance(factoryClassName, null, true);
|
return newInstance(type, factoryClassName, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
@ -252,112 +264,52 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try Jar Service Provider Mechanism
|
// Try Jar Service Provider Mechanism
|
||||||
Object provider = findJarServiceProvider(factoryId);
|
T provider = findServiceProvider(type);
|
||||||
if (provider != null) {
|
if (provider != null) {
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
if (fallbackClassName == null) {
|
if (fallbackClassName == null) {
|
||||||
throw new ConfigurationError(
|
throw new FactoryConfigurationError(
|
||||||
"Provider for " + factoryId + " cannot be found", null);
|
"Provider for " + factoryId + " cannot be found");
|
||||||
}
|
}
|
||||||
|
|
||||||
dPrint("loaded from fallback value: " + fallbackClassName);
|
dPrint("loaded from fallback value: " + fallbackClassName);
|
||||||
return newInstance(fallbackClassName, null, true);
|
return newInstance(type, fallbackClassName, null, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find provider using Jar Service Provider Mechanism
|
* Try to find provider using the ServiceLoader API
|
||||||
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to find.
|
||||||
*
|
*
|
||||||
* @return instance of provider class if found or null
|
* @return instance of provider class if found or null
|
||||||
*/
|
*/
|
||||||
private static Object findJarServiceProvider(String factoryId)
|
private static <T> T findServiceProvider(final Class<T> type) {
|
||||||
throws ConfigurationError
|
|
||||||
{
|
|
||||||
String serviceId = "META-INF/services/" + factoryId;
|
|
||||||
InputStream is = null;
|
|
||||||
|
|
||||||
// First try the Context ClassLoader
|
|
||||||
ClassLoader cl = ss.getContextClassLoader();
|
|
||||||
boolean useBSClsLoader = false;
|
|
||||||
if (cl != null) {
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
|
|
||||||
// If no provider found then try the current ClassLoader
|
|
||||||
if (is == null) {
|
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
useBSClsLoader = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No Context ClassLoader, try the current ClassLoader
|
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
useBSClsLoader = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is == null) {
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
|
||||||
dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedReader rd;
|
|
||||||
try {
|
try {
|
||||||
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
return AccessController.doPrivileged(new PrivilegedAction<T>() {
|
||||||
}
|
public T run() {
|
||||||
catch (java.io.UnsupportedEncodingException e) {
|
final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
|
||||||
rd = new BufferedReader(new InputStreamReader(is));
|
final Iterator<T> iterator = serviceLoader.iterator();
|
||||||
}
|
if (iterator.hasNext()) {
|
||||||
|
return iterator.next();
|
||||||
String factoryClassName = null;
|
} else {
|
||||||
try {
|
return null;
|
||||||
// XXX Does not handle all possible input as specified by the
|
}
|
||||||
// Jar Service Provider specification
|
}
|
||||||
factoryClassName = rd.readLine();
|
});
|
||||||
rd.close();
|
} catch(ServiceConfigurationError e) {
|
||||||
} catch (IOException x) {
|
// It is not possible to wrap an error directly in
|
||||||
// No provider found
|
// FactoryConfigurationError - so we need to wrap the
|
||||||
return null;
|
// ServiceConfigurationError in a RuntimeException.
|
||||||
}
|
// The alternative would be to modify the logic in
|
||||||
|
// FactoryConfigurationError to allow setting a
|
||||||
if (factoryClassName != null && !"".equals(factoryClassName)) {
|
// Throwable as the cause, but that could cause
|
||||||
dPrint("found in resource, value=" + factoryClassName);
|
// compatibility issues down the road.
|
||||||
|
final RuntimeException x = new RuntimeException(
|
||||||
// Note: here we do not want to fall back to the current
|
"Provider for " + type + " cannot be created", e);
|
||||||
// ClassLoader because we want to avoid the case where the
|
final FactoryConfigurationError error =
|
||||||
// resource file was found using one ClassLoader and the
|
new FactoryConfigurationError(x, x.getMessage());
|
||||||
// provider class was instantiated using a different one.
|
throw error;
|
||||||
return newInstance(factoryClassName, cl, false, useBSClsLoader);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ConfigurationError extends Error {
|
|
||||||
private Exception exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new instance with the specified detail string and
|
|
||||||
* exception.
|
|
||||||
*/
|
|
||||||
ConfigurationError(String msg, Exception x) {
|
|
||||||
super(msg);
|
|
||||||
this.exception = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exception getException() {
|
|
||||||
return exception;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* use the exception chaining mechanism of JDK1.4
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Throwable getCause() {
|
|
||||||
return exception;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -26,7 +26,6 @@
|
|||||||
package javax.xml.parsers;
|
package javax.xml.parsers;
|
||||||
|
|
||||||
import javax.xml.validation.Schema;
|
import javax.xml.validation.Schema;
|
||||||
|
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import org.xml.sax.SAXNotRecognizedException;
|
import org.xml.sax.SAXNotRecognizedException;
|
||||||
import org.xml.sax.SAXNotSupportedException;
|
import org.xml.sax.SAXNotSupportedException;
|
||||||
@ -42,8 +41,6 @@ import org.xml.sax.SAXNotSupportedException;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public abstract class SAXParserFactory {
|
public abstract class SAXParserFactory {
|
||||||
/** The default property name according to the JAXP spec */
|
|
||||||
private static final String DEFAULT_PROPERTY_NAME = "javax.xml.parsers.SAXParserFactory";
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Should Parsers be validating?</p>
|
* <p>Should Parsers be validating?</p>
|
||||||
@ -87,14 +84,12 @@ public abstract class SAXParserFactory {
|
|||||||
* of any property in jaxp.properties after it has been read for the first time.
|
* of any property in jaxp.properties after it has been read for the first time.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Use the Services API (as detailed in the JAR specification), if
|
* Use the service-provider loading facilities, defined by the
|
||||||
* available, to determine the classname. The Services API will look
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* for a classname in the file
|
* implementation of the service.
|
||||||
* <code>META-INF/services/javax.xml.parsers.SAXParserFactory</code>
|
|
||||||
* in jars available to the runtime.
|
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Platform default <code>SAXParserFactory</code> instance.
|
* Otherwise the system-default implementation is returned.
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -109,7 +104,7 @@ public abstract class SAXParserFactory {
|
|||||||
* this method to print a lot of debug messages
|
* this method to print a lot of debug messages
|
||||||
* to <code>System.err</code> about what it is doing and where it is looking at.</p>
|
* to <code>System.err</code> about what it is doing and where it is looking at.</p>
|
||||||
*
|
*
|
||||||
* <p> If you have problems loading {@link DocumentBuilder}s, try:</p>
|
* <p> If you have problems loading {@link SAXParser}s, try:</p>
|
||||||
* <pre>
|
* <pre>
|
||||||
* java -Djaxp.debug=1 YourProgram ....
|
* java -Djaxp.debug=1 YourProgram ....
|
||||||
* </pre>
|
* </pre>
|
||||||
@ -117,21 +112,17 @@ public abstract class SAXParserFactory {
|
|||||||
*
|
*
|
||||||
* @return A new instance of a SAXParserFactory.
|
* @return A new instance of a SAXParserFactory.
|
||||||
*
|
*
|
||||||
* @throws FactoryConfigurationError if the implementation is
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
* not available or cannot be instantiated.
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public static SAXParserFactory newInstance() {
|
public static SAXParserFactory newInstance() {
|
||||||
try {
|
return FactoryFinder.find(
|
||||||
return (SAXParserFactory) FactoryFinder.find(
|
|
||||||
/* The default property name according to the JAXP spec */
|
/* The default property name according to the JAXP spec */
|
||||||
"javax.xml.parsers.SAXParserFactory",
|
SAXParserFactory.class,
|
||||||
/* The fallback implementation class name */
|
/* The fallback implementation class name */
|
||||||
"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
|
"com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -169,13 +160,9 @@ public abstract class SAXParserFactory {
|
|||||||
* @since 1.6
|
* @since 1.6
|
||||||
*/
|
*/
|
||||||
public static SAXParserFactory newInstance(String factoryClassName, ClassLoader classLoader){
|
public static SAXParserFactory newInstance(String factoryClassName, ClassLoader classLoader){
|
||||||
try {
|
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
return (SAXParserFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
|
return FactoryFinder.newInstance(SAXParserFactory.class,
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
factoryClassName, classLoader, false);
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -266,22 +253,22 @@ public abstract class SAXParserFactory {
|
|||||||
* A list of the core features and properties can be found at
|
* A list of the core features and properties can be found at
|
||||||
* <a href="http://www.saxproject.org/">http://www.saxproject.org/</a></p>
|
* <a href="http://www.saxproject.org/">http://www.saxproject.org/</a></p>
|
||||||
*
|
*
|
||||||
* <p>All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
|
* <p>All implementations are required to support the {@link javax.xml.XMLConstants#FEATURE_SECURE_PROCESSING} feature.
|
||||||
* When the feature is</p>
|
* When the feature is</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>
|
* <li>
|
||||||
* <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
|
* <code>true</code>: the implementation will limit XML processing to conform to implementation limits.
|
||||||
* Examples include enity expansion limits and XML Schema constructs that would consume large amounts of resources.
|
* Examples include entity expansion limits and XML Schema constructs that would consume large amounts of resources.
|
||||||
* If XML processing is limited for security reasons, it will be reported via a call to the registered
|
* If XML processing is limited for security reasons, it will be reported via a call to the registered
|
||||||
* {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
|
* {@link org.xml.sax.ErrorHandler#fatalError(SAXParseException exception)}.
|
||||||
* See {@link SAXParser} <code>parse</code> methods for handler specification.
|
* See {@link SAXParser} <code>parse</code> methods for handler specification.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* When the feature is <code>false</code>, the implementation will processing XML according to the XML specifications without
|
* When the feature is <code>false</code>, the implementation will processing XML according to the XML specifications without
|
||||||
* regard to possible implementation limits.
|
* regard to possible implementation limits.
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @param name The name of the feature to be set.
|
* @param name The name of the feature to be set.
|
||||||
* @param value The value of the feature to be set.
|
* @param value The value of the feature to be set.
|
||||||
*
|
*
|
||||||
@ -320,17 +307,6 @@ public abstract class SAXParserFactory {
|
|||||||
SAXNotSupportedException;
|
SAXNotSupportedException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* <p>Get current state of canonicalization.</p>
|
|
||||||
*
|
|
||||||
* @return current state canonicalization control
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
public boolean getCanonicalization() {
|
|
||||||
return canonicalState;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the {@link Schema} object specified through
|
* Gets the {@link Schema} object specified through
|
||||||
* the {@link #setSchema(Schema schema)} method.
|
* the {@link #setSchema(Schema schema)} method.
|
||||||
@ -357,17 +333,6 @@ public abstract class SAXParserFactory {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** <p>Set canonicalization control to <code>true</code> or
|
|
||||||
* </code>false</code>.</p>
|
|
||||||
*
|
|
||||||
* @param state of canonicalization
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
public void setCanonicalization(boolean state) {
|
|
||||||
canonicalState = state;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Set the {@link Schema} to be used by parsers created
|
* <p>Set the {@link Schema} to be used by parsers created
|
||||||
* from this factory.</p>
|
* from this factory.</p>
|
||||||
@ -400,7 +365,7 @@ public abstract class SAXParserFactory {
|
|||||||
* Such configuration will cause a {@link SAXException}
|
* Such configuration will cause a {@link SAXException}
|
||||||
* exception when those properties are set on a {@link SAXParser}.</p>
|
* exception when those properties are set on a {@link SAXParser}.</p>
|
||||||
*
|
*
|
||||||
* <h4>Note for implmentors</h4>
|
* <h4>Note for implementors</h4>
|
||||||
* <p>
|
* <p>
|
||||||
* A parser must be able to work with any {@link Schema}
|
* A parser must be able to work with any {@link Schema}
|
||||||
* implementation. However, parsers and schemas are allowed
|
* implementation. However, parsers and schemas are allowed
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2005, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,15 +25,16 @@
|
|||||||
|
|
||||||
package javax.xml.stream;
|
package javax.xml.stream;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.security.AccessController;
|
||||||
import java.io.InputStream;
|
import java.security.PrivilegedAction;
|
||||||
import java.io.InputStreamReader;
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Implements pluggable Datatypes.</p>
|
* <p>Implements pluggable streams.</p>
|
||||||
*
|
*
|
||||||
* <p>This class is duplicated for each JAXP subpackage so keep it in
|
* <p>This class is duplicated for each JAXP subpackage so keep it in
|
||||||
* sync. It is package private for secure class loading.</p>
|
* sync. It is package private for secure class loading.</p>
|
||||||
@ -52,19 +53,19 @@ class FactoryFinder {
|
|||||||
/**
|
/**
|
||||||
* Cache for properties in java.home/lib/jaxp.properties
|
* Cache for properties in java.home/lib/jaxp.properties
|
||||||
*/
|
*/
|
||||||
static Properties cacheProps = new Properties();
|
final private static Properties cacheProps = new Properties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag indicating if properties from java.home/lib/jaxp.properties
|
* Flag indicating if properties from java.home/lib/jaxp.properties
|
||||||
* have been cached.
|
* have been cached.
|
||||||
*/
|
*/
|
||||||
static volatile boolean firstTime = true;
|
private static volatile boolean firstTime = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Security support class use to check access control before
|
* Security support class use to check access control before
|
||||||
* getting certain system resources.
|
* getting certain system resources.
|
||||||
*/
|
*/
|
||||||
static SecuritySupport ss = new SecuritySupport();
|
final private static SecuritySupport ss = new SecuritySupport();
|
||||||
|
|
||||||
// Define system property "jaxp.debug" to get output
|
// Define system property "jaxp.debug" to get output
|
||||||
static {
|
static {
|
||||||
@ -103,25 +104,25 @@ class FactoryFinder {
|
|||||||
try {
|
try {
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
if (useBSClsLoader) {
|
if (useBSClsLoader) {
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
} else {
|
} else {
|
||||||
cl = ss.getContextClassLoader();
|
cl = ss.getContextClassLoader();
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
throw new ClassNotFoundException();
|
throw new ClassNotFoundException();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e1) {
|
catch (ClassNotFoundException e1) {
|
||||||
if (doFallback) {
|
if (doFallback) {
|
||||||
// Use current class loader - should always be bootstrap CL
|
// Use current class loader - should always be bootstrap CL
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e1;
|
throw e1;
|
||||||
@ -133,6 +134,9 @@ class FactoryFinder {
|
|||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to
|
||||||
|
* instantiate.
|
||||||
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
*
|
*
|
||||||
@ -142,16 +146,19 @@ class FactoryFinder {
|
|||||||
* @param doFallback True if the current ClassLoader should be tried as
|
* @param doFallback True if the current ClassLoader should be tried as
|
||||||
* a fallback if the class is not found using cl
|
* a fallback if the class is not found using cl
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl, boolean doFallback)
|
||||||
throws ConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return newInstance(className, cl, doFallback, false);
|
return newInstance(type, className, cl, doFallback, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to
|
||||||
|
* instantiate.
|
||||||
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
*
|
*
|
||||||
@ -164,9 +171,12 @@ class FactoryFinder {
|
|||||||
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
||||||
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
|
||||||
throws ConfigurationError
|
boolean doFallback, boolean useBSClsLoader)
|
||||||
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
|
assert type != null;
|
||||||
|
|
||||||
// make sure we have access to restricted packages
|
// make sure we have access to restricted packages
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
||||||
@ -176,20 +186,23 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
||||||
|
if (!type.isAssignableFrom(providerClass)) {
|
||||||
|
throw new ClassCastException(className + " cannot be cast to " + type.getName());
|
||||||
|
}
|
||||||
Object instance = providerClass.newInstance();
|
Object instance = providerClass.newInstance();
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
if (debug) { // Extra check to avoid computing cl strings
|
||||||
dPrint("created new instance of " + providerClass +
|
dPrint("created new instance of " + providerClass +
|
||||||
" using ClassLoader: " + cl);
|
" using ClassLoader: " + cl);
|
||||||
}
|
}
|
||||||
return instance;
|
return type.cast(instance);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException x) {
|
catch (ClassNotFoundException x) {
|
||||||
throw new ConfigurationError(
|
throw new FactoryConfigurationError(
|
||||||
"Provider " + className + " not found", x);
|
"Provider " + className + " not found", x);
|
||||||
}
|
}
|
||||||
catch (Exception x) {
|
catch (Exception x) {
|
||||||
throw new ConfigurationError(
|
throw new FactoryConfigurationError(
|
||||||
"Provider " + className + " could not be instantiated: " + x,
|
"Provider " + className + " could not be instantiated: " + x,
|
||||||
x);
|
x);
|
||||||
}
|
}
|
||||||
@ -200,17 +213,18 @@ class FactoryFinder {
|
|||||||
*
|
*
|
||||||
* @return Class object of factory, never null
|
* @return Class object of factory, never null
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param type Base class / Service interface of the
|
||||||
* a property name
|
* factory to find.
|
||||||
|
*
|
||||||
* @param fallbackClassName Implementation class name, if nothing else
|
* @param fallbackClassName Implementation class name, if nothing else
|
||||||
* is found. Use null to mean no fallback.
|
* is found. Use null to mean no fallback.
|
||||||
*
|
*
|
||||||
* Package private so this code can be shared.
|
* Package private so this code can be shared.
|
||||||
*/
|
*/
|
||||||
static Object find(String factoryId, String fallbackClassName)
|
static <T> T find(Class<T> type, String fallbackClassName)
|
||||||
throws ConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return find(factoryId, null, fallbackClassName);
|
return find(type, type.getName(), null, fallbackClassName);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -218,6 +232,9 @@ class FactoryFinder {
|
|||||||
* entry point.
|
* entry point.
|
||||||
* @return Class object of factory, never null
|
* @return Class object of factory, never null
|
||||||
*
|
*
|
||||||
|
* @param type Base class / Service interface of the
|
||||||
|
* factory to find.
|
||||||
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param factoryId Name of the factory to find, same as
|
||||||
* a property name
|
* a property name
|
||||||
*
|
*
|
||||||
@ -229,8 +246,8 @@ class FactoryFinder {
|
|||||||
*
|
*
|
||||||
* Package private so this code can be shared.
|
* Package private so this code can be shared.
|
||||||
*/
|
*/
|
||||||
static Object find(String factoryId, ClassLoader cl, String fallbackClassName)
|
static <T> T find(Class<T> type, String factoryId, ClassLoader cl, String fallbackClassName)
|
||||||
throws ConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
dPrint("find factoryId =" + factoryId);
|
dPrint("find factoryId =" + factoryId);
|
||||||
|
|
||||||
@ -239,7 +256,9 @@ class FactoryFinder {
|
|||||||
String systemProp = ss.getSystemProperty(factoryId);
|
String systemProp = ss.getSystemProperty(factoryId);
|
||||||
if (systemProp != null) {
|
if (systemProp != null) {
|
||||||
dPrint("found system property, value=" + systemProp);
|
dPrint("found system property, value=" + systemProp);
|
||||||
return newInstance(systemProp, null, true);
|
// There's a bug here - because 'cl' is ignored.
|
||||||
|
// This will be handled separately.
|
||||||
|
return newInstance(type, systemProp, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SecurityException se) {
|
catch (SecurityException se) {
|
||||||
@ -250,7 +269,6 @@ class FactoryFinder {
|
|||||||
// $java.home/lib/jaxp.properties if former not present
|
// $java.home/lib/jaxp.properties if former not present
|
||||||
String configFile = null;
|
String configFile = null;
|
||||||
try {
|
try {
|
||||||
String factoryClassName = null;
|
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
synchronized (cacheProps) {
|
synchronized (cacheProps) {
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
@ -269,130 +287,80 @@ class FactoryFinder {
|
|||||||
if (ss.doesFileExist(f)) {
|
if (ss.doesFileExist(f)) {
|
||||||
dPrint("Read properties file "+f);
|
dPrint("Read properties file "+f);
|
||||||
cacheProps.load(ss.getFileInputStream(f));
|
cacheProps.load(ss.getFileInputStream(f));
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
final String factoryClassName = cacheProps.getProperty(factoryId);
|
||||||
}
|
|
||||||
factoryClassName = cacheProps.getProperty(factoryId);
|
|
||||||
|
|
||||||
if (factoryClassName != null) {
|
if (factoryClassName != null) {
|
||||||
dPrint("found in " + configFile + " value=" + factoryClassName);
|
dPrint("found in " + configFile + " value=" + factoryClassName);
|
||||||
return newInstance(factoryClassName, null, true);
|
// There's a bug here - because 'cl' is ignored.
|
||||||
|
// This will be handled separately.
|
||||||
|
return newInstance(type, factoryClassName, null, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
if (debug) ex.printStackTrace();
|
if (debug) ex.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try Jar Service Provider Mechanism
|
if (type.getName().equals(factoryId)) {
|
||||||
Object provider = findJarServiceProvider(factoryId);
|
// Try Jar Service Provider Mechanism
|
||||||
if (provider != null) {
|
final T provider = findServiceProvider(type);
|
||||||
return provider;
|
if (provider != null) {
|
||||||
|
return provider;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// We're in the case where a 'custom' factoryId was provided,
|
||||||
|
// and in every case where that happens, we expect that
|
||||||
|
// fallbackClassName will be null.
|
||||||
|
assert fallbackClassName == null;
|
||||||
}
|
}
|
||||||
if (fallbackClassName == null) {
|
if (fallbackClassName == null) {
|
||||||
throw new ConfigurationError(
|
throw new FactoryConfigurationError(
|
||||||
"Provider for " + factoryId + " cannot be found", null);
|
"Provider for " + factoryId + " cannot be found", null);
|
||||||
}
|
}
|
||||||
|
|
||||||
dPrint("loaded from fallback value: " + fallbackClassName);
|
dPrint("loaded from fallback value: " + fallbackClassName);
|
||||||
return newInstance(fallbackClassName, cl, true);
|
return newInstance(type, fallbackClassName, cl, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find provider using Jar Service Provider Mechanism
|
* Try to find provider using the ServiceLoader API
|
||||||
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to find.
|
||||||
*
|
*
|
||||||
* @return instance of provider class if found or null
|
* @return instance of provider class if found or null
|
||||||
*/
|
*/
|
||||||
private static Object findJarServiceProvider(String factoryId)
|
private static <T> T findServiceProvider(final Class<T> type) {
|
||||||
throws ConfigurationError
|
|
||||||
{
|
|
||||||
String serviceId = "META-INF/services/" + factoryId;
|
|
||||||
InputStream is = null;
|
|
||||||
|
|
||||||
// First try the Context ClassLoader
|
|
||||||
ClassLoader cl = ss.getContextClassLoader();
|
|
||||||
boolean useBSClsLoader = false;
|
|
||||||
if (cl != null) {
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
|
|
||||||
// If no provider found then try the current ClassLoader
|
|
||||||
if (is == null) {
|
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
useBSClsLoader = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// No Context ClassLoader, try the current ClassLoader
|
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
|
||||||
useBSClsLoader = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is == null) {
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
|
||||||
dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedReader rd;
|
|
||||||
try {
|
try {
|
||||||
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
return AccessController.doPrivileged(new PrivilegedAction<T>() {
|
||||||
}
|
@Override
|
||||||
catch (java.io.UnsupportedEncodingException e) {
|
public T run() {
|
||||||
rd = new BufferedReader(new InputStreamReader(is));
|
final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
|
||||||
}
|
final Iterator<T> iterator = serviceLoader.iterator();
|
||||||
|
if (iterator.hasNext()) {
|
||||||
String factoryClassName = null;
|
return iterator.next();
|
||||||
try {
|
} else {
|
||||||
// XXX Does not handle all possible input as specified by the
|
return null;
|
||||||
// Jar Service Provider specification
|
}
|
||||||
factoryClassName = rd.readLine();
|
}
|
||||||
rd.close();
|
});
|
||||||
} catch (IOException x) {
|
} catch(ServiceConfigurationError e) {
|
||||||
// No provider found
|
// It is not possible to wrap an error directly in
|
||||||
return null;
|
// FactoryConfigurationError - so we need to wrap the
|
||||||
}
|
// ServiceConfigurationError in a RuntimeException.
|
||||||
|
// The alternative would be to modify the logic in
|
||||||
if (factoryClassName != null && !"".equals(factoryClassName)) {
|
// FactoryConfigurationError to allow setting a
|
||||||
dPrint("found in resource, value=" + factoryClassName);
|
// Throwable as the cause, but that could cause
|
||||||
|
// compatibility issues down the road.
|
||||||
// Note: here we do not want to fall back to the current
|
final RuntimeException x = new RuntimeException(
|
||||||
// ClassLoader because we want to avoid the case where the
|
"Provider for " + type + " cannot be created", e);
|
||||||
// resource file was found using one ClassLoader and the
|
final FactoryConfigurationError error =
|
||||||
// provider class was instantiated using a different one.
|
new FactoryConfigurationError(x, x.getMessage());
|
||||||
return newInstance(factoryClassName, cl, false, useBSClsLoader);
|
throw error;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ConfigurationError extends Error {
|
|
||||||
private Exception exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new instance with the specified detail string and
|
|
||||||
* exception.
|
|
||||||
*/
|
|
||||||
ConfigurationError(String msg, Exception x) {
|
|
||||||
super(msg);
|
|
||||||
this.exception = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exception getException() {
|
|
||||||
return exception;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* use the exception chaining mechanism of JDK1.4
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Throwable getCause() {
|
|
||||||
return exception;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -23,14 +23,14 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
|
* Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package javax.xml.stream;
|
package javax.xml.stream;
|
||||||
import javax.xml.stream.events.*;
|
import java.util.Iterator;
|
||||||
import javax.xml.namespace.NamespaceContext;
|
import javax.xml.namespace.NamespaceContext;
|
||||||
import javax.xml.namespace.QName;
|
import javax.xml.namespace.QName;
|
||||||
import java.util.Iterator;
|
import javax.xml.stream.events.*;
|
||||||
/**
|
/**
|
||||||
* This interface defines a utility class for creating instances of
|
* This interface defines a utility class for creating instances of
|
||||||
* XMLEvents
|
* XMLEvents
|
||||||
@ -54,48 +54,59 @@ public abstract class XMLEventFactory {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory
|
* Creates a new instance of the factory in exactly the same manner as the
|
||||||
|
* {@link #newFactory()} method.
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
||||||
*/
|
*/
|
||||||
public static XMLEventFactory newInstance()
|
public static XMLEventFactory newInstance()
|
||||||
throws FactoryConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return (XMLEventFactory) FactoryFinder.find(
|
return FactoryFinder.find(XMLEventFactory.class, DEFAULIMPL);
|
||||||
JAXPFACTORYID,
|
|
||||||
DEFAULIMPL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Create a new instance of the factory.
|
||||||
|
* <p>
|
||||||
* This static method creates a new factory instance.
|
* This static method creates a new factory instance.
|
||||||
* This method uses the following ordered lookup procedure to determine
|
* This method uses the following ordered lookup procedure to determine
|
||||||
* the XMLEventFactory implementation class to load:
|
* the XMLEventFactory implementation class to load:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
* Use the javax.xml.stream.XMLEventFactory system property.
|
* Use the javax.xml.stream.XMLEventFactory system property.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
* Use the properties file "lib/stax.properties" in the JRE directory.
|
* Use the properties file "lib/stax.properties" in the JRE directory.
|
||||||
* This configuration file is in standard java.util.Properties format
|
* This configuration file is in standard java.util.Properties format
|
||||||
* and contains the fully qualified name of the implementation class
|
* and contains the fully qualified name of the implementation class
|
||||||
* with the key being the system property defined above.
|
* with the key being the system property defined above.
|
||||||
* Use the Services API (as detailed in the JAR specification), if available,
|
* </li>
|
||||||
* to determine the classname. The Services API will look for a classname
|
* <li>
|
||||||
* in the file META-INF/services/javax.xml.stream.XMLEventFactory in jars
|
* Use the service-provider loading facilities, defined by the
|
||||||
* available to the runtime.
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* Platform default XMLEventFactory instance.
|
* implementation of the service.
|
||||||
*
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Otherwise, the system-default implementation is returned.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
* Once an application has obtained a reference to a XMLEventFactory it
|
* Once an application has obtained a reference to a XMLEventFactory it
|
||||||
* can use the factory to configure and obtain stream instances.
|
* can use the factory to configure and obtain stream instances.
|
||||||
*
|
* </p>
|
||||||
|
* <p>
|
||||||
* Note that this is a new method that replaces the deprecated newInstance() method.
|
* Note that this is a new method that replaces the deprecated newInstance() method.
|
||||||
* No changes in behavior are defined by this replacement method relative to
|
* No changes in behavior are defined by this replacement method relative to
|
||||||
* the deprecated method.
|
* the deprecated method.
|
||||||
*
|
* </p>
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static XMLEventFactory newFactory()
|
public static XMLEventFactory newFactory()
|
||||||
throws FactoryConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return (XMLEventFactory) FactoryFinder.find(
|
return FactoryFinder.find(XMLEventFactory.class, DEFAULIMPL);
|
||||||
JAXPFACTORYID,
|
|
||||||
DEFAULIMPL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -116,40 +127,59 @@ public abstract class XMLEventFactory {
|
|||||||
public static XMLEventFactory newInstance(String factoryId,
|
public static XMLEventFactory newInstance(String factoryId,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws FactoryConfigurationError {
|
throws FactoryConfigurationError {
|
||||||
try {
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
return FactoryFinder.find(XMLEventFactory.class, factoryId, classLoader, null);
|
||||||
return (XMLEventFactory) FactoryFinder.find(factoryId, classLoader, null);
|
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Create a new instance of the factory.
|
||||||
* If the classLoader argument is null, then the ContextClassLoader is used.
|
* If the classLoader argument is null, then the ContextClassLoader is used.
|
||||||
|
* <p>
|
||||||
|
* This method uses the following ordered lookup procedure to determine
|
||||||
|
* the XMLEventFactory implementation class to load:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* Use the value of the system property identified by {@code factoryId}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Use the properties file "lib/stax.properties" in the JRE directory.
|
||||||
|
* This configuration file is in standard java.util.Properties format
|
||||||
|
* and contains the fully qualified name of the implementation class
|
||||||
|
* with the key being the given {@code factoryId}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* If {@code factoryId} is "javax.xml.stream.XMLEventFactory",
|
||||||
|
* use the service-provider loading facilities, defined by the
|
||||||
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
|
* implementation of the service.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Otherwise, throws a {@link FactoryConfigurationError}.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
* Note that this is a new method that replaces the deprecated
|
* Note that this is a new method that replaces the deprecated
|
||||||
* newInstance(String factoryId, ClassLoader classLoader) method.
|
* {@link #newInstance(java.lang.String, java.lang.ClassLoader)
|
||||||
|
* newInstance(String factoryId, ClassLoader classLoader)} method.
|
||||||
* No changes in behavior are defined by this replacement method relative
|
* No changes in behavior are defined by this replacement method relative
|
||||||
* to the deprecated method.
|
* to the deprecated method.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param factoryId Name of the factory to find, same as
|
||||||
* a property name
|
* a property name
|
||||||
* @param classLoader classLoader to use
|
* @param classLoader classLoader to use
|
||||||
* @return the factory implementation
|
* @return the factory implementation
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static XMLEventFactory newFactory(String factoryId,
|
public static XMLEventFactory newFactory(String factoryId,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws FactoryConfigurationError {
|
throws FactoryConfigurationError {
|
||||||
try {
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
return FactoryFinder.find(XMLEventFactory.class, factoryId, classLoader, null);
|
||||||
return (XMLEventFactory) FactoryFinder.find(factoryId, classLoader, null);
|
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,13 +23,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
|
* Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package javax.xml.stream;
|
package javax.xml.stream;
|
||||||
|
|
||||||
import javax.xml.transform.Source;
|
|
||||||
import javax.xml.stream.util.XMLEventAllocator;
|
import javax.xml.stream.util.XMLEventAllocator;
|
||||||
|
import javax.xml.transform.Source;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Defines an abstract implementation of a factory for getting streams.
|
* Defines an abstract implementation of a factory for getting streams.
|
||||||
@ -144,48 +144,59 @@ public abstract class XMLInputFactory {
|
|||||||
protected XMLInputFactory(){}
|
protected XMLInputFactory(){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Creates a new instance of the factory in exactly the same manner as the
|
||||||
|
* {@link #newFactory()} method.
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
||||||
*/
|
*/
|
||||||
public static XMLInputFactory newInstance()
|
public static XMLInputFactory newInstance()
|
||||||
throws FactoryConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return (XMLInputFactory) FactoryFinder.find(
|
return FactoryFinder.find(XMLInputFactory.class, DEFAULIMPL);
|
||||||
"javax.xml.stream.XMLInputFactory",
|
|
||||||
DEFAULIMPL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Create a new instance of the factory.
|
||||||
|
* <p>
|
||||||
* This static method creates a new factory instance.
|
* This static method creates a new factory instance.
|
||||||
* This method uses the following ordered lookup procedure to determine
|
* This method uses the following ordered lookup procedure to determine
|
||||||
* the XMLInputFactory implementation class to load:
|
* the XMLInputFactory implementation class to load:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
* Use the javax.xml.stream.XMLInputFactory system property.
|
* Use the javax.xml.stream.XMLInputFactory system property.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
* Use the properties file "lib/stax.properties" in the JRE directory.
|
* Use the properties file "lib/stax.properties" in the JRE directory.
|
||||||
* This configuration file is in standard java.util.Properties format
|
* This configuration file is in standard java.util.Properties format
|
||||||
* and contains the fully qualified name of the implementation class
|
* and contains the fully qualified name of the implementation class
|
||||||
* with the key being the system property defined above.
|
* with the key being the system property defined above.
|
||||||
* Use the Services API (as detailed in the JAR specification), if available,
|
* </li>
|
||||||
* to determine the classname. The Services API will look for a classname
|
* <li>
|
||||||
* in the file META-INF/services/javax.xml.stream.XMLInputFactory in jars
|
* Use the service-provider loading facilities, defined by the
|
||||||
* available to the runtime.
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* Platform default XMLInputFactory instance.
|
* implementation of the service.
|
||||||
*
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Otherwise, the system-default implementation is returned.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
|
* <p>
|
||||||
* Once an application has obtained a reference to a XMLInputFactory it
|
* Once an application has obtained a reference to a XMLInputFactory it
|
||||||
* can use the factory to configure and obtain stream instances.
|
* can use the factory to configure and obtain stream instances.
|
||||||
*
|
* </p>
|
||||||
|
* <p>
|
||||||
* Note that this is a new method that replaces the deprecated newInstance() method.
|
* Note that this is a new method that replaces the deprecated newInstance() method.
|
||||||
* No changes in behavior are defined by this replacement method relative to
|
* No changes in behavior are defined by this replacement method relative to
|
||||||
* the deprecated method.
|
* the deprecated method.
|
||||||
*
|
* </p>
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static XMLInputFactory newFactory()
|
public static XMLInputFactory newFactory()
|
||||||
throws FactoryConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return (XMLInputFactory) FactoryFinder.find(
|
return FactoryFinder.find(XMLInputFactory.class, DEFAULIMPL);
|
||||||
"javax.xml.stream.XMLInputFactory",
|
|
||||||
DEFAULIMPL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -206,40 +217,60 @@ public abstract class XMLInputFactory {
|
|||||||
public static XMLInputFactory newInstance(String factoryId,
|
public static XMLInputFactory newInstance(String factoryId,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws FactoryConfigurationError {
|
throws FactoryConfigurationError {
|
||||||
try {
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
|
||||||
return (XMLInputFactory) FactoryFinder.find(factoryId, classLoader, null);
|
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Create a new instance of the factory.
|
||||||
* If the classLoader argument is null, then the ContextClassLoader is used.
|
* If the classLoader argument is null, then the ContextClassLoader is used.
|
||||||
|
* <p>
|
||||||
|
* This method uses the following ordered lookup procedure to determine
|
||||||
|
* the XMLInputFactory implementation class to load:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* Use the value of the system property identified by {@code factoryId}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Use the properties file "lib/stax.properties" in the JRE directory.
|
||||||
|
* This configuration file is in standard java.util.Properties format
|
||||||
|
* and contains the fully qualified name of the implementation class
|
||||||
|
* with the key being the given {@code factoryId}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* If {@code factoryId} is "javax.xml.stream.XMLInputFactory",
|
||||||
|
* use the service-provider loading facilities, defined by the
|
||||||
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
|
* implementation of the service.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Otherwise, throws a {@link FactoryConfigurationError}.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
* Note that this is a new method that replaces the deprecated
|
* Note that this is a new method that replaces the deprecated
|
||||||
* newInstance(String factoryId, ClassLoader classLoader) method.
|
* {@link #newInstance(java.lang.String, java.lang.ClassLoader)
|
||||||
|
* newInstance(String factoryId, ClassLoader classLoader)} method.
|
||||||
* No changes in behavior are defined by this replacement method relative
|
* No changes in behavior are defined by this replacement method relative
|
||||||
* to the deprecated method.
|
* to the deprecated method.
|
||||||
|
* </p>
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param factoryId Name of the factory to find, same as
|
||||||
* a property name
|
* a property name
|
||||||
* @param classLoader classLoader to use
|
* @param classLoader classLoader to use
|
||||||
* @return the factory implementation
|
* @return the factory implementation
|
||||||
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
||||||
*/
|
*/
|
||||||
public static XMLInputFactory newFactory(String factoryId,
|
public static XMLInputFactory newFactory(String factoryId,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws FactoryConfigurationError {
|
throws FactoryConfigurationError {
|
||||||
try {
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
|
||||||
return (XMLInputFactory) FactoryFinder.find(factoryId, classLoader, null);
|
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -23,7 +23,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2009 by Oracle Corporation. All Rights Reserved.
|
* Copyright (c) 2009, 2013, by Oracle Corporation. All Rights Reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package javax.xml.stream;
|
package javax.xml.stream;
|
||||||
@ -120,46 +120,58 @@ public abstract class XMLOutputFactory {
|
|||||||
protected XMLOutputFactory(){}
|
protected XMLOutputFactory(){}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Creates a new instance of the factory in exactly the same manner as the
|
||||||
|
* {@link #newFactory()} method.
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
||||||
*/
|
*/
|
||||||
public static XMLOutputFactory newInstance()
|
public static XMLOutputFactory newInstance()
|
||||||
throws FactoryConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return (XMLOutputFactory) FactoryFinder.find("javax.xml.stream.XMLOutputFactory",
|
return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL);
|
||||||
DEFAULIMPL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Create a new instance of the factory.
|
||||||
|
* <p>
|
||||||
* This static method creates a new factory instance. This method uses the
|
* This static method creates a new factory instance. This method uses the
|
||||||
* following ordered lookup procedure to determine the XMLOutputFactory
|
* following ordered lookup procedure to determine the XMLOutputFactory
|
||||||
* implementation class to load:
|
* implementation class to load:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
* Use the javax.xml.stream.XMLOutputFactory system property.
|
* Use the javax.xml.stream.XMLOutputFactory system property.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
* Use the properties file "lib/stax.properties" in the JRE directory.
|
* Use the properties file "lib/stax.properties" in the JRE directory.
|
||||||
* This configuration file is in standard java.util.Properties format
|
* This configuration file is in standard java.util.Properties format
|
||||||
* and contains the fully qualified name of the implementation class
|
* and contains the fully qualified name of the implementation class
|
||||||
* with the key being the system property defined above.
|
* with the key being the system property defined above.
|
||||||
* Use the Services API (as detailed in the JAR specification), if available,
|
* </li>
|
||||||
* to determine the classname. The Services API will look for a classname
|
* <li>
|
||||||
* in the file META-INF/services/javax.xml.stream.XMLOutputFactory in jars
|
* Use the service-provider loading facilities, defined by the
|
||||||
* available to the runtime.
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* Platform default XMLOutputFactory instance.
|
* implementation of the service.
|
||||||
*
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Otherwise, the system-default implementation is returned.
|
||||||
|
* </li>
|
||||||
|
* <p>
|
||||||
* Once an application has obtained a reference to a XMLOutputFactory it
|
* Once an application has obtained a reference to a XMLOutputFactory it
|
||||||
* can use the factory to configure and obtain stream instances.
|
* can use the factory to configure and obtain stream instances.
|
||||||
*
|
* </p>
|
||||||
|
* <p>
|
||||||
* Note that this is a new method that replaces the deprecated newInstance() method.
|
* Note that this is a new method that replaces the deprecated newInstance() method.
|
||||||
* No changes in behavior are defined by this replacement method relative to the
|
* No changes in behavior are defined by this replacement method relative to the
|
||||||
* deprecated method.
|
* deprecated method.
|
||||||
*
|
* </p>
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static XMLOutputFactory newFactory()
|
public static XMLOutputFactory newFactory()
|
||||||
throws FactoryConfigurationError
|
throws FactoryConfigurationError
|
||||||
{
|
{
|
||||||
return (XMLOutputFactory) FactoryFinder.find("javax.xml.stream.XMLOutputFactory",
|
return FactoryFinder.find(XMLOutputFactory.class, DEFAULIMPL);
|
||||||
DEFAULIMPL);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -179,42 +191,59 @@ public abstract class XMLOutputFactory {
|
|||||||
public static XMLInputFactory newInstance(String factoryId,
|
public static XMLInputFactory newInstance(String factoryId,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws FactoryConfigurationError {
|
throws FactoryConfigurationError {
|
||||||
try {
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
return FactoryFinder.find(XMLInputFactory.class, factoryId, classLoader, null);
|
||||||
return (XMLInputFactory) FactoryFinder.find(factoryId, classLoader, null);
|
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new instance of the factory.
|
* Create a new instance of the factory.
|
||||||
* If the classLoader argument is null, then the ContextClassLoader is used.
|
* If the classLoader argument is null, then the ContextClassLoader is used.
|
||||||
|
* <p>
|
||||||
|
* This method uses the following ordered lookup procedure to determine
|
||||||
|
* the XMLOutputFactory implementation class to load:
|
||||||
|
* </p>
|
||||||
|
* <ul>
|
||||||
|
* <li>
|
||||||
|
* Use the value of the system property identified by {@code factoryId}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Use the properties file "lib/stax.properties" in the JRE directory.
|
||||||
|
* This configuration file is in standard java.util.Properties format
|
||||||
|
* and contains the fully qualified name of the implementation class
|
||||||
|
* with the key being the given {@code factoryId}.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* If {@code factoryId} is "javax.xml.stream.XMLOutputFactory",
|
||||||
|
* use the service-provider loading facilities, defined by the
|
||||||
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
|
* implementation of the service.
|
||||||
|
* </li>
|
||||||
|
* <li>
|
||||||
|
* Otherwise, throws a {@link FactoryConfigurationError}.
|
||||||
|
* </li>
|
||||||
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* <p>
|
||||||
* Note that this is a new method that replaces the deprecated
|
* Note that this is a new method that replaces the deprecated
|
||||||
* newInstance(String factoryId, ClassLoader classLoader) method.
|
* {@link #newInstance(java.lang.String, java.lang.ClassLoader)
|
||||||
*
|
* newInstance(String factoryId, ClassLoader classLoader)} method.
|
||||||
* No changes in behavior are defined by this replacement method relative
|
* No changes in behavior are defined by this replacement method relative
|
||||||
* to the deprecated method.
|
* to the deprecated method.
|
||||||
*
|
* </p>
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param factoryId Name of the factory to find, same as
|
||||||
* a property name
|
* a property name
|
||||||
* @param classLoader classLoader to use
|
* @param classLoader classLoader to use
|
||||||
* @return the factory implementation
|
* @return the factory implementation
|
||||||
* @throws FactoryConfigurationError if an instance of this factory cannot be loaded
|
* @throws FactoryConfigurationError in case of {@linkplain
|
||||||
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static XMLOutputFactory newFactory(String factoryId,
|
public static XMLOutputFactory newFactory(String factoryId,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws FactoryConfigurationError {
|
throws FactoryConfigurationError {
|
||||||
try {
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
return FactoryFinder.find(XMLOutputFactory.class, factoryId, classLoader, null);
|
||||||
return (XMLOutputFactory) FactoryFinder.find(factoryId, classLoader, null);
|
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new FactoryConfigurationError(e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,13 +25,15 @@
|
|||||||
|
|
||||||
package javax.xml.transform;
|
package javax.xml.transform;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Modifier;
|
||||||
|
import java.security.AccessController;
|
||||||
|
import java.security.PrivilegedAction;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Implements pluggable Datatypes.</p>
|
* <p>Implements pluggable Datatypes.</p>
|
||||||
@ -53,7 +55,7 @@ class FactoryFinder {
|
|||||||
/**
|
/**
|
||||||
* Cache for properties in java.home/lib/jaxp.properties
|
* Cache for properties in java.home/lib/jaxp.properties
|
||||||
*/
|
*/
|
||||||
static Properties cacheProps = new Properties();
|
private final static Properties cacheProps = new Properties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Flag indicating if properties from java.home/lib/jaxp.properties
|
* Flag indicating if properties from java.home/lib/jaxp.properties
|
||||||
@ -65,7 +67,7 @@ class FactoryFinder {
|
|||||||
* Security support class use to check access control before
|
* Security support class use to check access control before
|
||||||
* getting certain system resources.
|
* getting certain system resources.
|
||||||
*/
|
*/
|
||||||
static SecuritySupport ss = new SecuritySupport();
|
private final static SecuritySupport ss = new SecuritySupport();
|
||||||
|
|
||||||
// Define system property "jaxp.debug" to get output
|
// Define system property "jaxp.debug" to get output
|
||||||
static {
|
static {
|
||||||
@ -98,31 +100,31 @@ class FactoryFinder {
|
|||||||
*
|
*
|
||||||
* Use bootstrap classLoader if cl = null and useBSClsLoader is true
|
* Use bootstrap classLoader if cl = null and useBSClsLoader is true
|
||||||
*/
|
*/
|
||||||
static private Class getProviderClass(String className, ClassLoader cl,
|
static private Class<?> getProviderClass(String className, ClassLoader cl,
|
||||||
boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
|
boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
|
||||||
{
|
{
|
||||||
try {
|
try {
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
if (useBSClsLoader) {
|
if (useBSClsLoader) {
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
} else {
|
} else {
|
||||||
cl = ss.getContextClassLoader();
|
cl = ss.getContextClassLoader();
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
throw new ClassNotFoundException();
|
throw new ClassNotFoundException();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return cl.loadClass(className);
|
return Class.forName(className, false, cl);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException e1) {
|
catch (ClassNotFoundException e1) {
|
||||||
if (doFallback) {
|
if (doFallback) {
|
||||||
// Use current class loader - should always be bootstrap CL
|
// Use current class loader - should always be bootstrap CL
|
||||||
return Class.forName(className, true, FactoryFinder.class.getClassLoader());
|
return Class.forName(className, false, FactoryFinder.class.getClassLoader());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e1;
|
throw e1;
|
||||||
@ -134,24 +136,8 @@ class FactoryFinder {
|
|||||||
* Create an instance of a class. Delegates to method
|
* Create an instance of a class. Delegates to method
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
* <code>getProviderClass()</code> in order to load the class.
|
||||||
*
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param type Base class / Service interface of the factory to
|
||||||
* service provider
|
* instantiate.
|
||||||
*
|
|
||||||
* @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
|
|
||||||
* current <code>Thread</code>'s context classLoader is used to load the factory class.
|
|
||||||
*
|
|
||||||
* @param doFallback True if the current ClassLoader should be tried as
|
|
||||||
* a fallback if the class is not found using cl
|
|
||||||
*/
|
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback)
|
|
||||||
throws ConfigurationError
|
|
||||||
{
|
|
||||||
return newInstance(className, cl, doFallback, false, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Create an instance of a class. Delegates to method
|
|
||||||
* <code>getProviderClass()</code> in order to load the class.
|
|
||||||
*
|
*
|
||||||
* @param className Name of the concrete class corresponding to the
|
* @param className Name of the concrete class corresponding to the
|
||||||
* service provider
|
* service provider
|
||||||
@ -162,14 +148,15 @@ class FactoryFinder {
|
|||||||
* @param doFallback True if the current ClassLoader should be tried as
|
* @param doFallback True if the current ClassLoader should be tried as
|
||||||
* a fallback if the class is not found using cl
|
* a fallback if the class is not found using cl
|
||||||
*
|
*
|
||||||
* @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
|
|
||||||
* is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
|
|
||||||
*
|
|
||||||
* @param useServicesMechanism True use services mechanism
|
* @param useServicesMechanism True use services mechanism
|
||||||
*/
|
*/
|
||||||
static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader, boolean useServicesMechanism)
|
static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
|
||||||
throws ConfigurationError
|
boolean doFallback, boolean useServicesMechanism)
|
||||||
|
throws TransformerFactoryConfigurationError
|
||||||
{
|
{
|
||||||
|
assert type != null;
|
||||||
|
|
||||||
|
boolean useBSClsLoader = false;
|
||||||
// make sure we have access to restricted packages
|
// make sure we have access to restricted packages
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
|
||||||
@ -179,10 +166,13 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
|
||||||
|
if (!type.isAssignableFrom(providerClass)) {
|
||||||
|
throw new ClassCastException(className + " cannot be cast to " + type.getName());
|
||||||
|
}
|
||||||
Object instance = null;
|
Object instance = null;
|
||||||
if (!useServicesMechanism) {
|
if (!useServicesMechanism) {
|
||||||
instance = newInstanceNoServiceLoader(providerClass);
|
instance = newInstanceNoServiceLoader(type, providerClass);
|
||||||
}
|
}
|
||||||
if (instance == null) {
|
if (instance == null) {
|
||||||
instance = providerClass.newInstance();
|
instance = providerClass.newInstance();
|
||||||
@ -191,63 +181,87 @@ class FactoryFinder {
|
|||||||
dPrint("created new instance of " + providerClass +
|
dPrint("created new instance of " + providerClass +
|
||||||
" using ClassLoader: " + cl);
|
" using ClassLoader: " + cl);
|
||||||
}
|
}
|
||||||
return instance;
|
return type.cast(instance);
|
||||||
}
|
}
|
||||||
catch (ClassNotFoundException x) {
|
catch (ClassNotFoundException x) {
|
||||||
throw new ConfigurationError(
|
throw new TransformerFactoryConfigurationError(x,
|
||||||
"Provider " + className + " not found", x);
|
"Provider " + className + " not found");
|
||||||
}
|
}
|
||||||
catch (Exception x) {
|
catch (Exception x) {
|
||||||
throw new ConfigurationError(
|
throw new TransformerFactoryConfigurationError(x,
|
||||||
"Provider " + className + " could not be instantiated: " + x,
|
"Provider " + className + " could not be instantiated: " + x);
|
||||||
x);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to construct using newTransformerFactoryNoServiceLoader
|
* Try to construct using newTransformerFactoryNoServiceLoader
|
||||||
* method if available.
|
* method if available.
|
||||||
*/
|
*/
|
||||||
private static Object newInstanceNoServiceLoader(
|
private static <T> T newInstanceNoServiceLoader(Class<T> type, Class<?> providerClass) {
|
||||||
Class<?> providerClass
|
|
||||||
) {
|
|
||||||
// Retain maximum compatibility if no security manager.
|
// Retain maximum compatibility if no security manager.
|
||||||
if (System.getSecurityManager() == null) {
|
if (System.getSecurityManager() == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Method creationMethod =
|
final Method creationMethod =
|
||||||
providerClass.getDeclaredMethod(
|
providerClass.getDeclaredMethod(
|
||||||
"newTransformerFactoryNoServiceLoader"
|
"newTransformerFactoryNoServiceLoader"
|
||||||
);
|
);
|
||||||
return creationMethod.invoke(null, (Object[])null);
|
final int modifiers = creationMethod.getModifiers();
|
||||||
} catch (NoSuchMethodException exc) {
|
|
||||||
return null;
|
// Do not call the method if it's not public static.
|
||||||
} catch (Exception exc) {
|
if (!Modifier.isPublic(modifiers) || !Modifier.isStatic(modifiers)) {
|
||||||
return null;
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only call the method if it's declared to return an instance of
|
||||||
|
// TransformerFactory
|
||||||
|
final Class<?> returnType = creationMethod.getReturnType();
|
||||||
|
if (type.isAssignableFrom(returnType)) {
|
||||||
|
final Object result = creationMethod.invoke(null, (Object[])null);
|
||||||
|
return type.cast(result);
|
||||||
|
} else {
|
||||||
|
// This should not happen, as
|
||||||
|
// TransformerFactoryImpl.newTransformerFactoryNoServiceLoader is
|
||||||
|
// declared to return TransformerFactory.
|
||||||
|
throw new ClassCastException(returnType + " cannot be cast to " + type);
|
||||||
|
}
|
||||||
|
} catch (ClassCastException e) {
|
||||||
|
throw new TransformerFactoryConfigurationError(e, e.getMessage());
|
||||||
|
} catch (NoSuchMethodException exc) {
|
||||||
|
return null;
|
||||||
|
} catch (Exception exc) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Finds the implementation Class object in the specified order. Main
|
* Finds the implementation Class object in the specified order. Main
|
||||||
* entry point.
|
* entry point.
|
||||||
* @return Class object of factory, never null
|
* @return Class object of factory, never null
|
||||||
*
|
*
|
||||||
* @param factoryId Name of the factory to find, same as
|
* @param type Base class / Service interface of the
|
||||||
* a property name
|
* factory to find.
|
||||||
|
*
|
||||||
* @param fallbackClassName Implementation class name, if nothing else
|
* @param fallbackClassName Implementation class name, if nothing else
|
||||||
* is found. Use null to mean no fallback.
|
* is found. Use null to mean no fallback.
|
||||||
*
|
*
|
||||||
* Package private so this code can be shared.
|
* Package private so this code can be shared.
|
||||||
*/
|
*/
|
||||||
static Object find(String factoryId, String fallbackClassName)
|
static <T> T find(Class<T> type, String fallbackClassName)
|
||||||
throws ConfigurationError
|
throws TransformerFactoryConfigurationError
|
||||||
{
|
{
|
||||||
|
assert type != null;
|
||||||
|
|
||||||
|
final String factoryId = type.getName();
|
||||||
|
|
||||||
dPrint("find factoryId =" + factoryId);
|
dPrint("find factoryId =" + factoryId);
|
||||||
// Use the system property first
|
// Use the system property first
|
||||||
try {
|
try {
|
||||||
String systemProp = ss.getSystemProperty(factoryId);
|
String systemProp = ss.getSystemProperty(factoryId);
|
||||||
if (systemProp != null) {
|
if (systemProp != null) {
|
||||||
dPrint("found system property, value=" + systemProp);
|
dPrint("found system property, value=" + systemProp);
|
||||||
return newInstance(systemProp, null, true, false, true);
|
return newInstance(type, systemProp, null, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (SecurityException se) {
|
catch (SecurityException se) {
|
||||||
@ -256,7 +270,6 @@ class FactoryFinder {
|
|||||||
|
|
||||||
// try to read from $java.home/lib/jaxp.properties
|
// try to read from $java.home/lib/jaxp.properties
|
||||||
try {
|
try {
|
||||||
String factoryClassName = null;
|
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
synchronized (cacheProps) {
|
synchronized (cacheProps) {
|
||||||
if (firstTime) {
|
if (firstTime) {
|
||||||
@ -271,11 +284,11 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
factoryClassName = cacheProps.getProperty(factoryId);
|
final String factoryClassName = cacheProps.getProperty(factoryId);
|
||||||
|
|
||||||
if (factoryClassName != null) {
|
if (factoryClassName != null) {
|
||||||
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
|
dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
|
||||||
return newInstance(factoryClassName, null, true, false, true);
|
return newInstance(type, factoryClassName, null, true, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception ex) {
|
catch (Exception ex) {
|
||||||
@ -283,113 +296,54 @@ class FactoryFinder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Try Jar Service Provider Mechanism
|
// Try Jar Service Provider Mechanism
|
||||||
Object provider = findJarServiceProvider(factoryId);
|
T provider = findServiceProvider(type);
|
||||||
if (provider != null) {
|
if (provider != null) {
|
||||||
return provider;
|
return provider;
|
||||||
}
|
}
|
||||||
if (fallbackClassName == null) {
|
if (fallbackClassName == null) {
|
||||||
throw new ConfigurationError(
|
throw new TransformerFactoryConfigurationError(null,
|
||||||
"Provider for " + factoryId + " cannot be found", null);
|
"Provider for " + factoryId + " cannot be found");
|
||||||
}
|
}
|
||||||
|
|
||||||
dPrint("loaded from fallback value: " + fallbackClassName);
|
dPrint("loaded from fallback value: " + fallbackClassName);
|
||||||
return newInstance(fallbackClassName, null, true, false, true);
|
return newInstance(type, fallbackClassName, null, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Try to find provider using Jar Service Provider Mechanism
|
* Try to find provider using the ServiceLoader.
|
||||||
|
*
|
||||||
|
* @param type Base class / Service interface of the factory to find.
|
||||||
*
|
*
|
||||||
* @return instance of provider class if found or null
|
* @return instance of provider class if found or null
|
||||||
*/
|
*/
|
||||||
private static Object findJarServiceProvider(String factoryId)
|
private static <T> T findServiceProvider(final Class<T> type)
|
||||||
throws ConfigurationError
|
throws TransformerFactoryConfigurationError
|
||||||
{
|
{
|
||||||
String serviceId = "META-INF/services/" + factoryId;
|
try {
|
||||||
InputStream is = null;
|
return AccessController.doPrivileged(new PrivilegedAction<T>() {
|
||||||
|
public T run() {
|
||||||
// First try the Context ClassLoader
|
final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
|
||||||
ClassLoader cl = ss.getContextClassLoader();
|
final Iterator<T> iterator = serviceLoader.iterator();
|
||||||
boolean useBSClsLoader = false;
|
if (iterator.hasNext()) {
|
||||||
if (cl != null) {
|
return iterator.next();
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
} else {
|
||||||
|
return null;
|
||||||
// If no provider found then try the current ClassLoader
|
}
|
||||||
if (is == null) {
|
}
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
});
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
} catch(ServiceConfigurationError e) {
|
||||||
useBSClsLoader = true;
|
// It is not possible to wrap an error directly in
|
||||||
}
|
// FactoryConfigurationError - so we need to wrap the
|
||||||
} else {
|
// ServiceConfigurationError in a RuntimeException.
|
||||||
// No Context ClassLoader, try the current ClassLoader
|
// The alternative would be to modify the logic in
|
||||||
cl = FactoryFinder.class.getClassLoader();
|
// FactoryConfigurationError to allow setting a
|
||||||
is = ss.getResourceAsStream(cl, serviceId);
|
// Throwable as the cause, but that could cause
|
||||||
useBSClsLoader = true;
|
// compatibility issues down the road.
|
||||||
}
|
final RuntimeException x = new RuntimeException(
|
||||||
|
"Provider for " + type + " cannot be created", e);
|
||||||
if (is == null) {
|
final TransformerFactoryConfigurationError error =
|
||||||
// No provider found
|
new TransformerFactoryConfigurationError(x, x.getMessage());
|
||||||
return null;
|
throw error;
|
||||||
}
|
|
||||||
|
|
||||||
if (debug) { // Extra check to avoid computing cl strings
|
|
||||||
dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
|
|
||||||
}
|
|
||||||
|
|
||||||
BufferedReader rd;
|
|
||||||
try {
|
|
||||||
rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
|
|
||||||
}
|
|
||||||
catch (java.io.UnsupportedEncodingException e) {
|
|
||||||
rd = new BufferedReader(new InputStreamReader(is));
|
|
||||||
}
|
|
||||||
|
|
||||||
String factoryClassName = null;
|
|
||||||
try {
|
|
||||||
// XXX Does not handle all possible input as specified by the
|
|
||||||
// Jar Service Provider specification
|
|
||||||
factoryClassName = rd.readLine();
|
|
||||||
rd.close();
|
|
||||||
} catch (IOException x) {
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (factoryClassName != null && !"".equals(factoryClassName)) {
|
|
||||||
dPrint("found in resource, value=" + factoryClassName);
|
|
||||||
|
|
||||||
// Note: here we do not want to fall back to the current
|
|
||||||
// ClassLoader because we want to avoid the case where the
|
|
||||||
// resource file was found using one ClassLoader and the
|
|
||||||
// provider class was instantiated using a different one.
|
|
||||||
return newInstance(factoryClassName, cl, false, useBSClsLoader, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// No provider found
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class ConfigurationError extends Error {
|
|
||||||
private Exception exception;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Construct a new instance with the specified detail string and
|
|
||||||
* exception.
|
|
||||||
*/
|
|
||||||
ConfigurationError(String msg, Exception x) {
|
|
||||||
super(msg);
|
|
||||||
this.exception = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
Exception getException() {
|
|
||||||
return exception;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* use the exception chaining mechanism of JDK1.4
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public Throwable getCause() {
|
|
||||||
return exception;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -52,8 +52,8 @@ public abstract class TransformerFactory {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Obtain a new instance of a <code>TransformerFactory</code>.
|
* <p>Obtain a new instance of a <code>TransformerFactory</code>.
|
||||||
* This static method creates a new factory instance
|
* This static method creates a new factory instance.</p>
|
||||||
* This method uses the following ordered lookup procedure to determine
|
* <p>This method uses the following ordered lookup procedure to determine
|
||||||
* the <code>TransformerFactory</code> implementation class to
|
* the <code>TransformerFactory</code> implementation class to
|
||||||
* load:</p>
|
* load:</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
@ -67,7 +67,7 @@ public abstract class TransformerFactory {
|
|||||||
* </code> format and contains the fully qualified name of the
|
* </code> format and contains the fully qualified name of the
|
||||||
* implementation class with the key being the system property defined
|
* implementation class with the key being the system property defined
|
||||||
* above.
|
* above.
|
||||||
*
|
* <br>
|
||||||
* The jaxp.properties file is read only once by the JAXP implementation
|
* The jaxp.properties file is read only once by the JAXP implementation
|
||||||
* and it's values are then cached for future use. If the file does not exist
|
* and it's 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
|
* when the first attempt is made to read from it, no further attempts are
|
||||||
@ -75,14 +75,12 @@ public abstract class TransformerFactory {
|
|||||||
* of any property in jaxp.properties after it has been read for the first time.
|
* of any property in jaxp.properties after it has been read for the first time.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Use the Services API (as detailed in the JAR specification), if
|
* Use the service-provider loading facilities, defined by the
|
||||||
* available, to determine the classname. The Services API will look
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* for a classname in the file
|
* implementation of the service.
|
||||||
* <code>META-INF/services/javax.xml.transform.TransformerFactory</code>
|
|
||||||
* in jars available to the runtime.
|
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Platform default <code>TransformerFactory</code> instance.
|
* Otherwise, the system-default implementation is returned.
|
||||||
* </li>
|
* </li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
@ -92,22 +90,18 @@ public abstract class TransformerFactory {
|
|||||||
*
|
*
|
||||||
* @return new TransformerFactory instance, never null.
|
* @return new TransformerFactory instance, never null.
|
||||||
*
|
*
|
||||||
* @throws TransformerFactoryConfigurationError Thrown if the implementation
|
* @throws TransformerFactoryConfigurationError Thrown in case of {@linkplain
|
||||||
* is not available or cannot be instantiated.
|
* java.util.ServiceConfigurationError service configuration error} or if
|
||||||
|
* the implementation is not available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static TransformerFactory newInstance()
|
public static TransformerFactory newInstance()
|
||||||
throws TransformerFactoryConfigurationError {
|
throws TransformerFactoryConfigurationError {
|
||||||
try {
|
|
||||||
return (TransformerFactory) FactoryFinder.find(
|
return FactoryFinder.find(
|
||||||
/* The default property name according to the JAXP spec */
|
/* The default property name according to the JAXP spec */
|
||||||
"javax.xml.transform.TransformerFactory",
|
TransformerFactory.class,
|
||||||
/* The fallback implementation class name, XSLTC */
|
/* The fallback implementation class name, XSLTC */
|
||||||
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
|
"com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl");
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
|
||||||
throw new TransformerFactoryConfigurationError(
|
|
||||||
e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -147,14 +141,10 @@ public abstract class TransformerFactory {
|
|||||||
*/
|
*/
|
||||||
public static TransformerFactory newInstance(String factoryClassName, ClassLoader classLoader)
|
public static TransformerFactory newInstance(String factoryClassName, ClassLoader classLoader)
|
||||||
throws TransformerFactoryConfigurationError{
|
throws TransformerFactoryConfigurationError{
|
||||||
try {
|
|
||||||
//do not fallback if given classloader can't find the class, throw exception
|
//do not fallback if given classloader can't find the class, throw exception
|
||||||
return (TransformerFactory) FactoryFinder.newInstance(factoryClassName, classLoader, false);
|
return FactoryFinder.newInstance(TransformerFactory.class,
|
||||||
} catch (FactoryFinder.ConfigurationError e) {
|
factoryClassName, classLoader, false, false);
|
||||||
throw new TransformerFactoryConfigurationError(
|
|
||||||
e.getException(),
|
|
||||||
e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* <p>Process the <code>Source</code> into a <code>Transformer</code>
|
* <p>Process the <code>Source</code> into a <code>Transformer</code>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -27,15 +27,14 @@ package javax.xml.validation;
|
|||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
import javax.xml.transform.Source;
|
import javax.xml.transform.Source;
|
||||||
import javax.xml.transform.stream.StreamSource;
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
|
||||||
import org.w3c.dom.ls.LSResourceResolver;
|
import org.w3c.dom.ls.LSResourceResolver;
|
||||||
import org.xml.sax.ErrorHandler;
|
import org.xml.sax.ErrorHandler;
|
||||||
import org.xml.sax.SAXException;
|
import org.xml.sax.SAXException;
|
||||||
import org.xml.sax.SAXNotRecognizedException;
|
import org.xml.sax.SAXNotRecognizedException;
|
||||||
import org.xml.sax.SAXNotSupportedException;
|
import org.xml.sax.SAXNotSupportedException;
|
||||||
|
import org.xml.sax.SAXParseException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Factory that creates {@link Schema} objects. Entry-point to
|
* Factory that creates {@link Schema} objects. Entry-point to
|
||||||
@ -79,7 +78,7 @@ import org.xml.sax.SAXNotSupportedException;
|
|||||||
* and has a significant effect on the parsing process, it is impossible
|
* and has a significant effect on the parsing process, it is impossible
|
||||||
* to define the DTD validation as a process independent from parsing.
|
* to define the DTD validation as a process independent from parsing.
|
||||||
* For this reason, this specification does not define the semantics for
|
* For this reason, this specification does not define the semantics for
|
||||||
* the XML DTD. This doesn't prohibit implentors from implementing it
|
* the XML DTD. This doesn't prohibit implementors from implementing it
|
||||||
* in a way they see fit, but <em>users are warned that any DTD
|
* in a way they see fit, but <em>users are warned that any DTD
|
||||||
* validation implemented on this interface necessarily deviate from
|
* validation implemented on this interface necessarily deviate from
|
||||||
* the XML DTD semantics as defined in the XML 1.0</em>.
|
* the XML DTD semantics as defined in the XML 1.0</em>.
|
||||||
@ -147,14 +146,17 @@ public abstract class SchemaFactory {
|
|||||||
* is looked for. If present, the value is processed just like above.
|
* is looked for. If present, the value is processed just like above.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* <p>The class loader is asked for service provider provider-configuration files matching
|
* Use the service-provider loading facilities, defined by the
|
||||||
* <code>javax.xml.validation.SchemaFactory</code> in the resource directory META-INF/services.
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* See the JAR File Specification for file format and parsing rules.
|
* implementation of the service.<br>
|
||||||
* Each potential service provider is required to implement the method:</p>
|
* Each potential service provider is required to implement the method
|
||||||
* <pre>
|
* {@link #isSchemaLanguageSupported(String schemaLanguage)}.
|
||||||
* {@link #isSchemaLanguageSupported(String schemaLanguage)}
|
* <br>
|
||||||
* </pre>
|
* The first service provider found that supports the specified schema
|
||||||
* The first service provider found in class loader order that supports the specified schema language is returned.
|
* language is returned.
|
||||||
|
* <br>
|
||||||
|
* In case of {@link java.util.ServiceConfigurationError} a
|
||||||
|
* {@link SchemaFactoryConfigurationError} will be thrown.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Platform default <code>SchemaFactory</code> is located
|
* Platform default <code>SchemaFactory</code> is located
|
||||||
@ -186,10 +188,12 @@ public abstract class SchemaFactory {
|
|||||||
* If no implementation of the schema language is available.
|
* If no implementation of the schema language is available.
|
||||||
* @throws NullPointerException
|
* @throws NullPointerException
|
||||||
* If the <code>schemaLanguage</code> parameter is null.
|
* If the <code>schemaLanguage</code> parameter is null.
|
||||||
|
* @throws SchemaFactoryConfigurationError
|
||||||
|
* If a configuration error is encountered.
|
||||||
*
|
*
|
||||||
* @see #newInstance(String schemaLanguage, String factoryClassName, ClassLoader classLoader)
|
* @see #newInstance(String schemaLanguage, String factoryClassName, ClassLoader classLoader)
|
||||||
*/
|
*/
|
||||||
public static final SchemaFactory newInstance(String schemaLanguage) {
|
public static SchemaFactory newInstance(String schemaLanguage) {
|
||||||
ClassLoader cl;
|
ClassLoader cl;
|
||||||
cl = ss.getContextClassLoader();
|
cl = ss.getContextClassLoader();
|
||||||
|
|
||||||
@ -275,19 +279,19 @@ public abstract class SchemaFactory {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Is specified schema supported by this <code>SchemaFactory</code>?</p>
|
* <p>Is specified schema supported by this <code>SchemaFactory</code>?</p>
|
||||||
*
|
*
|
||||||
* @param schemaLanguage Specifies the schema language which the returned <code>SchemaFactory</code> will understand.
|
* @param schemaLanguage Specifies the schema language which the returned <code>SchemaFactory</code> will understand.
|
||||||
* <code>schemaLanguage</code> must specify a <a href="#schemaLanguage">valid</a> schema language.
|
* <code>schemaLanguage</code> must specify a <a href="#schemaLanguage">valid</a> schema language.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if <code>SchemaFactory</code> supports <code>schemaLanguage</code>, else <code>false</code>.
|
* @return <code>true</code> if <code>SchemaFactory</code> supports <code>schemaLanguage</code>, else <code>false</code>.
|
||||||
*
|
*
|
||||||
* @throws NullPointerException If <code>schemaLanguage</code> is <code>null</code>.
|
* @throws NullPointerException If <code>schemaLanguage</code> is <code>null</code>.
|
||||||
* @throws IllegalArgumentException If <code>schemaLanguage.length() == 0</code>
|
* @throws IllegalArgumentException If <code>schemaLanguage.length() == 0</code>
|
||||||
* or <code>schemaLanguage</code> does not specify a <a href="#schemaLanguage">valid</a> schema language.
|
* or <code>schemaLanguage</code> does not specify a <a href="#schemaLanguage">valid</a> schema language.
|
||||||
*/
|
*/
|
||||||
public abstract boolean isSchemaLanguageSupported(String schemaLanguage);
|
public abstract boolean isSchemaLanguageSupported(String schemaLanguage);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Look up the value of a feature flag.
|
* Look up the value of a feature flag.
|
||||||
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2013, 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.validation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Thrown when a problem with configuration with the Schema Factories
|
||||||
|
* exists. This error will typically be thrown when the class of a
|
||||||
|
* schema factory specified in the system properties cannot be found
|
||||||
|
* or instantiated.
|
||||||
|
* @since 1.8
|
||||||
|
*/
|
||||||
|
public final class SchemaFactoryConfigurationError extends Error {
|
||||||
|
|
||||||
|
static final long serialVersionUID = 3531438703147750126L;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new <code>SchemaFactoryConfigurationError</code> with no
|
||||||
|
* detail message.
|
||||||
|
*/
|
||||||
|
public SchemaFactoryConfigurationError() {
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new <code>SchemaFactoryConfigurationError</code> with
|
||||||
|
* the <code>String</code> specified as an error message.
|
||||||
|
*
|
||||||
|
* @param message The error message for the exception.
|
||||||
|
*/
|
||||||
|
public SchemaFactoryConfigurationError(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new <code>SchemaFactoryConfigurationError</code> with the
|
||||||
|
* given <code>Throwable</code> base cause.
|
||||||
|
*
|
||||||
|
* @param cause The exception or error to be encapsulated in a
|
||||||
|
* SchemaFactoryConfigurationError.
|
||||||
|
*/
|
||||||
|
public SchemaFactoryConfigurationError(Throwable cause) {
|
||||||
|
super(cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new <code>SchemaFactoryConfigurationError</code> with the
|
||||||
|
* given <code>Throwable</code> base cause and detail message.
|
||||||
|
*
|
||||||
|
* @param cause The exception or error to be encapsulated in a
|
||||||
|
* SchemaFactoryConfigurationError.
|
||||||
|
* @param message The detail message.
|
||||||
|
*/
|
||||||
|
public SchemaFactoryConfigurationError(String message, Throwable cause) {
|
||||||
|
super(message, cause);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2003, 2005, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2003, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,19 +25,16 @@
|
|||||||
|
|
||||||
package javax.xml.validation;
|
package javax.xml.validation;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.security.AccessControlContext;
|
||||||
import java.util.Enumeration;
|
import java.security.AccessController;
|
||||||
import java.util.Iterator;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link SchemaFactory#newInstance(String)}.
|
* Implementation of {@link SchemaFactory#newInstance(String)}.
|
||||||
@ -53,17 +50,17 @@ class SchemaFactoryFinder {
|
|||||||
/**
|
/**
|
||||||
*<p> Take care of restrictions imposed by java security model </p>
|
*<p> Take care of restrictions imposed by java security model </p>
|
||||||
*/
|
*/
|
||||||
private static SecuritySupport ss = new SecuritySupport();
|
private static final SecuritySupport ss = new SecuritySupport();
|
||||||
private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
|
private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
|
||||||
/**
|
/**
|
||||||
* <p>Cache properties for performance.</p>
|
* <p>Cache properties for performance.</p>
|
||||||
*/
|
*/
|
||||||
private static Properties cacheProps = new Properties();
|
private static final Properties cacheProps = new Properties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>First time requires initialization overhead.</p>
|
* <p>First time requires initialization overhead.</p>
|
||||||
*/
|
*/
|
||||||
private static volatile boolean firstTime = true;
|
private static volatile boolean firstTime = true;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
// Use try/catch block to support applets
|
// Use try/catch block to support applets
|
||||||
@ -115,7 +112,7 @@ class SchemaFactoryFinder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch( Throwable unused ) {
|
} catch( Throwable unused ) {
|
||||||
; // getContextClassLoader() undefined in JDK1.1
|
// getContextClassLoader() undefined in JDK1.1
|
||||||
}
|
}
|
||||||
|
|
||||||
if( classLoader==ClassLoader.getSystemClassLoader() ) {
|
if( classLoader==ClassLoader.getSystemClassLoader() ) {
|
||||||
@ -138,9 +135,13 @@ class SchemaFactoryFinder {
|
|||||||
*
|
*
|
||||||
* @throws NullPointerException
|
* @throws NullPointerException
|
||||||
* If the <code>schemaLanguage</code> parameter is null.
|
* If the <code>schemaLanguage</code> parameter is null.
|
||||||
|
* @throws SchemaFactoryConfigurationError
|
||||||
|
* If a configuration error is encountered.
|
||||||
*/
|
*/
|
||||||
public SchemaFactory newFactory(String schemaLanguage) {
|
public SchemaFactory newFactory(String schemaLanguage) {
|
||||||
if(schemaLanguage==null) throw new NullPointerException();
|
if(schemaLanguage==null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
SchemaFactory f = _newFactory(schemaLanguage);
|
SchemaFactory f = _newFactory(schemaLanguage);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage);
|
debugPrintln("factory '" + f.getClass().getName() + "' was found for " + schemaLanguage);
|
||||||
@ -183,7 +184,6 @@ class SchemaFactoryFinder {
|
|||||||
String configFile = javah + File.separator +
|
String configFile = javah + File.separator +
|
||||||
"lib" + File.separator + "jaxp.properties";
|
"lib" + File.separator + "jaxp.properties";
|
||||||
|
|
||||||
String factoryClassName = null ;
|
|
||||||
|
|
||||||
// try to read from $java.home/lib/jaxp.properties
|
// try to read from $java.home/lib/jaxp.properties
|
||||||
try {
|
try {
|
||||||
@ -199,7 +199,7 @@ class SchemaFactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
factoryClassName = cacheProps.getProperty(propertyName);
|
final String factoryClassName = cacheProps.getProperty(propertyName);
|
||||||
debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
|
debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
|
||||||
|
|
||||||
if (factoryClassName != null) {
|
if (factoryClassName != null) {
|
||||||
@ -214,21 +214,15 @@ class SchemaFactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try META-INF/services files
|
// Try with ServiceLoader
|
||||||
Iterator sitr = createServiceFileIterator();
|
final SchemaFactory factoryImpl = findServiceProvider(schemaLanguage);
|
||||||
while(sitr.hasNext()) {
|
|
||||||
URL resource = (URL)sitr.next();
|
// The following assertion should always be true.
|
||||||
debugPrintln("looking into " + resource);
|
// Uncomment it, recompile, and run with -ea in case of doubts:
|
||||||
try {
|
// assert factoryImpl == null || factoryImpl.isSchemaLanguageSupported(schemaLanguage);
|
||||||
sf = loadFromService(schemaLanguage,resource.toExternalForm(),
|
|
||||||
ss.getURLInputStream(resource));
|
if (factoryImpl != null) {
|
||||||
if(sf!=null) return sf;
|
return factoryImpl;
|
||||||
} catch(IOException e) {
|
|
||||||
if( debug ) {
|
|
||||||
debugPrintln("failed to read "+resource);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// platform default
|
// platform default
|
||||||
@ -246,8 +240,8 @@ class SchemaFactoryFinder {
|
|||||||
* @param className Name of class to create.
|
* @param className Name of class to create.
|
||||||
* @return Created class or <code>null</code>.
|
* @return Created class or <code>null</code>.
|
||||||
*/
|
*/
|
||||||
private Class createClass(String className) {
|
private Class<?> createClass(String className) {
|
||||||
Class clazz;
|
Class<?> clazz;
|
||||||
// make sure we have access to restricted packages
|
// make sure we have access to restricted packages
|
||||||
boolean internal = false;
|
boolean internal = false;
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
@ -256,25 +250,27 @@ class SchemaFactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (classLoader != null && !internal) {
|
if (classLoader != null && !internal) {
|
||||||
clazz = classLoader.loadClass(className);
|
clazz = Class.forName(className, false, classLoader);
|
||||||
} else {
|
} else {
|
||||||
clazz = Class.forName(className);
|
clazz = Class.forName(className);
|
||||||
}
|
|
||||||
} catch (Throwable t) {
|
|
||||||
if(debug) t.printStackTrace();
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
} catch (Throwable t) {
|
||||||
|
if(debug) {
|
||||||
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Creates an instance of the specified and returns it.</p>
|
* <p>Creates an instance of the specified and returns it.</p>
|
||||||
*
|
*
|
||||||
* @param className
|
* @param className
|
||||||
* fully qualified class name to be instanciated.
|
* fully qualified class name to be instantiated.
|
||||||
*
|
*
|
||||||
* @return null
|
* @return null
|
||||||
* if it fails. Error messages will be printed by this method.
|
* if it fails. Error messages will be printed by this method.
|
||||||
@ -289,7 +285,7 @@ class SchemaFactoryFinder {
|
|||||||
debugPrintln("createInstance(" + className + ")");
|
debugPrintln("createInstance(" + className + ")");
|
||||||
|
|
||||||
// get Class from className
|
// get Class from className
|
||||||
Class clazz = createClass(className);
|
Class<?> clazz = createClass(className);
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
debugPrintln("failed to getClass(" + className + ")");
|
debugPrintln("failed to getClass(" + className + ")");
|
||||||
return null;
|
return null;
|
||||||
@ -298,9 +294,13 @@ class SchemaFactoryFinder {
|
|||||||
|
|
||||||
// instantiate Class as a SchemaFactory
|
// instantiate Class as a SchemaFactory
|
||||||
try {
|
try {
|
||||||
if (!useServicesMechanism) {
|
if (!SchemaFactory.class.isAssignableFrom(clazz)) {
|
||||||
schemaFactory = (SchemaFactory) newInstanceNoServiceLoader(clazz);
|
throw new ClassCastException(clazz.getName()
|
||||||
}
|
+ " cannot be cast to " + SchemaFactory.class);
|
||||||
|
}
|
||||||
|
if (!useServicesMechanism) {
|
||||||
|
schemaFactory = newInstanceNoServiceLoader(clazz);
|
||||||
|
}
|
||||||
if (schemaFactory == null) {
|
if (schemaFactory == null) {
|
||||||
schemaFactory = (SchemaFactory) clazz.newInstance();
|
schemaFactory = (SchemaFactory) clazz.newInstance();
|
||||||
}
|
}
|
||||||
@ -326,11 +326,12 @@ class SchemaFactoryFinder {
|
|||||||
|
|
||||||
return schemaFactory;
|
return schemaFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Try to construct using newTransformerFactoryNoServiceLoader
|
* Try to construct using newXMLSchemaFactoryNoServiceLoader
|
||||||
* method if available.
|
* method if available.
|
||||||
*/
|
*/
|
||||||
private static Object newInstanceNoServiceLoader(
|
private static SchemaFactory newInstanceNoServiceLoader(
|
||||||
Class<?> providerClass
|
Class<?> providerClass
|
||||||
) {
|
) {
|
||||||
// Retain maximum compatibility if no security manager.
|
// Retain maximum compatibility if no security manager.
|
||||||
@ -338,196 +339,87 @@ class SchemaFactoryFinder {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Method creationMethod =
|
final Method creationMethod =
|
||||||
providerClass.getDeclaredMethod(
|
providerClass.getDeclaredMethod(
|
||||||
"newXMLSchemaFactoryNoServiceLoader"
|
"newXMLSchemaFactoryNoServiceLoader"
|
||||||
);
|
);
|
||||||
return creationMethod.invoke(null, (Object[])null);
|
final int modifiers = creationMethod.getModifiers();
|
||||||
} catch (NoSuchMethodException exc) {
|
|
||||||
|
// Do not call the method if it's not public static.
|
||||||
|
if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception exc) {
|
}
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Iterator that lazily computes one value and returns it. */
|
// Only calls "newXMLSchemaFactoryNoServiceLoader" if it's
|
||||||
private static abstract class SingleIterator implements Iterator {
|
// declared to return an instance of SchemaFactory.
|
||||||
private boolean seen = false;
|
final Class<?> returnType = creationMethod.getReturnType();
|
||||||
|
if (SERVICE_CLASS.isAssignableFrom(returnType)) {
|
||||||
public final void remove() { throw new UnsupportedOperationException(); }
|
return SERVICE_CLASS.cast(creationMethod.invoke(null, (Object[])null));
|
||||||
public final boolean hasNext() { return !seen; }
|
} else {
|
||||||
public final Object next() {
|
// Should not happen since
|
||||||
if(seen) throw new NoSuchElementException();
|
// XMLSchemaFactory.newXMLSchemaFactoryNoServiceLoader is
|
||||||
seen = true;
|
// declared to return XMLSchemaFactory.
|
||||||
return value();
|
throw new ClassCastException(returnType
|
||||||
}
|
+ " cannot be cast to " + SERVICE_CLASS);
|
||||||
|
}
|
||||||
protected abstract Object value();
|
} catch(ClassCastException e) {
|
||||||
}
|
throw new SchemaFactoryConfigurationError(e.getMessage(), e);
|
||||||
|
} catch (NoSuchMethodException exc) {
|
||||||
/**
|
return null;
|
||||||
* Looks up a value in a property file
|
} catch (Exception exc) {
|
||||||
* while producing all sorts of debug messages.
|
|
||||||
*
|
|
||||||
* @return null
|
|
||||||
* if there was an error.
|
|
||||||
*/
|
|
||||||
private SchemaFactory loadFromProperty( String keyName, String resourceName, InputStream in )
|
|
||||||
throws IOException {
|
|
||||||
debugPrintln("Reading "+resourceName );
|
|
||||||
|
|
||||||
Properties props=new Properties();
|
|
||||||
props.load(in);
|
|
||||||
in.close();
|
|
||||||
String factoryClassName = props.getProperty(keyName);
|
|
||||||
if(factoryClassName != null){
|
|
||||||
debugPrintln("found "+keyName+" = " + factoryClassName);
|
|
||||||
return createInstance(factoryClassName);
|
|
||||||
} else {
|
|
||||||
debugPrintln(keyName+" is not in the property file");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
// Call isSchemaLanguageSupported with initial context.
|
||||||
* <p>Look up a value in a property file.</p>
|
private boolean isSchemaLanguageSupportedBy(final SchemaFactory factory,
|
||||||
*
|
final String schemaLanguage,
|
||||||
* <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p>
|
AccessControlContext acc) {
|
||||||
*
|
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||||
* @param schemaLanguage Schema Language to support.
|
public Boolean run() {
|
||||||
* @param inputName Name of <code>InputStream</code>.
|
return factory.isSchemaLanguageSupported(schemaLanguage);
|
||||||
* @param in <code>InputStream</code> of properties.
|
|
||||||
*
|
|
||||||
* @return <code>SchemaFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error.
|
|
||||||
*
|
|
||||||
* @throws IOException If IO error reading from <code>in</code>.
|
|
||||||
*/
|
|
||||||
private SchemaFactory loadFromService(
|
|
||||||
String schemaLanguage,
|
|
||||||
String inputName,
|
|
||||||
InputStream in)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
SchemaFactory schemaFactory = null;
|
|
||||||
final Class[] stringClassArray = {"".getClass()};
|
|
||||||
final Object[] schemaLanguageObjectArray = {schemaLanguage};
|
|
||||||
final String isSchemaLanguageSupportedMethod = "isSchemaLanguageSupported";
|
|
||||||
|
|
||||||
debugPrintln("Reading " + inputName);
|
|
||||||
|
|
||||||
// read from InputStream until a match is found
|
|
||||||
BufferedReader configFile = new BufferedReader(new InputStreamReader(in));
|
|
||||||
String line = null;
|
|
||||||
while ((line = configFile.readLine()) != null) {
|
|
||||||
// '#' is comment char
|
|
||||||
int comment = line.indexOf("#");
|
|
||||||
switch (comment) {
|
|
||||||
case -1: break; // no comment
|
|
||||||
case 0: line = ""; break; // entire line is a comment
|
|
||||||
default: line = line.substring(0, comment); break; // trim comment
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim whitespace
|
|
||||||
line = line.trim();
|
|
||||||
|
|
||||||
// any content left on line?
|
|
||||||
if (line.length() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// line content is now the name of the class
|
|
||||||
Class clazz = createClass(line);
|
|
||||||
if (clazz == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an instance of the Class
|
|
||||||
try {
|
|
||||||
schemaFactory = (SchemaFactory) clazz.newInstance();
|
|
||||||
} catch (ClassCastException classCastExcpetion) {
|
|
||||||
schemaFactory = null;
|
|
||||||
continue;
|
|
||||||
} catch (InstantiationException instantiationException) {
|
|
||||||
schemaFactory = null;
|
|
||||||
continue;
|
|
||||||
} catch (IllegalAccessException illegalAccessException) {
|
|
||||||
schemaFactory = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// does this Class support desired Schema?
|
|
||||||
try {
|
|
||||||
Method isSchemaLanguageSupported = clazz.getMethod(isSchemaLanguageSupportedMethod, stringClassArray);
|
|
||||||
Boolean supported = (Boolean) isSchemaLanguageSupported.invoke(schemaFactory, schemaLanguageObjectArray);
|
|
||||||
if (supported.booleanValue()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} catch (NoSuchMethodException noSuchMethodException) {
|
|
||||||
|
|
||||||
} catch (IllegalAccessException illegalAccessException) {
|
|
||||||
|
|
||||||
} catch (InvocationTargetException invocationTargetException) {
|
|
||||||
|
|
||||||
}
|
|
||||||
schemaFactory = null;
|
|
||||||
}
|
}
|
||||||
|
}, acc);
|
||||||
// clean up
|
|
||||||
configFile.close();
|
|
||||||
|
|
||||||
// return new instance of SchemaFactory or null
|
|
||||||
return schemaFactory;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an {@link Iterator} that enumerates all
|
* Finds a service provider subclass of SchemaFactory that supports the
|
||||||
* the META-INF/services files that we care.
|
* given schema language using the ServiceLoader.
|
||||||
|
*
|
||||||
|
* @param schemaLanguage The schema language for which we seek a factory.
|
||||||
|
* @return A SchemaFactory supporting the specified schema language, or null
|
||||||
|
* if none is found.
|
||||||
|
* @throws SchemaFactoryConfigurationError if a configuration error is found.
|
||||||
*/
|
*/
|
||||||
private Iterator createServiceFileIterator() {
|
private SchemaFactory findServiceProvider(final String schemaLanguage) {
|
||||||
if (classLoader == null) {
|
assert schemaLanguage != null;
|
||||||
return new SingleIterator() {
|
// store current context.
|
||||||
protected Object value() {
|
final AccessControlContext acc = AccessController.getContext();
|
||||||
ClassLoader classLoader = SchemaFactoryFinder.class.getClassLoader();
|
try {
|
||||||
//return (ClassLoader.getSystemResource( SERVICE_ID ));
|
return AccessController.doPrivileged(new PrivilegedAction<SchemaFactory>() {
|
||||||
return ss.getResourceAsURL(classLoader, SERVICE_ID);
|
public SchemaFactory run() {
|
||||||
|
final ServiceLoader<SchemaFactory> loader =
|
||||||
|
ServiceLoader.load(SERVICE_CLASS);
|
||||||
|
for (SchemaFactory factory : loader) {
|
||||||
|
// restore initial context to call
|
||||||
|
// factory.isSchemaLanguageSupported
|
||||||
|
if (isSchemaLanguageSupportedBy(factory, schemaLanguage, acc)) {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; // no factory found.
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
} else {
|
} catch (ServiceConfigurationError error) {
|
||||||
try {
|
throw new SchemaFactoryConfigurationError(
|
||||||
//final Enumeration e = classLoader.getResources(SERVICE_ID);
|
"Provider for " + SERVICE_CLASS + " cannot be created", error);
|
||||||
final Enumeration e = ss.getResources(classLoader, SERVICE_ID);
|
|
||||||
if(!e.hasMoreElements()) {
|
|
||||||
debugPrintln("no "+SERVICE_ID+" file was found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrap it into an Iterator.
|
|
||||||
return new Iterator() {
|
|
||||||
public void remove() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return e.hasMoreElements();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object next() {
|
|
||||||
return e.nextElement();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (IOException e) {
|
|
||||||
debugPrintln("failed to enumerate resources "+SERVICE_ID);
|
|
||||||
if(debug) e.printStackTrace();
|
|
||||||
return new ArrayList().iterator(); // empty iterator
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Class SERVICE_CLASS = SchemaFactory.class;
|
private static final Class<SchemaFactory> SERVICE_CLASS = SchemaFactory.class;
|
||||||
private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName();
|
|
||||||
|
|
||||||
|
|
||||||
|
private static String which( Class<?> clazz ) {
|
||||||
private static String which( Class clazz ) {
|
|
||||||
return which( clazz.getName(), clazz.getClassLoader() );
|
return which( clazz.getName(), clazz.getClassLoader() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -90,7 +90,7 @@ public abstract class XPathFactory {
|
|||||||
* @throws RuntimeException When there is a failure in creating an
|
* @throws RuntimeException When there is a failure in creating an
|
||||||
* <code>XPathFactory</code> for the default object model.
|
* <code>XPathFactory</code> for the default object model.
|
||||||
*/
|
*/
|
||||||
public static final XPathFactory newInstance() {
|
public static XPathFactory newInstance() {
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return newInstance(DEFAULT_OBJECT_MODEL_URI);
|
return newInstance(DEFAULT_OBJECT_MODEL_URI);
|
||||||
@ -121,14 +121,17 @@ public abstract class XPathFactory {
|
|||||||
* If present, the value is processed just like above.
|
* If present, the value is processed just like above.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* The class loader is asked for service provider provider-configuration files matching <code>javax.xml.xpath.XPathFactory</code>
|
* Use the service-provider loading facilities, defined by the
|
||||||
* in the resource directory META-INF/services.
|
* {@link java.util.ServiceLoader} class, to attempt to locate and load an
|
||||||
* See the JAR File Specification for file format and parsing rules.
|
* implementation of the service.
|
||||||
* Each potential service provider is required to implement the method:
|
* <br>
|
||||||
* <pre>
|
* Each potential service provider is required to implement the method
|
||||||
* {@link #isObjectModelSupported(String objectModel)}
|
* {@link #isObjectModelSupported(String objectModel)}.
|
||||||
* </pre>
|
* The first service provider found that supports the specified object
|
||||||
* The first service provider found in class loader order that supports the specified object model is returned.
|
* model is returned.
|
||||||
|
* <br>
|
||||||
|
* In case of {@link java.util.ServiceConfigurationError} an
|
||||||
|
* {@link XPathFactoryConfigurationException} will be thrown.
|
||||||
* </li>
|
* </li>
|
||||||
* <li>
|
* <li>
|
||||||
* Platform default <code>XPathFactory</code> is located in a platform specific way.
|
* Platform default <code>XPathFactory</code> is located in a platform specific way.
|
||||||
@ -152,43 +155,41 @@ public abstract class XPathFactory {
|
|||||||
*
|
*
|
||||||
* @return Instance of an <code>XPathFactory</code>.
|
* @return Instance of an <code>XPathFactory</code>.
|
||||||
*
|
*
|
||||||
* @throws XPathFactoryConfigurationException If the specified object model is unavailable.
|
* @throws XPathFactoryConfigurationException If the specified object model
|
||||||
|
* is unavailable, or if there is a configuration error.
|
||||||
* @throws NullPointerException If <code>uri</code> is <code>null</code>.
|
* @throws NullPointerException If <code>uri</code> is <code>null</code>.
|
||||||
* @throws IllegalArgumentException If <code>uri</code> is <code>null</code>
|
* @throws IllegalArgumentException If <code>uri</code> is <code>null</code>
|
||||||
* or <code>uri.length() == 0</code>.
|
* or <code>uri.length() == 0</code>.
|
||||||
*/
|
*/
|
||||||
public static final XPathFactory newInstance(final String uri)
|
public static XPathFactory newInstance(final String uri)
|
||||||
throws XPathFactoryConfigurationException {
|
throws XPathFactoryConfigurationException {
|
||||||
|
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
throw new NullPointerException(
|
throw new NullPointerException(
|
||||||
"XPathFactory#newInstance(String uri) cannot be called with uri == null"
|
"XPathFactory#newInstance(String uri) cannot be called with uri == null");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uri.length() == 0) {
|
if (uri.length() == 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
|
"XPathFactory#newInstance(String uri) cannot be called with uri == \"\"");
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
ClassLoader classLoader = ss.getContextClassLoader();
|
ClassLoader classLoader = ss.getContextClassLoader();
|
||||||
|
|
||||||
if (classLoader == null) {
|
if (classLoader == null) {
|
||||||
//use the current class loader
|
//use the current class loader
|
||||||
classLoader = XPathFactory.class.getClassLoader();
|
classLoader = XPathFactory.class.getClassLoader();
|
||||||
}
|
}
|
||||||
|
|
||||||
XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
|
XPathFactory xpathFactory = new XPathFactoryFinder(classLoader).newFactory(uri);
|
||||||
|
|
||||||
if (xpathFactory == null) {
|
if (xpathFactory == null) {
|
||||||
throw new XPathFactoryConfigurationException(
|
throw new XPathFactoryConfigurationException(
|
||||||
"No XPathFactory implementation found for the object model: "
|
"No XPathFactory implementation found for the object model: "
|
||||||
+ uri
|
+ uri);
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return xpathFactory;
|
return xpathFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -242,16 +243,14 @@ public abstract class XPathFactory {
|
|||||||
ClassLoader cl = classLoader;
|
ClassLoader cl = classLoader;
|
||||||
|
|
||||||
if (uri == null) {
|
if (uri == null) {
|
||||||
throw new NullPointerException(
|
throw new NullPointerException(
|
||||||
"XPathFactory#newInstance(String uri) cannot be called with uri == null"
|
"XPathFactory#newInstance(String uri) cannot be called with uri == null");
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uri.length() == 0) {
|
if (uri.length() == 0) {
|
||||||
throw new IllegalArgumentException(
|
throw new IllegalArgumentException(
|
||||||
"XPathFactory#newInstance(String uri) cannot be called with uri == \"\""
|
"XPathFactory#newInstance(String uri) cannot be called with uri == \"\"");
|
||||||
);
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (cl == null) {
|
if (cl == null) {
|
||||||
cl = ss.getContextClassLoader();
|
cl = ss.getContextClassLoader();
|
||||||
@ -260,31 +259,32 @@ public abstract class XPathFactory {
|
|||||||
XPathFactory f = new XPathFactoryFinder(cl).createInstance(factoryClassName);
|
XPathFactory f = new XPathFactoryFinder(cl).createInstance(factoryClassName);
|
||||||
|
|
||||||
if (f == null) {
|
if (f == null) {
|
||||||
throw new XPathFactoryConfigurationException(
|
throw new XPathFactoryConfigurationException(
|
||||||
"No XPathFactory implementation found for the object model: "
|
"No XPathFactory implementation found for the object model: "
|
||||||
+ uri
|
+ uri);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
//if this factory supports the given schemalanguage return this factory else thrown exception
|
//if this factory supports the given schemalanguage return this factory else thrown exception
|
||||||
if(f.isObjectModelSupported(uri)){
|
if (f.isObjectModelSupported(uri)) {
|
||||||
return f;
|
return f;
|
||||||
}else{
|
} else {
|
||||||
throw new XPathFactoryConfigurationException("Factory " + factoryClassName + " doesn't support given " + uri + " object model");
|
throw new XPathFactoryConfigurationException("Factory "
|
||||||
|
+ factoryClassName + " doesn't support given " + uri
|
||||||
|
+ " object model");
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Is specified object model supported by this <code>XPathFactory</code>?</p>
|
* <p>Is specified object model supported by this <code>XPathFactory</code>?</p>
|
||||||
*
|
*
|
||||||
* @param objectModel Specifies the object model which the returned <code>XPathFactory</code> will understand.
|
* @param objectModel Specifies the object model which the returned <code>XPathFactory</code> will understand.
|
||||||
*
|
*
|
||||||
* @return <code>true</code> if <code>XPathFactory</code> supports <code>objectModel</code>, else <code>false</code>.
|
* @return <code>true</code> if <code>XPathFactory</code> supports <code>objectModel</code>, else <code>false</code>.
|
||||||
*
|
*
|
||||||
* @throws NullPointerException If <code>objectModel</code> is <code>null</code>.
|
* @throws NullPointerException If <code>objectModel</code> is <code>null</code>.
|
||||||
* @throws IllegalArgumentException If <code>objectModel.length() == 0</code>.
|
* @throws IllegalArgumentException If <code>objectModel.length() == 0</code>.
|
||||||
*/
|
*/
|
||||||
public abstract boolean isObjectModelSupported(String objectModel);
|
public abstract boolean isObjectModelSupported(String objectModel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Set a feature for this <code>XPathFactory</code> and
|
* <p>Set a feature for this <code>XPathFactory</code> and
|
||||||
@ -314,8 +314,8 @@ public abstract class XPathFactory {
|
|||||||
* it creates cannot support this feature.
|
* it creates cannot support this feature.
|
||||||
* @throws NullPointerException if <code>name</code> is <code>null</code>.
|
* @throws NullPointerException if <code>name</code> is <code>null</code>.
|
||||||
*/
|
*/
|
||||||
public abstract void setFeature(String name, boolean value)
|
public abstract void setFeature(String name, boolean value)
|
||||||
throws XPathFactoryConfigurationException;
|
throws XPathFactoryConfigurationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Get the state of the named feature.</p>
|
* <p>Get the state of the named feature.</p>
|
||||||
@ -339,8 +339,8 @@ public abstract class XPathFactory {
|
|||||||
* it creates cannot support this feature.
|
* it creates cannot support this feature.
|
||||||
* @throws NullPointerException if <code>name</code> is <code>null</code>.
|
* @throws NullPointerException if <code>name</code> is <code>null</code>.
|
||||||
*/
|
*/
|
||||||
public abstract boolean getFeature(String name)
|
public abstract boolean getFeature(String name)
|
||||||
throws XPathFactoryConfigurationException;
|
throws XPathFactoryConfigurationException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Establish a default variable resolver.</p>
|
* <p>Establish a default variable resolver.</p>
|
||||||
@ -359,19 +359,19 @@ public abstract class XPathFactory {
|
|||||||
public abstract void setXPathVariableResolver(XPathVariableResolver resolver);
|
public abstract void setXPathVariableResolver(XPathVariableResolver resolver);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Establish a default function resolver.</p>
|
* <p>Establish a default function resolver.</p>
|
||||||
*
|
*
|
||||||
* <p>Any <code>XPath</code> objects constructed from this factory will
|
* <p>Any <code>XPath</code> objects constructed from this factory will
|
||||||
* use the specified resolver by default.</p>
|
* use the specified resolver by default.</p>
|
||||||
*
|
*
|
||||||
* <p>A <code>NullPointerException</code> is thrown if
|
* <p>A <code>NullPointerException</code> is thrown if
|
||||||
* <code>resolver</code> is <code>null</code>.</p>
|
* <code>resolver</code> is <code>null</code>.</p>
|
||||||
*
|
*
|
||||||
* @param resolver XPath function resolver.
|
* @param resolver XPath function resolver.
|
||||||
*
|
*
|
||||||
* @throws NullPointerException If <code>resolver</code> is
|
* @throws NullPointerException If <code>resolver</code> is
|
||||||
* <code>null</code>.
|
* <code>null</code>.
|
||||||
*/
|
*/
|
||||||
public abstract void setXPathFunctionResolver(XPathFunctionResolver resolver);
|
public abstract void setXPathFunctionResolver(XPathFunctionResolver resolver);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2004, 2005, Oracle and/or its affiliates. All rights reserved.
|
* Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved.
|
||||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||||
*
|
*
|
||||||
* This code is free software; you can redistribute it and/or modify it
|
* This code is free software; you can redistribute it and/or modify it
|
||||||
@ -25,20 +25,16 @@
|
|||||||
|
|
||||||
package javax.xml.xpath;
|
package javax.xml.xpath;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.Modifier;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.ArrayList;
|
import java.security.AccessControlContext;
|
||||||
import java.util.Enumeration;
|
import java.security.AccessController;
|
||||||
import java.util.Iterator;
|
import java.security.PrivilegedAction;
|
||||||
import java.util.NoSuchElementException;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
import java.util.ServiceConfigurationError;
|
||||||
|
import java.util.ServiceLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Implementation of {@link XPathFactory#newInstance(String)}.
|
* Implementation of {@link XPathFactory#newInstance(String)}.
|
||||||
@ -50,7 +46,7 @@ import java.util.Properties;
|
|||||||
class XPathFactoryFinder {
|
class XPathFactoryFinder {
|
||||||
private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xpath.internal";
|
private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xpath.internal";
|
||||||
|
|
||||||
private static SecuritySupport ss = new SecuritySupport() ;
|
private static final SecuritySupport ss = new SecuritySupport() ;
|
||||||
/** debug support code. */
|
/** debug support code. */
|
||||||
private static boolean debug = false;
|
private static boolean debug = false;
|
||||||
static {
|
static {
|
||||||
@ -65,12 +61,12 @@ class XPathFactoryFinder {
|
|||||||
/**
|
/**
|
||||||
* <p>Cache properties for performance.</p>
|
* <p>Cache properties for performance.</p>
|
||||||
*/
|
*/
|
||||||
private static Properties cacheProps = new Properties();
|
private static final Properties cacheProps = new Properties();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>First time requires initialization overhead.</p>
|
* <p>First time requires initialization overhead.</p>
|
||||||
*/
|
*/
|
||||||
private volatile static boolean firstTime = true;
|
private volatile static boolean firstTime = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Conditional debug printing.</p>
|
* <p>Conditional debug printing.</p>
|
||||||
@ -93,9 +89,8 @@ class XPathFactoryFinder {
|
|||||||
* to find <code>XPathFactory</code>.</p>
|
* to find <code>XPathFactory</code>.</p>
|
||||||
*
|
*
|
||||||
* @param loader
|
* @param loader
|
||||||
* to be used to load resource, {@link XPathFactory}, and
|
* to be used to load resource and {@link XPathFactory}
|
||||||
* {@link SchemaFactoryLoader} implementations during
|
* implementations during the resolution process.
|
||||||
* the resolution process.
|
|
||||||
* If this parameter is null, the default system class loader
|
* If this parameter is null, the default system class loader
|
||||||
* will be used.
|
* will be used.
|
||||||
*/
|
*/
|
||||||
@ -113,7 +108,7 @@ class XPathFactoryFinder {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
} catch( Throwable unused ) {
|
} catch( Throwable unused ) {
|
||||||
; // getContextClassLoader() undefined in JDK1.1
|
// getContextClassLoader() undefined in JDK1.1
|
||||||
}
|
}
|
||||||
|
|
||||||
if( classLoader==ClassLoader.getSystemClassLoader() ) {
|
if( classLoader==ClassLoader.getSystemClassLoader() ) {
|
||||||
@ -126,7 +121,7 @@ class XPathFactoryFinder {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Creates a new {@link XPathFactory} object for the specified
|
* <p>Creates a new {@link XPathFactory} object for the specified
|
||||||
* schema language.</p>
|
* object model.</p>
|
||||||
*
|
*
|
||||||
* @param uri
|
* @param uri
|
||||||
* Identifies the underlying object model.
|
* Identifies the underlying object model.
|
||||||
@ -136,8 +131,10 @@ class XPathFactoryFinder {
|
|||||||
* @throws NullPointerException
|
* @throws NullPointerException
|
||||||
* If the parameter is null.
|
* If the parameter is null.
|
||||||
*/
|
*/
|
||||||
public XPathFactory newFactory(String uri) {
|
public XPathFactory newFactory(String uri) throws XPathFactoryConfigurationException {
|
||||||
if(uri==null) throw new NullPointerException();
|
if (uri == null) {
|
||||||
|
throw new NullPointerException();
|
||||||
|
}
|
||||||
XPathFactory f = _newFactory(uri);
|
XPathFactory f = _newFactory(uri);
|
||||||
if (f != null) {
|
if (f != null) {
|
||||||
debugPrintln("factory '" + f.getClass().getName() + "' was found for " + uri);
|
debugPrintln("factory '" + f.getClass().getName() + "' was found for " + uri);
|
||||||
@ -154,8 +151,8 @@ class XPathFactoryFinder {
|
|||||||
*
|
*
|
||||||
* @return {@link XPathFactory} for the given object model.
|
* @return {@link XPathFactory} for the given object model.
|
||||||
*/
|
*/
|
||||||
private XPathFactory _newFactory(String uri) {
|
private XPathFactory _newFactory(String uri) throws XPathFactoryConfigurationException {
|
||||||
XPathFactory xpathFactory;
|
XPathFactory xpathFactory = null;
|
||||||
|
|
||||||
String propertyName = SERVICE_CLASS.getName() + ":" + uri;
|
String propertyName = SERVICE_CLASS.getName() + ":" + uri;
|
||||||
|
|
||||||
@ -166,7 +163,9 @@ class XPathFactoryFinder {
|
|||||||
if(r!=null) {
|
if(r!=null) {
|
||||||
debugPrintln("The value is '"+r+"'");
|
debugPrintln("The value is '"+r+"'");
|
||||||
xpathFactory = createInstance(r, true);
|
xpathFactory = createInstance(r, true);
|
||||||
if(xpathFactory != null) return xpathFactory;
|
if (xpathFactory != null) {
|
||||||
|
return xpathFactory;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
debugPrintln("The property is undefined.");
|
debugPrintln("The property is undefined.");
|
||||||
} catch( Throwable t ) {
|
} catch( Throwable t ) {
|
||||||
@ -180,8 +179,6 @@ class XPathFactoryFinder {
|
|||||||
String configFile = javah + File.separator +
|
String configFile = javah + File.separator +
|
||||||
"lib" + File.separator + "jaxp.properties";
|
"lib" + File.separator + "jaxp.properties";
|
||||||
|
|
||||||
String factoryClassName = null ;
|
|
||||||
|
|
||||||
// try to read from $java.home/lib/jaxp.properties
|
// try to read from $java.home/lib/jaxp.properties
|
||||||
try {
|
try {
|
||||||
if(firstTime){
|
if(firstTime){
|
||||||
@ -196,7 +193,7 @@ class XPathFactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
factoryClassName = cacheProps.getProperty(propertyName);
|
final String factoryClassName = cacheProps.getProperty(propertyName);
|
||||||
debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
|
debugPrintln("found " + factoryClassName + " in $java.home/jaxp.properties");
|
||||||
|
|
||||||
if (factoryClassName != null) {
|
if (factoryClassName != null) {
|
||||||
@ -211,23 +208,16 @@ class XPathFactoryFinder {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// try META-INF/services files
|
// Try with ServiceLoader
|
||||||
Iterator sitr = createServiceFileIterator();
|
assert xpathFactory == null;
|
||||||
while(sitr.hasNext()) {
|
xpathFactory = findServiceProvider(uri);
|
||||||
URL resource = (URL)sitr.next();
|
|
||||||
debugPrintln("looking into " + resource);
|
// The following assertion should always be true.
|
||||||
try {
|
// Uncomment it, recompile, and run with -ea in case of doubts:
|
||||||
xpathFactory = loadFromService(uri, resource.toExternalForm(),
|
// assert xpathFactory == null || xpathFactory.isObjectModelSupported(uri);
|
||||||
ss.getURLInputStream(resource));
|
|
||||||
if (xpathFactory != null) {
|
if (xpathFactory != null) {
|
||||||
return xpathFactory;
|
return xpathFactory;
|
||||||
}
|
|
||||||
} catch(IOException e) {
|
|
||||||
if( debug ) {
|
|
||||||
debugPrintln("failed to read "+resource);
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// platform default
|
// platform default
|
||||||
@ -245,8 +235,8 @@ class XPathFactoryFinder {
|
|||||||
* @param className Name of class to create.
|
* @param className Name of class to create.
|
||||||
* @return Created class or <code>null</code>.
|
* @return Created class or <code>null</code>.
|
||||||
*/
|
*/
|
||||||
private Class createClass(String className) {
|
private Class<?> createClass(String className) {
|
||||||
Class clazz;
|
Class clazz;
|
||||||
// make sure we have access to restricted packages
|
// make sure we have access to restricted packages
|
||||||
boolean internal = false;
|
boolean internal = false;
|
||||||
if (System.getSecurityManager() != null) {
|
if (System.getSecurityManager() != null) {
|
||||||
@ -258,47 +248,54 @@ class XPathFactoryFinder {
|
|||||||
// use approprite ClassLoader
|
// use approprite ClassLoader
|
||||||
try {
|
try {
|
||||||
if (classLoader != null && !internal) {
|
if (classLoader != null && !internal) {
|
||||||
clazz = classLoader.loadClass(className);
|
clazz = Class.forName(className, false, classLoader);
|
||||||
} else {
|
} else {
|
||||||
clazz = Class.forName(className);
|
clazz = Class.forName(className);
|
||||||
}
|
}
|
||||||
} catch (Throwable t) {
|
} catch (Throwable t) {
|
||||||
if(debug) t.printStackTrace();
|
if(debug) {
|
||||||
return null;
|
t.printStackTrace();
|
||||||
|
}
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return clazz;
|
return clazz;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Creates an instance of the specified and returns it.</p>
|
* <p>Creates an instance of the specified and returns it.</p>
|
||||||
*
|
*
|
||||||
* @param className
|
* @param className
|
||||||
* fully qualified class name to be instanciated.
|
* fully qualified class name to be instantiated.
|
||||||
*
|
*
|
||||||
* @return null
|
* @return null
|
||||||
* if it fails. Error messages will be printed by this method.
|
* if it fails. Error messages will be printed by this method.
|
||||||
*/
|
*/
|
||||||
XPathFactory createInstance( String className ) {
|
XPathFactory createInstance( String className )
|
||||||
|
throws XPathFactoryConfigurationException
|
||||||
|
{
|
||||||
return createInstance( className, false );
|
return createInstance( className, false );
|
||||||
}
|
}
|
||||||
XPathFactory createInstance( String className, boolean useServicesMechanism ) {
|
|
||||||
|
XPathFactory createInstance( String className, boolean useServicesMechanism )
|
||||||
|
throws XPathFactoryConfigurationException
|
||||||
|
{
|
||||||
XPathFactory xPathFactory = null;
|
XPathFactory xPathFactory = null;
|
||||||
|
|
||||||
debugPrintln("createInstance(" + className + ")");
|
debugPrintln("createInstance(" + className + ")");
|
||||||
|
|
||||||
// get Class from className
|
// get Class from className
|
||||||
Class clazz = createClass(className);
|
Class<?> clazz = createClass(className);
|
||||||
if (clazz == null) {
|
if (clazz == null) {
|
||||||
debugPrintln("failed to getClass(" + className + ")");
|
debugPrintln("failed to getClass(" + className + ")");
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
debugPrintln("loaded " + className + " from " + which(clazz));
|
debugPrintln("loaded " + className + " from " + which(clazz));
|
||||||
|
|
||||||
// instantiate Class as a XPathFactory
|
// instantiate Class as a XPathFactory
|
||||||
try {
|
try {
|
||||||
if (!useServicesMechanism) {
|
if (!useServicesMechanism) {
|
||||||
xPathFactory = (XPathFactory) newInstanceNoServiceLoader(clazz);
|
xPathFactory = newInstanceNoServiceLoader(clazz);
|
||||||
}
|
}
|
||||||
if (xPathFactory == null) {
|
if (xPathFactory == null) {
|
||||||
xPathFactory = (XPathFactory) clazz.newInstance();
|
xPathFactory = (XPathFactory) clazz.newInstance();
|
||||||
@ -329,203 +326,94 @@ class XPathFactoryFinder {
|
|||||||
* Try to construct using newXPathFactoryNoServiceLoader
|
* Try to construct using newXPathFactoryNoServiceLoader
|
||||||
* method if available.
|
* method if available.
|
||||||
*/
|
*/
|
||||||
private static Object newInstanceNoServiceLoader(
|
private static XPathFactory newInstanceNoServiceLoader(
|
||||||
Class<?> providerClass
|
Class<?> providerClass
|
||||||
) {
|
) throws XPathFactoryConfigurationException {
|
||||||
// Retain maximum compatibility if no security manager.
|
// Retain maximum compatibility if no security manager.
|
||||||
if (System.getSecurityManager() == null) {
|
if (System.getSecurityManager() == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
Method creationMethod =
|
Method creationMethod =
|
||||||
providerClass.getDeclaredMethod(
|
providerClass.getDeclaredMethod(
|
||||||
"newXPathFactoryNoServiceLoader"
|
"newXPathFactoryNoServiceLoader"
|
||||||
);
|
);
|
||||||
return creationMethod.invoke(null, (Object[])null);
|
final int modifiers = creationMethod.getModifiers();
|
||||||
} catch (NoSuchMethodException exc) {
|
|
||||||
|
// Do not call "newXPathFactoryNoServiceLoader" if it's
|
||||||
|
// not public static.
|
||||||
|
if (!Modifier.isStatic(modifiers) || !Modifier.isPublic(modifiers)) {
|
||||||
return null;
|
return null;
|
||||||
} catch (Exception exc) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>Look up a value in a property file.</p>
|
|
||||||
*
|
|
||||||
* <p>Set <code>debug</code> to <code>true</code> to trace property evaluation.</p>
|
|
||||||
*
|
|
||||||
* @param objectModel URI of object model to support.
|
|
||||||
* @param inputName Name of <code>InputStream</code>.
|
|
||||||
* @param in <code>InputStream</code> of properties.
|
|
||||||
*
|
|
||||||
* @return <code>XPathFactory</code> as determined by <code>keyName</code> value or <code>null</code> if there was an error.
|
|
||||||
*
|
|
||||||
* @throws IOException If IO error reading from <code>in</code>.
|
|
||||||
*/
|
|
||||||
private XPathFactory loadFromService(
|
|
||||||
String objectModel,
|
|
||||||
String inputName,
|
|
||||||
InputStream in)
|
|
||||||
throws IOException {
|
|
||||||
|
|
||||||
XPathFactory xPathFactory = null;
|
|
||||||
final Class[] stringClassArray = {"".getClass()};
|
|
||||||
final Object[] objectModelObjectArray = {objectModel};
|
|
||||||
final String isObjectModelSupportedMethod = "isObjectModelSupported";
|
|
||||||
|
|
||||||
debugPrintln("Reading " + inputName);
|
|
||||||
|
|
||||||
// read from InputStream until a match is found
|
|
||||||
BufferedReader configFile = new BufferedReader(new InputStreamReader(in));
|
|
||||||
String line = null;
|
|
||||||
while ((line = configFile.readLine()) != null) {
|
|
||||||
// '#' is comment char
|
|
||||||
int comment = line.indexOf("#");
|
|
||||||
switch (comment) {
|
|
||||||
case -1: break; // no comment
|
|
||||||
case 0: line = ""; break; // entire line is a comment
|
|
||||||
default: line = line.substring(0, comment); break; // trim comment
|
|
||||||
}
|
|
||||||
|
|
||||||
// trim whitespace
|
|
||||||
line = line.trim();
|
|
||||||
|
|
||||||
// any content left on line?
|
|
||||||
if (line.length() == 0) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// line content is now the name of the class
|
|
||||||
Class clazz = createClass(line);
|
|
||||||
if (clazz == null) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// create an instance of the Class
|
|
||||||
try {
|
|
||||||
xPathFactory = (XPathFactory) clazz.newInstance();
|
|
||||||
} catch (ClassCastException classCastExcpetion) {
|
|
||||||
xPathFactory = null;
|
|
||||||
continue;
|
|
||||||
} catch (InstantiationException instantiationException) {
|
|
||||||
xPathFactory = null;
|
|
||||||
continue;
|
|
||||||
} catch (IllegalAccessException illegalAccessException) {
|
|
||||||
xPathFactory = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// does this Class support desired object model?
|
|
||||||
try {
|
|
||||||
Method isObjectModelSupported = clazz.getMethod(isObjectModelSupportedMethod, stringClassArray);
|
|
||||||
Boolean supported = (Boolean) isObjectModelSupported.invoke(xPathFactory, objectModelObjectArray);
|
|
||||||
if (supported.booleanValue()) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (NoSuchMethodException noSuchMethodException) {
|
|
||||||
|
|
||||||
} catch (IllegalAccessException illegalAccessException) {
|
|
||||||
|
|
||||||
} catch (InvocationTargetException invocationTargetException) {
|
|
||||||
|
|
||||||
}
|
|
||||||
xPathFactory = null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clean up
|
// Only calls "newXPathFactoryNoServiceLoader" if it's
|
||||||
configFile.close();
|
// declared to return an instance of XPathFactory.
|
||||||
|
final Class<?> returnType = creationMethod.getReturnType();
|
||||||
// return new instance of XPathFactory or null
|
if (SERVICE_CLASS.isAssignableFrom(returnType)) {
|
||||||
return xPathFactory;
|
return SERVICE_CLASS.cast(creationMethod.invoke(null, (Object[])null));
|
||||||
}
|
} else {
|
||||||
|
// Should not happen since
|
||||||
/** Iterator that lazily computes one value and returns it. */
|
// XPathFactoryImpl.newXPathFactoryNoServiceLoader is
|
||||||
private static abstract class SingleIterator implements Iterator {
|
// declared to return XPathFactory.
|
||||||
private boolean seen = false;
|
throw new ClassCastException(returnType
|
||||||
|
+ " cannot be cast to " + SERVICE_CLASS);
|
||||||
public final void remove() { throw new UnsupportedOperationException(); }
|
}
|
||||||
public final boolean hasNext() { return !seen; }
|
} catch (ClassCastException e) {
|
||||||
public final Object next() {
|
throw new XPathFactoryConfigurationException(e);
|
||||||
if(seen) throw new NoSuchElementException();
|
} catch (NoSuchMethodException exc) {
|
||||||
seen = true;
|
return null;
|
||||||
return value();
|
} catch (Exception exc) {
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Object value();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Looks up a value in a property file
|
|
||||||
* while producing all sorts of debug messages.
|
|
||||||
*
|
|
||||||
* @return null
|
|
||||||
* if there was an error.
|
|
||||||
*/
|
|
||||||
private XPathFactory loadFromProperty( String keyName, String resourceName, InputStream in )
|
|
||||||
throws IOException {
|
|
||||||
debugPrintln("Reading "+resourceName );
|
|
||||||
|
|
||||||
Properties props = new Properties();
|
|
||||||
props.load(in);
|
|
||||||
in.close();
|
|
||||||
String factoryClassName = props.getProperty(keyName);
|
|
||||||
if(factoryClassName != null){
|
|
||||||
debugPrintln("found "+keyName+" = " + factoryClassName);
|
|
||||||
return createInstance(factoryClassName, true);
|
|
||||||
} else {
|
|
||||||
debugPrintln(keyName+" is not in the property file");
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Call isObjectModelSupportedBy with initial context.
|
||||||
|
private boolean isObjectModelSupportedBy(final XPathFactory factory,
|
||||||
|
final String objectModel,
|
||||||
|
AccessControlContext acc) {
|
||||||
|
return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
|
||||||
|
public Boolean run() {
|
||||||
|
return factory.isObjectModelSupported(objectModel);
|
||||||
|
}
|
||||||
|
}, acc);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns an {@link Iterator} that enumerates all
|
* Finds a service provider subclass of XPathFactory that supports the
|
||||||
* the META-INF/services files that we care.
|
* given object model using the ServiceLoader.
|
||||||
|
*
|
||||||
|
* @param objectModel URI of object model to support.
|
||||||
|
* @return An XPathFactory supporting the specified object model, or null
|
||||||
|
* if none is found.
|
||||||
|
* @throws XPathFactoryConfigurationException if a configuration error is found.
|
||||||
*/
|
*/
|
||||||
private Iterator createServiceFileIterator() {
|
private XPathFactory findServiceProvider(final String objectModel)
|
||||||
if (classLoader == null) {
|
throws XPathFactoryConfigurationException {
|
||||||
return new SingleIterator() {
|
|
||||||
protected Object value() {
|
assert objectModel != null;
|
||||||
ClassLoader classLoader = XPathFactoryFinder.class.getClassLoader();
|
// store current context.
|
||||||
return ss.getResourceAsURL(classLoader, SERVICE_ID);
|
final AccessControlContext acc = AccessController.getContext();
|
||||||
//return (ClassLoader.getSystemResource( SERVICE_ID ));
|
try {
|
||||||
|
return AccessController.doPrivileged(new PrivilegedAction<XPathFactory>() {
|
||||||
|
public XPathFactory run() {
|
||||||
|
final ServiceLoader<XPathFactory> loader =
|
||||||
|
ServiceLoader.load(SERVICE_CLASS);
|
||||||
|
for (XPathFactory factory : loader) {
|
||||||
|
// restore initial context to call
|
||||||
|
// factory.isObjectModelSupportedBy
|
||||||
|
if (isObjectModelSupportedBy(factory, objectModel, acc)) {
|
||||||
|
return factory;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null; // no factory found.
|
||||||
}
|
}
|
||||||
};
|
});
|
||||||
} else {
|
} catch (ServiceConfigurationError error) {
|
||||||
try {
|
throw new XPathFactoryConfigurationException(error);
|
||||||
//final Enumeration e = classLoader.getResources(SERVICE_ID);
|
|
||||||
final Enumeration e = ss.getResources(classLoader, SERVICE_ID);
|
|
||||||
if(!e.hasMoreElements()) {
|
|
||||||
debugPrintln("no "+SERVICE_ID+" file was found");
|
|
||||||
}
|
|
||||||
|
|
||||||
// wrap it into an Iterator.
|
|
||||||
return new Iterator() {
|
|
||||||
public void remove() {
|
|
||||||
throw new UnsupportedOperationException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean hasNext() {
|
|
||||||
return e.hasMoreElements();
|
|
||||||
}
|
|
||||||
|
|
||||||
public Object next() {
|
|
||||||
return e.nextElement();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
} catch (IOException e) {
|
|
||||||
debugPrintln("failed to enumerate resources "+SERVICE_ID);
|
|
||||||
if(debug) e.printStackTrace();
|
|
||||||
return new ArrayList().iterator(); // empty iterator
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Class SERVICE_CLASS = XPathFactory.class;
|
private static final Class<XPathFactory> SERVICE_CLASS = XPathFactory.class;
|
||||||
private static final String SERVICE_ID = "META-INF/services/" + SERVICE_CLASS.getName();
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
private static String which( Class clazz ) {
|
private static String which( Class clazz ) {
|
||||||
return which( clazz.getName(), clazz.getClassLoader() );
|
return which( clazz.getName(), clazz.getClassLoader() );
|
||||||
|
Loading…
Reference in New Issue
Block a user