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.util.Iterator;
21: import java.util.ServiceLoader;
22:
23: class FactoryFinder {
24:
25: /**
26: * Finds the implementation {@code Class} object for the given
27: * factory type.
28: * The arguments supplied must be used in order
29: * This method is package private so that this code can be shared.
30: *
31: * @param factoryClass factory abstract class or interface to be found
32: * @return the {@code Class} object of the specified message factory
33: * @throws RuntimeException if there is an error
34: */
35: static <T> T find(Class<T> factoryClass) throws RuntimeException {
36:
37: String factoryId = factoryClass.getName();
38:
39: // Use the system property first
40: String className = fromSystemProperty(factoryId);
41:• if (className != null) {
42: T result = newInstance(className);
43:• if (result != null) {
44: return result;
45: }
46: }
47:
48: // standard services: java.util.ServiceLoader
49: T factory = factoryFromServiceLoader(factoryClass);
50:• if (factory != null) {
51: return factory;
52: }
53:
54: // handling Glassfish/OSGi (platform specific default)
55:• if (isHk2Available()) {
56: T result = lookupUsingHk2ServiceLoader(factoryId);
57:• if (result != null) {
58: return result;
59: }
60: }
61: throw new IllegalStateException("Not provider of " + factoryClass.getName() + " was found");
62: }
63:
64: @SuppressWarnings({"unchecked"})
65: private static <T> T newInstance(String className) throws RuntimeException {
66: ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
67: checkPackageAccess(className);
68: Class<T> clazz = null;
69: try {
70:• if (classLoader == null) {
71: clazz = (Class<T>) Class.forName(className);
72: } else {
73: clazz = (Class<T>) classLoader.loadClass(className);
74: }
75: return clazz.getConstructor().newInstance();
76: } catch (ReflectiveOperationException e) {
77: throw new IllegalArgumentException("Cannot instance " + className, e);
78: }
79: }
80:
81: private static String fromSystemProperty(String factoryId) {
82: String systemProp = System.getProperty(factoryId);
83: return systemProp;
84: }
85:
86: private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "org.glassfish.hk2.osgiresourcelocator.ServiceLoader";
87:
88: private static boolean isHk2Available() {
89: try {
90: Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
91: return true;
92: } catch (ClassNotFoundException ignored) {
93: }
94: return false;
95: }
96:
97: @SuppressWarnings({"unchecked"})
98: private static <T> T lookupUsingHk2ServiceLoader(String factoryId) {
99: try {
100: // Use reflection to avoid having any dependency on HK2 ServiceLoader class
101: Class<?> serviceClass = Class.forName(factoryId);
102: Class<?>[] args = new Class<?>[]{serviceClass};
103: Class<?> target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME);
104: Method m = target.getMethod("lookupProviderInstances", Class.class);
105: Iterable<?> iterable = ((Iterable<?>) m.invoke(null, (Object[]) args));
106:• if (iterable == null) {
107: return null;
108: }
109: Iterator<?> iter = iterable.iterator();
110:• return iter.hasNext() ? (T) iter.next() : null;
111: } catch (Exception ignored) {
112: // log and continue
113: return null;
114: }
115: }
116:
117: private static <T> T factoryFromServiceLoader(Class<T> factory) {
118: try {
119: ServiceLoader<T> sl = ServiceLoader.load(factory);
120: Iterator<T> iter = sl.iterator();
121:• if (iter.hasNext()) {
122: return iter.next();
123: } else {
124: return null;
125: }
126: } catch (Throwable t) {
127: // For example, ServiceConfigurationError can be thrown if the factory class is not declared with 'uses' in module-info
128: throw new IllegalStateException("Cannot load " + factory + " as ServiceLoader", t);
129: }
130: }
131:
132: private static void checkPackageAccess(String className) {
133: // make sure that the current thread has an access to the package of the given name.
134: SecurityManager s = System.getSecurityManager();
135:• if (s != null) {
136: int i = className.lastIndexOf('.');
137:• if (i != -1) {
138: s.checkPackageAccess(className.substring(0, i));
139: }
140: }
141: }
142: }
143: