jaxws/src/java.xml.bind/share/classes/javax/xml/bind/ServiceLoaderUtil.java
changeset 29839 6d5d546e953b
child 31109 a542f8dcbbf8
equal deleted inserted replaced
29838:fe5fd9871a13 29839:6d5d546e953b
       
     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 }