changeset 47216 | 71c04702a3d5 |
parent 45853 | bfa06be36a17 |
child 47312 | d4f959806fe9 |
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/java.xml/share/classes/com/sun/org/apache/xalan/internal/utils/ObjectFactory.java Tue Sep 12 19:03:39 2017 +0200 @@ -0,0 +1,204 @@ +/* + * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. + */ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.sun.org.apache.xalan.internal.utils; + +import java.util.function.Supplier; + +/** + * This class is duplicated for each JAXP subpackage so keep it in sync. + * It is package private and therefore is not exposed as part of the JAXP + * API. + * <p> + * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code> + * class and modified to be used as a general utility for creating objects + * dynamically. + * + */ +public class ObjectFactory { + + // + // Constants + // + private static final String JAXP_INTERNAL = "com.sun.org.apache"; + private static final String STAX_INTERNAL = "com.sun.xml.internal"; + + /** Set to true for debugging */ + private static final boolean DEBUG = false; + + + /** Prints a message to standard error if debugging is enabled. */ + private static void debugPrintln(Supplier<String> msgGen) { + if (DEBUG) { + System.err.println("JAXP: " + msgGen.get()); + } + } // debugPrintln(String) + + /** + * Figure out which ClassLoader to use. For JDK 1.2 and later use + * the context ClassLoader. + */ + public static ClassLoader findClassLoader() + { + if (System.getSecurityManager()!=null) { + //this will ensure bootclassloader is used + return null; + } + + // Figure out which ClassLoader to use for loading the provider + // class. If there is a Context ClassLoader then use it. + ClassLoader context = SecuritySupport.getContextClassLoader(); + ClassLoader system = SecuritySupport.getSystemClassLoader(); + + ClassLoader chain = system; + while (true) { + if (context == chain) { + // Assert: we are on JDK 1.1 or we have no Context ClassLoader + // or any Context ClassLoader in chain of system classloader + // (including extension ClassLoader) so extend to widest + // ClassLoader (always look in system ClassLoader if Xalan + // is in boot/extension/system classpath and in current + // ClassLoader otherwise); normal classloaders delegate + // back to system ClassLoader first so this widening doesn't + // change the fact that context ClassLoader will be consulted + ClassLoader current = ObjectFactory.class.getClassLoader(); + + chain = system; + while (true) { + if (current == chain) { + // Assert: Current ClassLoader in chain of + // boot/extension/system ClassLoaders + return system; + } + if (chain == null) { + break; + } + chain = SecuritySupport.getParentClassLoader(chain); + } + + // Assert: Current ClassLoader not in chain of + // boot/extension/system ClassLoaders + return current; + } + + if (chain == null) { + // boot ClassLoader reached + break; + } + + // Check for any extension ClassLoaders in chain up to + // boot ClassLoader + chain = SecuritySupport.getParentClassLoader(chain); + } + + // Assert: Context ClassLoader not in chain of + // boot/extension/system ClassLoaders + return context; + } // findClassLoader():ClassLoader + + /** + * Create an instance of a class using the same class loader for the ObjectFactory by default + * or boot class loader when Security Manager is in place + */ + public static Object newInstance(String className, boolean doFallback) + throws ConfigurationError + { + ClassLoader cl = System.getSecurityManager()!=null ? null : findClassLoader(); + try{ + Class providerClass = findProviderClass(className, cl, doFallback); + Object instance = providerClass.getConstructor().newInstance(); + debugPrintln(()->"created new instance of " + providerClass + + " using ClassLoader: " + cl); + return instance; + } catch (ClassNotFoundException x) { + throw new ConfigurationError( + "Provider " + className + " not found", x); + } catch (Exception x) { + throw new ConfigurationError( + "Provider " + className + " could not be instantiated: " + x, + x); + } + } + + /** + * Find a Class using the same class loader for the ObjectFactory by default + * or boot class loader when Security Manager is in place + */ + public static Class<?> findProviderClass(String className, boolean doFallback) + throws ClassNotFoundException, ConfigurationError + { + return findProviderClass (className, + findClassLoader (), doFallback); + } + + /** + * Find a Class using the specified ClassLoader + */ + private static Class<?> findProviderClass(String className, ClassLoader cl, + boolean doFallback) + throws ClassNotFoundException, ConfigurationError + { + //throw security exception if the calling thread is not allowed to access the + //class. Restrict the access to the package classes as specified in java.security policy. + SecurityManager security = System.getSecurityManager(); + try{ + if (security != null){ + if (className.startsWith(JAXP_INTERNAL) || + className.startsWith(STAX_INTERNAL)) { + cl = null; + } else { + final int lastDot = className.lastIndexOf("."); + String packageName = className; + if (lastDot != -1) packageName = className.substring(0, lastDot); + security.checkPackageAccess(packageName); + } + } + }catch(SecurityException e){ + throw e; + } + + Class<?> providerClass; + if (cl == null) { + providerClass = Class.forName(className, false, ObjectFactory.class.getClassLoader()); + } else { + try { + providerClass = cl.loadClass(className); + } catch (ClassNotFoundException x) { + if (doFallback) { + // Fall back to current classloader + ClassLoader current = ObjectFactory.class.getClassLoader(); + if (current == null) { + providerClass = Class.forName(className); + } else if (cl != current) { + cl = current; + providerClass = cl.loadClass(className); + } else { + throw x; + } + } else { + throw x; + } + } + } + + return providerClass; + } + +} // class ObjectFactory