1 /* 2 * Copyright (c) 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.bind; 27 28 import java.io.File; 29 import java.io.FileInputStream; 30 import java.io.IOException; 31 import java.lang.reflect.Method; 32 import java.security.AccessController; 33 import java.security.PrivilegedAction; 34 import java.util.Iterator; 35 import java.util.Properties; 36 import java.util.ServiceLoader; 37 import java.util.logging.Level; 38 import java.util.logging.Logger; 39 40 /** 41 * Shared ServiceLoader/FactoryFinder Utils shared among SAAJ, JAXB and JAXWS 42 * - this class must be duplicated to all those projects, but it's 43 * basically generic code and we want to have it everywhere same. 44 * 45 * @author Miroslav.Kos@oracle.com 46 */ 47 class ServiceLoaderUtil { 48 49 private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; 50 private static final String OSGI_SERVICE_LOADER_METHOD_NAME = "lookupProviderClasses"; 51 52 static <P> P firstByServiceLoader(Class<P> spiClass, Logger logger) { 53 // service discovery 54 ServiceLoader<P> serviceLoader = ServiceLoader.load(spiClass); 55 for (P impl : serviceLoader) { 56 logger.fine("ServiceProvider loading Facility used; returning object [" + impl.getClass().getName() + "]"); 57 return impl; 58 } 59 return null; 60 } 61 62 static boolean isOsgi(Logger logger) { 63 try { 64 Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); 65 return true; 66 } catch (ClassNotFoundException ignored) { 67 logger.log(Level.FINE, "OSGi classes not found, OSGi not available.", ignored); 68 } 69 return false; 70 } 71 72 static Object lookupUsingOSGiServiceLoader(String factoryId, Logger logger) { 73 try { 74 // Use reflection to avoid having any dependendcy on ServiceLoader class 75 Class serviceClass = Class.forName(factoryId); 76 Class target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); 77 Method m = target.getMethod(OSGI_SERVICE_LOADER_METHOD_NAME, Class.class); 78 Iterator iter = ((Iterable) m.invoke(null, serviceClass)).iterator(); 79 if (iter.hasNext()) { 80 Object next = iter.next(); 81 logger.fine("Found implementation using OSGi facility; returning object [" + next.getClass().getName() + "]."); 82 return next; 83 } else { 84 return null; 85 } 86 } catch (Exception ignored) { 87 logger.log(Level.FINE, "Unable to find from OSGi: [" + factoryId + "]", ignored); 88 return null; 89 } 90 } 91 92 static String propertyFileLookup(final String configFullPath, final String factoryId) throws IOException { 93 File f = new File(configFullPath); 94 String factoryClassName = null; 95 if (f.exists()) { 96 Properties props = new Properties(); 97 FileInputStream stream = null; 98 try { 99 stream = new FileInputStream(f); 100 props.load(stream); 101 factoryClassName = props.getProperty(factoryId); 102 } finally { 103 if (stream != null) { 104 try { 105 stream.close(); 106 } catch (IOException ignored) { 107 } 108 } 109 } 110 } 111 return factoryClassName; 112 } 113 114 static void checkPackageAccess(String className) { 115 // make sure that the current thread has an access to the package of the given name. 116 SecurityManager s = System.getSecurityManager(); 117 if (s != null) { 118 int i = className.lastIndexOf('.'); 119 if (i != -1) { 120 s.checkPackageAccess(className.substring(0, i)); 121 } 122 } 123 } 124 125 static Class nullSafeLoadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { 126 if (classLoader == null) { 127 return Class.forName(className); 128 } else { 129 return classLoader.loadClass(className); 130 } 131 } 132 133 /** 134 * Returns instance of required class. It checks package access (security) unless it is defaultClassname. It means if you 135 * are trying to instantiate default implementation (fallback), pass the class name to both first and second parameter. 136 * 137 * @param className class to be instantiated 138 * @param isDefaultClassname says whether default implementation class 139 * @param handler exception handler - necessary for wrapping exceptions and logging 140 * @param <T> Type of exception being thrown (necessary to distinguish between Runtime and checked exceptions) 141 * @return instantiated object or throws Runtime/checked exception, depending on ExceptionHandler's type 142 * @throws T 143 */ 144 static <T extends Exception> Object newInstance(String className, String defaultImplClassName, final ExceptionHandler<T> handler) throws T { 145 try { 146 return safeLoadClass(className, defaultImplClassName, contextClassLoader(handler)).newInstance(); 147 } catch (ClassNotFoundException x) { 148 throw handler.createException(x, "Provider " + className + " not found"); 149 } catch (Exception x) { 150 throw handler.createException(x, "Provider " + className + " could not be instantiated: " + x); 151 } 152 } 153 154 static Class safeLoadClass(String className, String defaultImplClassName, ClassLoader classLoader) throws ClassNotFoundException { 155 try { 156 checkPackageAccess(className); 157 } catch (SecurityException se) { 158 // anyone can access the platform default factory class without permission 159 if (defaultImplClassName != null && defaultImplClassName.equals(className)) { 160 return Class.forName(className); 161 } 162 // not platform default implementation ... 163 throw se; 164 } 165 return nullSafeLoadClass(className, classLoader); 166 } 167 168 static String getJavaHomeLibConfigPath(String filename) { 169 String javah = AccessController.doPrivileged(new PrivilegedAction<String>() { 170 @Override 171 public String run() { 172 return System.getProperty("java.home"); 173 } 174 }); 175 return javah + File.separator + "lib" + File.separator + filename; 176 } 177 178 static ClassLoader contextClassLoader(ExceptionHandler exceptionHandler) throws Exception { 179 try { 180 return Thread.currentThread().getContextClassLoader(); 181 } catch (Exception x) { 182 throw exceptionHandler.createException(x, x.toString()); 183 } 184 } 185 186 static abstract class ExceptionHandler<T extends Exception> { 187 188 public abstract T createException(Throwable throwable, String message); 189 190 } 191 192 }