1 /*
2 * Copyright (c) 2004, 2013, 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.datatype;
27
28 import java.io.File;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.Iterator;
32 import java.util.Properties;
33 import java.util.ServiceConfigurationError;
34 import java.util.ServiceLoader;
35
36 /**
37 * <p>Implements pluggable Datatypes.</p>
38 *
39 * <p>This class is duplicated for each JAXP subpackage so keep it in
40 * sync. It is package private for secure class loading.</p>
41 *
42 * @author Santiago.PericasGeertsen@sun.com
43 */
44 class FactoryFinder {
45 private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
46
47 /**
48 * Internal debug flag.
49 */
50 private static boolean debug = false;
51
52 /**
53 * Cache for properties in java.home/conf/jaxp.properties
54 */
63 /**
64 * Security support class use to check access control before
65 * getting certain system resources.
66 */
67 private final static SecuritySupport ss = new SecuritySupport();
68
69 // Define system property "jaxp.debug" to get output
70 static {
71 // Use try/catch block to support applets, which throws
72 // SecurityException out of this code.
73 try {
74 String val = ss.getSystemProperty("jaxp.debug");
75 // Allow simply setting the prop to turn on debug
76 debug = val != null && !"false".equals(val);
77 }
78 catch (SecurityException se) {
79 debug = false;
80 }
81 }
82
83 private static void dPrint(String msg) {
84 if (debug) {
85 System.err.println("JAXP: " + msg);
86 }
87 }
88
89 /**
90 * Attempt to load a class using the class loader supplied. If that fails
91 * and fall back is enabled, the current (i.e. bootstrap) class loader is
92 * tried.
93 *
94 * If the class loader supplied is <code>null</code>, first try using the
95 * context class loader followed by the current (i.e. bootstrap) class
96 * loader.
97 *
98 * Use bootstrap classLoader if cl = null and useBSClsLoader is true
99 */
100 static private Class<?> getProviderClass(String className, ClassLoader cl,
101 boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
102 {
103 try {
104 if (cl == null) {
105 if (useBSClsLoader) {
173 static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
174 boolean doFallback, boolean useBSClsLoader)
175 throws DatatypeConfigurationException
176 {
177 assert type != null;
178
179 // make sure we have access to restricted packages
180 if (System.getSecurityManager() != null) {
181 if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
182 cl = null;
183 useBSClsLoader = true;
184 }
185 }
186
187 try {
188 Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
189 if (!type.isAssignableFrom(providerClass)) {
190 throw new ClassCastException(className + " cannot be cast to " + type.getName());
191 }
192 Object instance = providerClass.newInstance();
193 if (debug) { // Extra check to avoid computing cl strings
194 dPrint("created new instance of " + providerClass +
195 " using ClassLoader: " + cl);
196 }
197 return type.cast(instance);
198 }
199 catch (ClassNotFoundException x) {
200 throw new DatatypeConfigurationException(
201 "Provider " + className + " not found", x);
202 }
203 catch (Exception x) {
204 throw new DatatypeConfigurationException(
205 "Provider " + className + " could not be instantiated: " + x,
206 x);
207 }
208 }
209
210 /**
211 * Finds the implementation Class object in the specified order. Main
212 * entry point.
213 * @return Class object of factory, never null
214 *
215 * @param type Base class / Service interface of the
216 * factory to find.
217 * @param fallbackClassName Implementation class name, if nothing else
218 * is found. Use null to mean no fallback.
219 *
220 * Package private so this code can be shared.
221 */
222 static <T> T find(Class<T> type, String fallbackClassName)
223 throws DatatypeConfigurationException
224 {
225 final String factoryId = type.getName();
226 dPrint("find factoryId =" + factoryId);
227
228 // Use the system property first
229 try {
230 String systemProp = ss.getSystemProperty(factoryId);
231 if (systemProp != null) {
232 dPrint("found system property, value=" + systemProp);
233 return newInstance(type, systemProp, null, true);
234 }
235 }
236 catch (SecurityException se) {
237 if (debug) se.printStackTrace();
238 }
239
240 // try to read from $java.home/conf/jaxp.properties
241 try {
242 if (firstTime) {
243 synchronized (cacheProps) {
244 if (firstTime) {
245 String configFile = ss.getSystemProperty("java.home") + File.separator +
246 "conf" + File.separator + "jaxp.properties";
247 File f = new File(configFile);
248 firstTime = false;
249 if (ss.doesFileExist(f)) {
250 dPrint("Read properties file "+f);
251 cacheProps.load(ss.getFileInputStream(f));
252 }
253 }
254 }
255 }
256 final String factoryClassName = cacheProps.getProperty(factoryId);
257
258 if (factoryClassName != null) {
259 dPrint("found in ${java.home}/conf/jaxp.properties, value=" + factoryClassName);
260 return newInstance(type, factoryClassName, null, true);
261 }
262 }
263 catch (Exception ex) {
264 if (debug) ex.printStackTrace();
265 }
266
267 // Try Jar Service Provider Mechanism
268 final T provider = findServiceProvider(type);
269 if (provider != null) {
270 return provider;
271 }
272 if (fallbackClassName == null) {
273 throw new DatatypeConfigurationException(
274 "Provider for " + factoryId + " cannot be found");
275 }
276
277 dPrint("loaded from fallback value: " + fallbackClassName);
278 return newInstance(type, fallbackClassName, null, true);
279 }
280
281 /*
282 * Try to find provider using the ServiceLoader API
283 *
284 * @param type Base class / Service interface of the factory to find.
285 *
286 * @return instance of provider class if found or null
287 */
288 private static <T> T findServiceProvider(final Class<T> type)
289 throws DatatypeConfigurationException
290 {
291 try {
292 return AccessController.doPrivileged(new PrivilegedAction<T>() {
293 public T run() {
294 final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
295 final Iterator<T> iterator = serviceLoader.iterator();
296 if (iterator.hasNext()) {
297 return iterator.next();
|
1 /*
2 * Copyright (c) 2004, 2016, 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.datatype;
27
28 import java.io.File;
29 import java.security.AccessController;
30 import java.security.PrivilegedAction;
31 import java.util.Iterator;
32 import java.util.Properties;
33 import java.util.ServiceConfigurationError;
34 import java.util.ServiceLoader;
35 import java.util.function.Supplier;
36
37 /**
38 * <p>Implements pluggable Datatypes.</p>
39 *
40 * <p>This class is duplicated for each JAXP subpackage so keep it in
41 * sync. It is package private for secure class loading.</p>
42 *
43 * @author Santiago.PericasGeertsen@sun.com
44 */
45 class FactoryFinder {
46 private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
47
48 /**
49 * Internal debug flag.
50 */
51 private static boolean debug = false;
52
53 /**
54 * Cache for properties in java.home/conf/jaxp.properties
55 */
64 /**
65 * Security support class use to check access control before
66 * getting certain system resources.
67 */
68 private final static SecuritySupport ss = new SecuritySupport();
69
70 // Define system property "jaxp.debug" to get output
71 static {
72 // Use try/catch block to support applets, which throws
73 // SecurityException out of this code.
74 try {
75 String val = ss.getSystemProperty("jaxp.debug");
76 // Allow simply setting the prop to turn on debug
77 debug = val != null && !"false".equals(val);
78 }
79 catch (SecurityException se) {
80 debug = false;
81 }
82 }
83
84 private static void dPrint(Supplier<String> msgGen) {
85 if (debug) {
86 System.err.println("JAXP: " + msgGen.get());
87 }
88 }
89
90 /**
91 * Attempt to load a class using the class loader supplied. If that fails
92 * and fall back is enabled, the current (i.e. bootstrap) class loader is
93 * tried.
94 *
95 * If the class loader supplied is <code>null</code>, first try using the
96 * context class loader followed by the current (i.e. bootstrap) class
97 * loader.
98 *
99 * Use bootstrap classLoader if cl = null and useBSClsLoader is true
100 */
101 static private Class<?> getProviderClass(String className, ClassLoader cl,
102 boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
103 {
104 try {
105 if (cl == null) {
106 if (useBSClsLoader) {
174 static <T> T newInstance(Class<T> type, String className, ClassLoader cl,
175 boolean doFallback, boolean useBSClsLoader)
176 throws DatatypeConfigurationException
177 {
178 assert type != null;
179
180 // make sure we have access to restricted packages
181 if (System.getSecurityManager() != null) {
182 if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
183 cl = null;
184 useBSClsLoader = true;
185 }
186 }
187
188 try {
189 Class<?> providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
190 if (!type.isAssignableFrom(providerClass)) {
191 throw new ClassCastException(className + " cannot be cast to " + type.getName());
192 }
193 Object instance = providerClass.newInstance();
194 final ClassLoader clD = cl;
195 dPrint(()->"created new instance of " + providerClass +
196 " using ClassLoader: " + clD);
197 return type.cast(instance);
198 }
199 catch (ClassNotFoundException x) {
200 throw new DatatypeConfigurationException(
201 "Provider " + className + " not found", x);
202 }
203 catch (Exception x) {
204 throw new DatatypeConfigurationException(
205 "Provider " + className + " could not be instantiated: " + x,
206 x);
207 }
208 }
209
210 /**
211 * Finds the implementation Class object in the specified order. Main
212 * entry point.
213 * @return Class object of factory, never null
214 *
215 * @param type Base class / Service interface of the
216 * factory to find.
217 * @param fallbackClassName Implementation class name, if nothing else
218 * is found. Use null to mean no fallback.
219 *
220 * Package private so this code can be shared.
221 */
222 static <T> T find(Class<T> type, String fallbackClassName)
223 throws DatatypeConfigurationException
224 {
225 final String factoryId = type.getName();
226 dPrint(()->"find factoryId =" + factoryId);
227
228 // Use the system property first
229 try {
230 String systemProp = ss.getSystemProperty(factoryId);
231 if (systemProp != null) {
232 dPrint(()->"found system property, value=" + systemProp);
233 return newInstance(type, systemProp, null, true);
234 }
235 }
236 catch (SecurityException se) {
237 if (debug) se.printStackTrace();
238 }
239
240 // try to read from $java.home/conf/jaxp.properties
241 try {
242 if (firstTime) {
243 synchronized (cacheProps) {
244 if (firstTime) {
245 String configFile = ss.getSystemProperty("java.home") + File.separator +
246 "conf" + File.separator + "jaxp.properties";
247 File f = new File(configFile);
248 firstTime = false;
249 if (ss.doesFileExist(f)) {
250 dPrint(()->"Read properties file "+f);
251 cacheProps.load(ss.getFileInputStream(f));
252 }
253 }
254 }
255 }
256 final String factoryClassName = cacheProps.getProperty(factoryId);
257
258 if (factoryClassName != null) {
259 dPrint(()->"found in ${java.home}/conf/jaxp.properties, value=" + factoryClassName);
260 return newInstance(type, factoryClassName, null, true);
261 }
262 }
263 catch (Exception ex) {
264 if (debug) ex.printStackTrace();
265 }
266
267 // Try Jar Service Provider Mechanism
268 final T provider = findServiceProvider(type);
269 if (provider != null) {
270 return provider;
271 }
272 if (fallbackClassName == null) {
273 throw new DatatypeConfigurationException(
274 "Provider for " + factoryId + " cannot be found");
275 }
276
277 dPrint(()->"loaded from fallback value: " + fallbackClassName);
278 return newInstance(type, fallbackClassName, null, true);
279 }
280
281 /*
282 * Try to find provider using the ServiceLoader API
283 *
284 * @param type Base class / Service interface of the factory to find.
285 *
286 * @return instance of provider class if found or null
287 */
288 private static <T> T findServiceProvider(final Class<T> type)
289 throws DatatypeConfigurationException
290 {
291 try {
292 return AccessController.doPrivileged(new PrivilegedAction<T>() {
293 public T run() {
294 final ServiceLoader<T> serviceLoader = ServiceLoader.load(type);
295 final Iterator<T> iterator = serviceLoader.iterator();
296 if (iterator.hasNext()) {
297 return iterator.next();
|