1 /* 2 * Copyright (c) 2005, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.xml.ws.spi; 27 28 import java.io.*; 29 30 import java.nio.file.Paths; 31 import java.util.Properties; 32 import java.util.logging.Level; 33 import java.util.logging.Logger; 34 import javax.xml.ws.WebServiceException; 35 36 class FactoryFinder { 37 38 private static final Logger logger = Logger.getLogger("javax.xml.ws"); 39 40 private static final ServiceLoaderUtil.ExceptionHandler<WebServiceException> EXCEPTION_HANDLER = 41 new ServiceLoaderUtil.ExceptionHandler<WebServiceException>() { 42 @Override 43 public WebServiceException createException(Throwable throwable, String message) { 44 return new WebServiceException(message, throwable); 45 } 46 }; 47 48 /** 49 * Finds the implementation {@code Class} object for the given 50 * factory name, or if that fails, finds the {@code Class} object 51 * for the given fallback class name. The arguments supplied MUST be 52 * used in order. If using the first argument is successful, the second 53 * one will not be used. 54 * <P> 55 * This method is package private so that this code can be shared. 56 * 57 * @return the {@code Class} object of the specified message factory; 58 * may not be {@code null} 59 * 60 * @param factoryClass the name of the factory to find, which is 61 * a system property 62 * @param fallbackClassName the implementation class name, which is 63 * to be used only if nothing else 64 * is found; {@code null} to indicate that 65 * there is no fallback class name 66 * @exception WebServiceException if there is an error 67 */ 68 @SuppressWarnings("unchecked") 69 static <T> T find(Class<T> factoryClass, String fallbackClassName) { 70 ClassLoader classLoader = ServiceLoaderUtil.contextClassLoader(EXCEPTION_HANDLER); 71 72 T provider = ServiceLoaderUtil.firstByServiceLoader(factoryClass, logger, EXCEPTION_HANDLER); 73 if (provider != null) return provider; 74 75 String factoryId = factoryClass.getName(); 76 77 // try to read from $java.home/lib/jaxws.properties 78 provider = (T) fromJDKProperties(factoryId, fallbackClassName, classLoader); 79 if (provider != null) return provider; 80 81 // Use the system property 82 provider = (T) fromSystemProperty(factoryId, fallbackClassName, classLoader); 83 if (provider != null) return provider; 84 85 // handling Glassfish (platform specific default) 86 if (isOsgi()) { 87 return (T) lookupUsingOSGiServiceLoader(factoryId); 88 } 89 90 if (fallbackClassName == null) { 91 throw new WebServiceException( 92 "Provider for " + factoryId + " cannot be found", null); 93 } 94 95 return (T) ServiceLoaderUtil.newInstance(fallbackClassName, 96 fallbackClassName, classLoader, EXCEPTION_HANDLER); 97 } 98 99 private static Object fromSystemProperty(String factoryId, 100 String fallbackClassName, 101 ClassLoader classLoader) { 102 try { 103 String systemProp = System.getProperty(factoryId); 104 if (systemProp != null) { 105 return ServiceLoaderUtil.newInstance(systemProp, 106 fallbackClassName, classLoader, EXCEPTION_HANDLER); 107 } 108 } catch (SecurityException ignored) { 109 } 110 return null; 111 } 112 113 private static Object fromJDKProperties(String factoryId, 114 String fallbackClassName, 115 ClassLoader classLoader) { 116 File f = null; 117 try { 118 String JAVA_HOME = System.getProperty("java.home"); 119 f = Paths.get(JAVA_HOME, "conf", "jaxws.properties").toFile(); 120 121 // to ensure backwards compatibility 122 if (!f.exists()) { 123 f = Paths.get(JAVA_HOME, "lib", "jaxws.properties").toFile(); 124 } 125 126 if (f.exists()) { 127 Properties props = new Properties(); 128 try (InputStream inStream = new FileInputStream(f)) { 129 props.load(inStream); 130 } 131 String factoryClassName = props.getProperty(factoryId); 132 return ServiceLoaderUtil.newInstance(factoryClassName, 133 fallbackClassName, classLoader, EXCEPTION_HANDLER); 134 } 135 } catch (Exception ignored) { 136 String absolutePath = f != null ? f.getAbsolutePath() : "null"; 137 logger.log(Level.SEVERE, "Error reading JAX-WS configuration from [" + 138 absolutePath + 139 "] file. Check it is accessible and has correct format.", ignored); 140 } 141 return null; 142 } 143 144 private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; 145 146 private static boolean isOsgi() { 147 try { 148 Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); 149 return true; 150 } catch (ClassNotFoundException ignored) { 151 } 152 return false; 153 } 154 155 private static Object lookupUsingOSGiServiceLoader(String factoryId) { 156 try { 157 // Use reflection to avoid having any dependendcy on ServiceLoader class 158 Class serviceClass = Class.forName(factoryId); 159 Class[] args = new Class[]{serviceClass}; 160 Class target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); 161 java.lang.reflect.Method m = target.getMethod("lookupProviderInstances", Class.class); 162 java.util.Iterator iter = ((Iterable) m.invoke(null, (Object[]) args)).iterator(); 163 return iter.hasNext() ? iter.next() : null; 164 } catch (Exception ignored) { 165 // log and continue 166 return null; 167 } 168 } 169 170 }