23 * questions. |
23 * questions. |
24 */ |
24 */ |
25 |
25 |
26 package javax.xml.bind; |
26 package javax.xml.bind; |
27 |
27 |
28 import java.io.File; |
28 import java.lang.reflect.InvocationTargetException; |
29 import java.io.FileInputStream; |
|
30 import java.io.IOException; |
|
31 import java.lang.reflect.Method; |
29 import java.lang.reflect.Method; |
32 import java.security.AccessController; |
|
33 import java.security.PrivilegedAction; |
|
34 import java.util.Iterator; |
30 import java.util.Iterator; |
35 import java.util.Properties; |
|
36 import java.util.ServiceLoader; |
31 import java.util.ServiceLoader; |
37 import java.util.logging.Level; |
32 import java.util.logging.Level; |
38 import java.util.logging.Logger; |
33 import java.util.logging.Logger; |
39 |
34 |
40 /** |
35 /** |
47 class ServiceLoaderUtil { |
42 class ServiceLoaderUtil { |
48 |
43 |
49 private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "com.sun.org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; |
44 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"; |
45 private static final String OSGI_SERVICE_LOADER_METHOD_NAME = "lookupProviderClasses"; |
51 |
46 |
52 static <P> P firstByServiceLoader(Class<P> spiClass, Logger logger) { |
47 static <P, T extends Exception> P firstByServiceLoader(Class<P> spiClass, |
|
48 Logger logger, |
|
49 ExceptionHandler<T> handler) throws T { |
53 // service discovery |
50 // service discovery |
54 ServiceLoader<P> serviceLoader = ServiceLoader.load(spiClass); |
51 try { |
55 for (P impl : serviceLoader) { |
52 ServiceLoader<P> serviceLoader = ServiceLoader.load(spiClass); |
56 logger.fine("ServiceProvider loading Facility used; returning object [" + impl.getClass().getName() + "]"); |
53 |
57 return impl; |
54 for (P impl : serviceLoader) { |
|
55 logger.fine("ServiceProvider loading Facility used; returning object [" + |
|
56 impl.getClass().getName() + "]"); |
|
57 |
|
58 return impl; |
|
59 } |
|
60 } catch (Throwable t) { |
|
61 throw handler.createException(t, "Error while searching for service [" + spiClass.getName() + "]"); |
58 } |
62 } |
59 return null; |
63 return null; |
60 } |
64 } |
61 |
65 |
62 static boolean isOsgi(Logger logger) { |
66 static Object lookupUsingOSGiServiceLoader(String factoryId, 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 |
67 |
72 static Object lookupUsingOSGiServiceLoader(String factoryId, Logger logger) { |
|
73 try { |
68 try { |
74 // Use reflection to avoid having any dependendcy on ServiceLoader class |
69 // Use reflection to avoid having any dependendcy on ServiceLoader class |
75 Class serviceClass = Class.forName(factoryId); |
70 Class serviceClass = Class.forName(factoryId); |
76 Class target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); |
71 Class target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); |
77 Method m = target.getMethod(OSGI_SERVICE_LOADER_METHOD_NAME, Class.class); |
72 Method m = target.getMethod(OSGI_SERVICE_LOADER_METHOD_NAME, Class.class); |
78 Iterator iter = ((Iterable) m.invoke(null, serviceClass)).iterator(); |
73 Iterator iter = ((Iterable) m.invoke(null, serviceClass)).iterator(); |
79 if (iter.hasNext()) { |
74 if (iter.hasNext()) { |
80 Object next = iter.next(); |
75 Object next = iter.next(); |
81 logger.fine("Found implementation using OSGi facility; returning object [" + next.getClass().getName() + "]."); |
76 logger.fine("Found implementation using OSGi facility; returning object [" + |
|
77 next.getClass().getName() + "]."); |
82 return next; |
78 return next; |
83 } else { |
79 } else { |
84 return null; |
80 return null; |
85 } |
81 } |
86 } catch (Exception ignored) { |
82 } catch (IllegalAccessException | |
|
83 InvocationTargetException | |
|
84 ClassNotFoundException | |
|
85 NoSuchMethodException ignored) { |
|
86 |
87 logger.log(Level.FINE, "Unable to find from OSGi: [" + factoryId + "]", ignored); |
87 logger.log(Level.FINE, "Unable to find from OSGi: [" + factoryId + "]", ignored); |
88 return null; |
88 return null; |
89 } |
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 } |
90 } |
113 |
91 |
114 static void checkPackageAccess(String className) { |
92 static void checkPackageAccess(String className) { |
115 // make sure that the current thread has an access to the package of the given name. |
93 // make sure that the current thread has an access to the package of the given name. |
116 SecurityManager s = System.getSecurityManager(); |
94 SecurityManager s = System.getSecurityManager(); |
128 } else { |
106 } else { |
129 return classLoader.loadClass(className); |
107 return classLoader.loadClass(className); |
130 } |
108 } |
131 } |
109 } |
132 |
110 |
133 /** |
111 // Returns instance of required class. It checks package access (security) |
134 * Returns instance of required class. It checks package access (security) unless it is defaultClassname. It means if you |
112 // unless it is defaultClassname. It means if you are trying to instantiate |
135 * are trying to instantiate default implementation (fallback), pass the class name to both first and second parameter. |
113 // default implementation (fallback), pass the class name to both first and second parameter. |
136 * |
114 static <T extends Exception> Object newInstance(String className, |
137 * @param className class to be instantiated |
115 String defaultImplClassName, |
138 * @param isDefaultClassname says whether default implementation class |
116 final ExceptionHandler<T> handler) throws T { |
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 { |
117 try { |
146 return safeLoadClass(className, defaultImplClassName, contextClassLoader(handler)).newInstance(); |
118 return safeLoadClass(className, defaultImplClassName, contextClassLoader(handler)).newInstance(); |
147 } catch (ClassNotFoundException x) { |
119 } catch (ClassNotFoundException x) { |
148 throw handler.createException(x, "Provider " + className + " not found"); |
120 throw handler.createException(x, "Provider " + className + " not found"); |
149 } catch (Exception x) { |
121 } catch (Exception x) { |
150 throw handler.createException(x, "Provider " + className + " could not be instantiated: " + x); |
122 throw handler.createException(x, "Provider " + className + " could not be instantiated: " + x); |
151 } |
123 } |
152 } |
124 } |
153 |
125 |
154 static Class safeLoadClass(String className, String defaultImplClassName, ClassLoader classLoader) throws ClassNotFoundException { |
126 static Class safeLoadClass(String className, |
|
127 String defaultImplClassName, |
|
128 ClassLoader classLoader) throws ClassNotFoundException { |
|
129 |
155 try { |
130 try { |
156 checkPackageAccess(className); |
131 checkPackageAccess(className); |
157 } catch (SecurityException se) { |
132 } catch (SecurityException se) { |
158 // anyone can access the platform default factory class without permission |
133 // anyone can access the platform default factory class without permission |
159 if (defaultImplClassName != null && defaultImplClassName.equals(className)) { |
134 if (defaultImplClassName != null && defaultImplClassName.equals(className)) { |