Skip to content

Package: FactoryFinder

FactoryFinder

nameinstructionbranchcomplexitylinemethod
FactoryFinder()
M: 3 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 1 C: 0
0%
M: 1 C: 0
0%
checkPackageAccess(String)
M: 18 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 6 C: 0
0%
M: 1 C: 0
0%
factoryFromServiceLoader(Class)
M: 30 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 7 C: 0
0%
M: 1 C: 0
0%
find(Class)
M: 46 C: 0
0%
M: 10 C: 0
0%
M: 6 C: 0
0%
M: 14 C: 0
0%
M: 1 C: 0
0%
fromSystemProperty(String)
M: 5 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 2 C: 0
0%
M: 1 C: 0
0%
isHk2Available()
M: 8 C: 0
0%
M: 0 C: 0
100%
M: 1 C: 0
0%
M: 4 C: 0
0%
M: 1 C: 0
0%
lookupUsingHk2ServiceLoader(String)
M: 48 C: 0
0%
M: 4 C: 0
0%
M: 3 C: 0
0%
M: 11 C: 0
0%
M: 1 C: 0
0%
newInstance(String)
M: 39 C: 0
0%
M: 2 C: 0
0%
M: 2 C: 0
0%
M: 9 C: 0
0%
M: 1 C: 0
0%

Coverage

1: /*
2: * Copyright (c) 2021, 2023 Oracle and/or its affiliates. All rights reserved.
3: *
4: * This program and the accompanying materials are made available under the
5: * terms of the Eclipse Public License v. 2.0, which is available at
6: * http://www.eclipse.org/legal/epl-2.0.
7: *
8: * This Source Code may also be made available under the following Secondary
9: * Licenses when the conditions for such availability set forth in the
10: * Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
11: * version 2 with the GNU Classpath Exception, which is available at
12: * https://www.gnu.org/software/classpath/license.html.
13: *
14: * SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
15: */
16:
17: package jakarta.mail.util;
18:
19: import java.lang.reflect.Method;
20: import java.security.AccessController;
21: import java.security.PrivilegedAction;
22: import java.util.Iterator;
23: import java.util.ServiceLoader;
24:
25: class FactoryFinder {
26:
27: /**
28: * Finds the implementation {@code Class} object for the given
29: * factory type.
30: * The arguments supplied must be used in order
31: * This method is package private so that this code can be shared.
32: *
33: * @return the {@code Class} object of the specified message factory
34: *
35: * @param factoryClass factory abstract class or interface to be found
36: * @exception RuntimeException if there is an error
37: */
38: static <T> T find(Class<T> factoryClass) throws RuntimeException {
39:
40: String factoryId = factoryClass.getName();
41:
42: // Use the system property first
43: String className = fromSystemProperty(factoryId);
44:• if (className != null) {
45: T result = newInstance(className);
46:• if (result != null) {
47: return result;
48: }
49: }
50:
51: // standard services: java.util.ServiceLoader
52: T factory = factoryFromServiceLoader(factoryClass);
53:• if (factory != null) {
54: return factory;
55: }
56:
57: // handling Glassfish/OSGi (platform specific default)
58:• if (isHk2Available()) {
59: T result = lookupUsingHk2ServiceLoader(factoryId);
60:• if (result != null) {
61: return result;
62: }
63: }
64: throw new IllegalStateException("Not provider of " + factoryClass.getName() + " was found");
65: }
66:
67: @SuppressWarnings({"unchecked"})
68: private static <T> T newInstance(String className) throws RuntimeException {
69: ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
70: checkPackageAccess(className);
71: Class<T> clazz = null;
72: try {
73:• if (classLoader == null) {
74: clazz = (Class<T>) Class.forName(className);
75: } else {
76: clazz = (Class<T>) classLoader.loadClass(className);
77: }
78: return clazz.getConstructor().newInstance();
79: } catch (ReflectiveOperationException e) {
80: throw new IllegalArgumentException("Cannot instance " + className, e);
81: }
82: }
83:
84: private static String fromSystemProperty(String factoryId) {
85: String systemProp = System.getProperty(factoryId);
86: return systemProp;
87: }
88:
89: private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "org.glassfish.hk2.osgiresourcelocator.ServiceLoader";
90:
91: private static boolean isHk2Available() {
92: try {
93: Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
94: return true;
95: } catch (ClassNotFoundException ignored) {
96: }
97: return false;
98: }
99:
100: @SuppressWarnings({"unchecked"})
101: private static <T> T lookupUsingHk2ServiceLoader(String factoryId) {
102: try {
103: // Use reflection to avoid having any dependency on HK2 ServiceLoader class
104: Class<?> serviceClass = Class.forName(factoryId);
105: Class<?>[] args = new Class<?>[]{serviceClass};
106: Class<?> target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
107: Method m = target.getMethod("lookupProviderInstances", Class.class);
108: Iterable<?> iterable = ((Iterable<?>) m.invoke(null, (Object[]) args));
109:• if (iterable == null) {
110: return null;
111: }
112: Iterator<?> iter = iterable.iterator();
113:• return iter.hasNext() ? (T) iter.next() : null;
114: } catch (Exception ignored) {
115: // log and continue
116: return null;
117: }
118: }
119:
120: private static <T> T factoryFromServiceLoader(Class<T> factory) {
121: try {
122: ServiceLoader<T> sl = ServiceLoader.load(factory);
123: Iterator<T> iter = sl.iterator();
124:• if (iter.hasNext()) {
125: return iter.next();
126: } else {
127: return null;
128: }
129: } catch (Throwable t) {
130: // For example, ServiceConfigurationError can be thrown if the factory class is not declared with 'uses' in module-info
131: throw new IllegalStateException("Cannot load " + factory + " as ServiceLoader", t);
132: }
133: }
134:
135: private static void checkPackageAccess(String className) {
136: // make sure that the current thread has an access to the package of the given name.
137: SecurityManager s = System.getSecurityManager();
138:• if (s != null) {
139: int i = className.lastIndexOf('.');
140:• if (i != -1) {
141: s.checkPackageAccess(className.substring(0, i));
142: }
143: }
144: }
145: }
146: