< prev index next >
src/java.xml.ws/share/classes/javax/xml/soap/FactoryFinder.java
Print this page
*** 24,186 ****
*/
package javax.xml.soap;
import java.io.*;
import java.util.Properties;
class FactoryFinder {
! /**
! * Creates an instance of the specified class using the specified
! * {@code ClassLoader} object.
! *
! * @exception SOAPException if the given class could not be found
! * or could not be instantiated
! */
! private static Object newInstance(String className,
! ClassLoader classLoader)
! throws SOAPException
! {
! try {
! Class spiClass = safeLoadClass(className, classLoader);
! return spiClass.newInstance();
!
! } catch (ClassNotFoundException x) {
! throw new SOAPException("Provider " + className + " not found", x);
! } catch (Exception x) {
! throw new SOAPException("Provider " + className + " could not be instantiated: " + x, x);
! }
! }
! /**
! * Finds the implementation {@code Class} object for the given
! * factory name, or null if that fails.
! * <P>
! * This method is package private so that this code can be shared.
! *
! * @return the {@code Class} object of the specified message factory;
! * or {@code null}
! *
! * @param factoryId the name of the factory to find, which is
! * a system property
! * @exception SOAPException if there is a SOAP error
! */
! static Object find(String factoryId)
! throws SOAPException
! {
! return find(factoryId, null, false);
}
/**
* Finds the implementation {@code Class} object for the given
! * factory name, or if that fails, finds the {@code Class} object
! * for the given fallback class name. The arguments supplied must be
! * used in order. If using the first argument is successful, the second
! * one will not be used.
! * <P>
! * This method is package private so that this code can be shared.
! *
! * @return the {@code Class} object of the specified message factory;
! * may be {@code null}
! *
! * @param factoryId the name of the factory to find, which is
! * a system property
! * @param fallbackClassName the implementation class name, which is
! * to be used only if nothing else
! * is found; {@code null} to indicate that
! * there is no fallback class name
! * @exception SOAPException if there is a SOAP error
! */
! static Object find(String factoryId, String fallbackClassName)
! throws SOAPException
! {
! return find(factoryId, fallbackClassName, true);
! }
!
! /**
! * Finds the implementation {@code Class} object for the given
! * factory name, or if that fails, finds the {@code Class} object
! * for the given default class name, but only if {@code tryFallback}
! * is {@code true}. The arguments supplied must be used in order
! * If using the first argument is successful, the second one will not
! * be used. Note the default class name may be needed even if fallback
! * is not to be attempted, so certain error conditions can be handled.
* <P>
* This method is package private so that this code can be shared.
*
* @return the {@code Class} object of the specified message factory;
* may not be {@code null}
*
! * @param factoryId the name of the factory to find, which is
! * a system property
* @param defaultClassName the implementation class name, which is
* to be used only if nothing else
* is found; {@code null} to indicate
* that there is no default class name
* @param tryFallback whether to try the default class as a
* fallback
* @exception SOAPException if there is a SOAP error
*/
! static Object find(String factoryId, String defaultClassName,
! boolean tryFallback) throws SOAPException {
! ClassLoader classLoader;
! try {
! classLoader = Thread.currentThread().getContextClassLoader();
! } catch (Exception x) {
! throw new SOAPException(x.toString(), x);
! }
// Use the system property first
! try {
! String systemProp =
! System.getProperty( factoryId );
! if( systemProp!=null) {
! return newInstance(systemProp, classLoader);
}
- } catch (SecurityException se) {
}
// try to read from $java.home/lib/jaxm.properties
! try {
! String javah=System.getProperty( "java.home" );
! String configFile = javah + File.separator +
! "lib" + File.separator + "jaxm.properties";
! File f=new File( configFile );
! if( f.exists()) {
! Properties props=new Properties();
! props.load( new FileInputStream(f));
! String factoryClassName = props.getProperty(factoryId);
! return newInstance(factoryClassName, classLoader);
}
- } catch(Exception ex ) {
}
! String serviceId = "META-INF/services/" + factoryId;
! // try to find services in CLASSPATH
! try {
! InputStream is=null;
! if (classLoader == null) {
! is=ClassLoader.getSystemResourceAsStream(serviceId);
! } else {
! is=classLoader.getResourceAsStream(serviceId);
}
! if( is!=null ) {
! BufferedReader rd =
! new BufferedReader(new InputStreamReader(is, "UTF-8"));
!
! String factoryClassName = rd.readLine();
! rd.close();
!
! if (factoryClassName != null &&
! ! "".equals(factoryClassName)) {
! return newInstance(factoryClassName, classLoader);
! }
}
- } catch( Exception ex ) {
}
// If not found and fallback should not be tried, return a null result.
if (!tryFallback)
return null;
--- 24,127 ----
*/
package javax.xml.soap;
import java.io.*;
+ import java.nio.charset.StandardCharsets;
+ import java.nio.file.Files;
+ import java.nio.file.Path;
+ import java.nio.file.Paths;
+ import java.security.AccessController;
+ import java.security.PrivilegedAction;
import java.util.Properties;
+ import java.util.logging.Level;
+ import java.util.logging.Logger;
class FactoryFinder {
! private static final Logger logger = Logger.getLogger("javax.xml.soap");
! private static final ServiceLoaderUtil.ExceptionHandler<SOAPException> EXCEPTION_HANDLER =
! new ServiceLoaderUtil.ExceptionHandler<SOAPException>() {
! @Override
! public SOAPException createException(Throwable throwable, String message) {
! return new SOAPException(message, throwable);
}
+ };
/**
* Finds the implementation {@code Class} object for the given
! * factory type. If it fails and {@code tryFallback} is {@code true}
! * finds the {@code Class} object for the given default class name.
! * The arguments supplied must be used in order
! * Note the default class name may be needed even if fallback
! * is not to be attempted in order to check if requested type is fallback.
* <P>
* This method is package private so that this code can be shared.
*
* @return the {@code Class} object of the specified message factory;
* may not be {@code null}
*
! * @param factoryClass factory abstract class or interface to be found
! * @param deprecatedFactoryId deprecated name of a factory; it is used for types
! * where class name is different from a name
! * being searched (in previous spec).
* @param defaultClassName the implementation class name, which is
* to be used only if nothing else
* is found; {@code null} to indicate
* that there is no default class name
* @param tryFallback whether to try the default class as a
* fallback
* @exception SOAPException if there is a SOAP error
*/
! @SuppressWarnings("unchecked")
! static <T> T find(Class<T> factoryClass,
! String defaultClassName,
! boolean tryFallback, String deprecatedFactoryId) throws SOAPException {
!
! ClassLoader tccl = ServiceLoaderUtil.contextClassLoader(EXCEPTION_HANDLER);
! String factoryId = factoryClass.getName();
// Use the system property first
! String className = fromSystemProperty(factoryId, deprecatedFactoryId);
! if (className != null) {
! Object result = newInstance(className, defaultClassName, tccl);
! if (result != null) {
! return (T) result;
}
}
// try to read from $java.home/lib/jaxm.properties
! className = fromJDKProperties(factoryId, deprecatedFactoryId);
! if (className != null) {
! Object result = newInstance(className, defaultClassName, tccl);
! if (result != null) {
! return (T) result;
}
}
! // standard services: java.util.ServiceLoader
! T factory = ServiceLoaderUtil.firstByServiceLoader(
! factoryClass,
! logger,
! EXCEPTION_HANDLER);
! if (factory != null) {
! return factory;
}
! // try to find services in CLASSPATH
! className = fromMetaInfServices(deprecatedFactoryId, tccl);
! if (className != null) {
! logger.log(Level.WARNING,
! "Using deprecated META-INF/services mechanism with non-standard property: {0}. " +
! "Property {1} should be used instead.",
! new Object[]{deprecatedFactoryId, factoryId});
! Object result = newInstance(className, defaultClassName, tccl);
! if (result != null) {
! return (T) result;
}
}
// If not found and fallback should not be tried, return a null result.
if (!tryFallback)
return null;
*** 189,236 ****
// (built in) factory if specified.
if (defaultClassName == null) {
throw new SOAPException(
"Provider for " + factoryId + " cannot be found", null);
}
! return newInstance(defaultClassName, classLoader);
}
! /**
! * Loads the class, provided that the calling thread has an access to the
! * class being loaded. If this is the specified default factory class and it
! * is restricted by package.access we get a SecurityException and can do a
! * Class.forName() on it so it will be loaded by the bootstrap class loader.
! */
! private static Class safeLoadClass(String className,
! ClassLoader classLoader)
! throws ClassNotFoundException {
try {
! // make sure that the current thread has an access to the package of the given name.
! SecurityManager s = System.getSecurityManager();
! if (s != null) {
! int i = className.lastIndexOf('.');
! if (i != -1) {
! s.checkPackageAccess(className.substring(0, i));
}
}
! if (classLoader == null)
! return Class.forName(className);
! else
! return classLoader.loadClass(className);
! } catch (SecurityException se) {
! // (only) default implementation can be loaded
! // using bootstrap class loader:
! if (isDefaultImplementation(className))
! return Class.forName(className);
!
! throw se;
}
}
! private static boolean isDefaultImplementation(String className) {
! return MessageFactory.DEFAULT_MESSAGE_FACTORY.equals(className) ||
! SOAPFactory.DEFAULT_SOAP_FACTORY.equals(className) ||
! SOAPConnectionFactory.DEFAULT_SOAP_CONNECTION_FACTORY.equals(className) ||
! SAAJMetaFactory.DEFAULT_META_FACTORY_CLASS.equals(className);
}
}
--- 130,264 ----
// (built in) factory if specified.
if (defaultClassName == null) {
throw new SOAPException(
"Provider for " + factoryId + " cannot be found", null);
}
! return (T) newInstance(defaultClassName, defaultClassName, tccl);
}
! // in most cases there is no deprecated factory id
! static <T> T find(Class<T> factoryClass,
! String defaultClassName,
! boolean tryFallback) throws SOAPException {
! return find(factoryClass, defaultClassName, tryFallback, null);
! }
!
! private static Object newInstance(String className, String defaultClassName, ClassLoader tccl) throws SOAPException {
! return ServiceLoaderUtil.newInstance(
! className,
! defaultClassName,
! tccl,
! EXCEPTION_HANDLER);
! }
!
! // used only for deprecatedFactoryId;
! // proper factoryId searched by java.util.ServiceLoader
! private static String fromMetaInfServices(String deprecatedFactoryId, ClassLoader tccl) {
! String serviceId = "META-INF/services/" + deprecatedFactoryId;
! logger.log(Level.FINE, "Checking deprecated {0} resource", serviceId);
!
! try (InputStream is =
! tccl == null ?
! ClassLoader.getSystemResourceAsStream(serviceId)
! :
! tccl.getResourceAsStream(serviceId)) {
!
! if (is != null) {
! String factoryClassName;
! try (InputStreamReader isr = new InputStreamReader(is, StandardCharsets.UTF_8);
! BufferedReader rd = new BufferedReader(isr)) {
! factoryClassName = rd.readLine();
! }
!
! logFound(factoryClassName);
! if (factoryClassName != null && !"".equals(factoryClassName)) {
! return factoryClassName;
! }
! }
!
! } catch (IOException e) {
! // keep original behavior
! }
! return null;
! }
!
! private static String fromJDKProperties(String factoryId, String deprecatedFactoryId) {
! Path path = null;
try {
! String JAVA_HOME = System.getProperty("java.home");
! path = Paths.get(JAVA_HOME, "conf", "jaxm.properties");
! logger.log(Level.FINE, "Checking configuration in {0}", path);
!
! // to ensure backwards compatibility
! if (!Files.exists(path)) {
! path = Paths.get(JAVA_HOME, "lib", "jaxm.properties");
}
+
+ logger.log(Level.FINE, "Checking configuration in {0}", path);
+ if (Files.exists(path)) {
+ Properties props = new Properties();
+ try (InputStream inputStream = Files.newInputStream(path)) {
+ props.load(inputStream);
}
! // standard property
! logger.log(Level.FINE, "Checking property {0}", factoryId);
! String factoryClassName = props.getProperty(factoryId);
! logFound(factoryClassName);
! if (factoryClassName != null) {
! return factoryClassName;
! }
!
! // deprecated property
! if (deprecatedFactoryId != null) {
! logger.log(Level.FINE, "Checking deprecated property {0}", deprecatedFactoryId);
! factoryClassName = props.getProperty(deprecatedFactoryId);
! logFound(factoryClassName);
! if (factoryClassName != null) {
! logger.log(Level.WARNING,
! "Using non-standard property: {0}. Property {1} should be used instead.",
! new Object[]{deprecatedFactoryId, factoryId});
! return factoryClassName;
}
}
+ }
+ } catch (Exception ignored) {
+ logger.log(Level.SEVERE, "Error reading SAAJ configuration from [" + path +
+ "] file. Check it is accessible and has correct format.", ignored);
+ }
+ return null;
+ }
! private static String fromSystemProperty(String factoryId, String deprecatedFactoryId) {
! String systemProp = getSystemProperty(factoryId);
! if (systemProp != null) {
! return systemProp;
! }
! if (deprecatedFactoryId != null) {
! systemProp = getSystemProperty(deprecatedFactoryId);
! if (systemProp != null) {
! logger.log(Level.WARNING,
! "Using non-standard property: {0}. Property {1} should be used instead.",
! new Object[] {deprecatedFactoryId, factoryId});
! return systemProp;
! }
}
+ return null;
+ }
+
+ private static String getSystemProperty(String property) {
+ logger.log(Level.FINE, "Checking system property {0}", property);
+ String value = AccessController.doPrivileged(
+ (PrivilegedAction<String>) () -> System.getProperty(property));
+ logFound(value);
+ return value;
+ }
+
+ private static void logFound(String value) {
+ if (value != null) {
+ logger.log(Level.FINE, " found {0}", value);
+ } else {
+ logger.log(Level.FINE, " not found");
+ }
+ }
+
}
< prev index next >