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.Files; 31 import java.nio.file.Path; 32 import java.nio.file.Paths; 33 import java.util.Properties; 34 import java.util.logging.Level; 35 import java.util.logging.Logger; 36 import javax.xml.ws.WebServiceException; 37 38 class FactoryFinder { 39 40 private static final Logger logger = Logger.getLogger("javax.xml.ws"); 41 42 private static final ServiceLoaderUtil.ExceptionHandler<WebServiceException> EXCEPTION_HANDLER = 43 new ServiceLoaderUtil.ExceptionHandler<WebServiceException>() { 44 @Override 45 public WebServiceException createException(Throwable throwable, String message) { 46 return new WebServiceException(message, throwable); 47 } 48 }; 49 50 /** 51 * Finds the implementation {@code Class} object for the given 52 * factory name, or if that fails, finds the {@code Class} object 53 * for the given fallback class name. The arguments supplied MUST be 54 * used in order. If using the first argument is successful, the second 55 * one will not be used. 56 * <P> 57 * This method is package private so that this code can be shared. 58 * 59 * @return the {@code Class} object of the specified message factory; 60 * may not be {@code null} 61 * 62 * @param factoryClass the name of the factory to find, which is 63 * a system property 64 * @param fallbackClassName the implementation class name, which is 65 * to be used only if nothing else 66 * is found; {@code null} to indicate that 67 * there is no fallback class name 68 * @exception WebServiceException if there is an error 69 */ 70 @SuppressWarnings("unchecked") 71 static <T> T find(Class<T> factoryClass, String fallbackClassName) { 72 ClassLoader classLoader = ServiceLoaderUtil.contextClassLoader(EXCEPTION_HANDLER); 73 74 T provider = ServiceLoaderUtil.firstByServiceLoader(factoryClass, logger, EXCEPTION_HANDLER); 75 if (provider != null) return provider; 76 77 String factoryId = factoryClass.getName(); 78 79 // try to read from $java.home/lib/jaxws.properties 80 provider = (T) fromJDKProperties(factoryId, fallbackClassName, classLoader); 81 if (provider != null) return provider; 82 83 // Use the system property 84 provider = (T) fromSystemProperty(factoryId, fallbackClassName, classLoader); 85 if (provider != null) return provider; 86 87 // handling Glassfish (platform specific default) 88 if (isOsgi()) { 89 return (T) lookupUsingOSGiServiceLoader(factoryId); 90 } 91 92 if (fallbackClassName == null) { 93 throw new WebServiceException( 94 "Provider for " + factoryId + " cannot be found", null); 95 } 96 97 return (T) ServiceLoaderUtil.newInstance(fallbackClassName, 98 fallbackClassName, classLoader, EXCEPTION_HANDLER); 99 } 100 101 private static Object fromSystemProperty(String factoryId, 102 String fallbackClassName, 103 ClassLoader classLoader) { 104 try { 105 String systemProp = System.getProperty(factoryId); 106 if (systemProp != null) { 107 return ServiceLoaderUtil.newInstance(systemProp, 108 fallbackClassName, classLoader, EXCEPTION_HANDLER); 109 } 110 } catch (SecurityException ignored) { 111 } 112 return null; 113 } 114 115 private static Object fromJDKProperties(String factoryId, 116 String fallbackClassName, 117 ClassLoader classLoader) { 118 Path path = null; 119 try { 120 String JAVA_HOME = System.getProperty("java.home"); 121 path = Paths.get(JAVA_HOME, "conf", "jaxws.properties"); 122 123 // to ensure backwards compatibility 124 if (!Files.exists(path)) { 125 path = Paths.get(JAVA_HOME, "lib", "jaxws.properties"); 126 } 127 128 if (!Files.exists(path)) { 129 Properties props = new Properties(); 130 try (InputStream inStream = Files.newInputStream(path)) { 131 props.load(inStream); 132 } 133 String factoryClassName = props.getProperty(factoryId); 134 return ServiceLoaderUtil.newInstance(factoryClassName, 135 fallbackClassName, classLoader, EXCEPTION_HANDLER); 136 } 137 } catch (Exception ignored) { 138 logger.log(Level.SEVERE, "Error reading JAX-WS configuration from [" + path + 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 }