aoqi@0: /* aoqi@0: * Copyright (c) 2004, 2013, Oracle and/or its affiliates. All rights reserved. aoqi@0: * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. aoqi@0: * aoqi@0: * This code is free software; you can redistribute it and/or modify it aoqi@0: * under the terms of the GNU General Public License version 2 only, as aoqi@0: * published by the Free Software Foundation. Oracle designates this aoqi@0: * particular file as subject to the "Classpath" exception as provided aoqi@0: * by Oracle in the LICENSE file that accompanied this code. aoqi@0: * aoqi@0: * This code is distributed in the hope that it will be useful, but WITHOUT aoqi@0: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or aoqi@0: * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License aoqi@0: * version 2 for more details (a copy is included in the LICENSE file that aoqi@0: * accompanied this code). aoqi@0: * aoqi@0: * You should have received a copy of the GNU General Public License version aoqi@0: * 2 along with this work; if not, write to the Free Software Foundation, aoqi@0: * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. aoqi@0: * aoqi@0: * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA aoqi@0: * or visit www.oracle.com if you need additional information or have any aoqi@0: * questions. aoqi@0: */ aoqi@0: aoqi@0: package javax.xml.soap; aoqi@0: aoqi@0: import java.io.*; aoqi@0: import java.util.Properties; aoqi@0: aoqi@0: aoqi@0: class FactoryFinder { aoqi@0: aoqi@0: /** aoqi@0: * Creates an instance of the specified class using the specified aoqi@0: * ClassLoader object. aoqi@0: * aoqi@0: * @exception SOAPException if the given class could not be found aoqi@0: * or could not be instantiated aoqi@0: */ aoqi@0: private static Object newInstance(String className, aoqi@0: ClassLoader classLoader) aoqi@0: throws SOAPException aoqi@0: { aoqi@0: try { aoqi@0: Class spiClass = safeLoadClass(className, classLoader); aoqi@0: return spiClass.newInstance(); aoqi@0: aoqi@0: } catch (ClassNotFoundException x) { aoqi@0: throw new SOAPException("Provider " + className + " not found", x); aoqi@0: } catch (Exception x) { aoqi@0: throw new SOAPException("Provider " + className + " could not be instantiated: " + x, x); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Finds the implementation Class object for the given aoqi@0: * factory name, or null if that fails. aoqi@0: *

aoqi@0: * This method is package private so that this code can be shared. aoqi@0: * aoqi@0: * @return the Class object of the specified message factory; aoqi@0: * or null aoqi@0: * aoqi@0: * @param factoryId the name of the factory to find, which is aoqi@0: * a system property aoqi@0: * @exception SOAPException if there is a SOAP error aoqi@0: */ aoqi@0: static Object find(String factoryId) aoqi@0: throws SOAPException aoqi@0: { aoqi@0: return find(factoryId, null, false); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Finds the implementation Class object for the given aoqi@0: * factory name, or if that fails, finds the Class object aoqi@0: * for the given fallback class name. The arguments supplied must be aoqi@0: * used in order. If using the first argument is successful, the second aoqi@0: * one will not be used. aoqi@0: *

aoqi@0: * This method is package private so that this code can be shared. aoqi@0: * aoqi@0: * @return the Class object of the specified message factory; aoqi@0: * may be null aoqi@0: * aoqi@0: * @param factoryId the name of the factory to find, which is aoqi@0: * a system property aoqi@0: * @param fallbackClassName the implementation class name, which is aoqi@0: * to be used only if nothing else aoqi@0: * is found; null to indicate that aoqi@0: * there is no fallback class name aoqi@0: * @exception SOAPException if there is a SOAP error aoqi@0: */ aoqi@0: static Object find(String factoryId, String fallbackClassName) aoqi@0: throws SOAPException aoqi@0: { aoqi@0: return find(factoryId, fallbackClassName, true); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Finds the implementation Class object for the given aoqi@0: * factory name, or if that fails, finds the Class object aoqi@0: * for the given default class name, but only if tryFallback aoqi@0: * is true. The arguments supplied must be used in order aoqi@0: * If using the first argument is successful, the second one will not aoqi@0: * be used. Note the default class name may be needed even if fallback aoqi@0: * is not to be attempted, so certain error conditions can be handled. aoqi@0: *

aoqi@0: * This method is package private so that this code can be shared. aoqi@0: * aoqi@0: * @return the Class object of the specified message factory; aoqi@0: * may not be null aoqi@0: * aoqi@0: * @param factoryId the name of the factory to find, which is aoqi@0: * a system property aoqi@0: * @param defaultClassName the implementation class name, which is aoqi@0: * to be used only if nothing else aoqi@0: * is found; null to indicate aoqi@0: * that there is no default class name aoqi@0: * @param tryFallback whether to try the default class as a aoqi@0: * fallback aoqi@0: * @exception SOAPException if there is a SOAP error aoqi@0: */ aoqi@0: static Object find(String factoryId, String defaultClassName, aoqi@0: boolean tryFallback) throws SOAPException { aoqi@0: ClassLoader classLoader; aoqi@0: try { aoqi@0: classLoader = Thread.currentThread().getContextClassLoader(); aoqi@0: } catch (Exception x) { aoqi@0: throw new SOAPException(x.toString(), x); aoqi@0: } aoqi@0: aoqi@0: // Use the system property first aoqi@0: try { aoqi@0: String systemProp = aoqi@0: System.getProperty( factoryId ); aoqi@0: if( systemProp!=null) { aoqi@0: return newInstance(systemProp, classLoader); aoqi@0: } aoqi@0: } catch (SecurityException se) { aoqi@0: } aoqi@0: aoqi@0: // try to read from $java.home/lib/jaxm.properties aoqi@0: try { aoqi@0: String javah=System.getProperty( "java.home" ); aoqi@0: String configFile = javah + File.separator + aoqi@0: "lib" + File.separator + "jaxm.properties"; aoqi@0: File f=new File( configFile ); aoqi@0: if( f.exists()) { aoqi@0: Properties props=new Properties(); aoqi@0: props.load( new FileInputStream(f)); aoqi@0: String factoryClassName = props.getProperty(factoryId); aoqi@0: return newInstance(factoryClassName, classLoader); aoqi@0: } aoqi@0: } catch(Exception ex ) { aoqi@0: } aoqi@0: aoqi@0: String serviceId = "META-INF/services/" + factoryId; aoqi@0: // try to find services in CLASSPATH aoqi@0: try { aoqi@0: InputStream is=null; aoqi@0: if (classLoader == null) { aoqi@0: is=ClassLoader.getSystemResourceAsStream(serviceId); aoqi@0: } else { aoqi@0: is=classLoader.getResourceAsStream(serviceId); aoqi@0: } aoqi@0: aoqi@0: if( is!=null ) { aoqi@0: BufferedReader rd = aoqi@0: new BufferedReader(new InputStreamReader(is, "UTF-8")); aoqi@0: aoqi@0: String factoryClassName = rd.readLine(); aoqi@0: rd.close(); aoqi@0: aoqi@0: if (factoryClassName != null && aoqi@0: ! "".equals(factoryClassName)) { aoqi@0: return newInstance(factoryClassName, classLoader); aoqi@0: } aoqi@0: } aoqi@0: } catch( Exception ex ) { aoqi@0: } aoqi@0: aoqi@0: // If not found and fallback should not be tried, return a null result. aoqi@0: if (!tryFallback) aoqi@0: return null; aoqi@0: aoqi@0: // We didn't find the class through the usual means so try the default aoqi@0: // (built in) factory if specified. aoqi@0: if (defaultClassName == null) { aoqi@0: throw new SOAPException( aoqi@0: "Provider for " + factoryId + " cannot be found", null); aoqi@0: } aoqi@0: return newInstance(defaultClassName, classLoader); aoqi@0: } aoqi@0: aoqi@0: /** aoqi@0: * Loads the class, provided that the calling thread has an access to the aoqi@0: * class being loaded. If this is the specified default factory class and it aoqi@0: * is restricted by package.access we get a SecurityException and can do a aoqi@0: * Class.forName() on it so it will be loaded by the bootstrap class loader. aoqi@0: */ aoqi@0: private static Class safeLoadClass(String className, aoqi@0: ClassLoader classLoader) aoqi@0: throws ClassNotFoundException { aoqi@0: try { aoqi@0: // make sure that the current thread has an access to the package of the given name. aoqi@0: SecurityManager s = System.getSecurityManager(); aoqi@0: if (s != null) { aoqi@0: int i = className.lastIndexOf('.'); aoqi@0: if (i != -1) { aoqi@0: s.checkPackageAccess(className.substring(0, i)); aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: if (classLoader == null) aoqi@0: return Class.forName(className); aoqi@0: else aoqi@0: return classLoader.loadClass(className); aoqi@0: } catch (SecurityException se) { aoqi@0: // (only) default implementation can be loaded aoqi@0: // using bootstrap class loader: aoqi@0: if (isDefaultImplementation(className)) aoqi@0: return Class.forName(className); aoqi@0: aoqi@0: throw se; aoqi@0: } aoqi@0: } aoqi@0: aoqi@0: private static boolean isDefaultImplementation(String className) { aoqi@0: return MessageFactory.DEFAULT_MESSAGE_FACTORY.equals(className) || aoqi@0: SOAPFactory.DEFAULT_SOAP_FACTORY.equals(className) || aoqi@0: SOAPConnectionFactory.DEFAULT_SOAP_CONNECTION_FACTORY.equals(className) || aoqi@0: SAAJMetaFactory.DEFAULT_META_FACTORY_CLASS.equals(className); aoqi@0: } aoqi@0: }