1/* 2 * Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved. 3 */ 4/* 5 * Licensed to the Apache Software Foundation (ASF) under one or more 6 * contributor license agreements. See the NOTICE file distributed with 7 * this work for additional information regarding copyright ownership. 8 * The ASF licenses this file to You under the Apache License, Version 2.0 9 * (the "License"); you may not use this file except in compliance with 10 * the License. You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 */ 20 21package com.sun.org.apache.xalan.internal.utils; 22 23import java.util.function.Supplier; 24 25/** 26 * This class is duplicated for each JAXP subpackage so keep it in sync. 27 * It is package private and therefore is not exposed as part of the JAXP 28 * API. 29 * <p> 30 * This class was moved from the <code>javax.xml.parsers.ObjectFactory</code> 31 * class and modified to be used as a general utility for creating objects 32 * dynamically. 33 * 34 */ 35public class ObjectFactory { 36 37 // 38 // Constants 39 // 40 private static final String JAXP_INTERNAL = "com.sun.org.apache"; 41 private static final String STAX_INTERNAL = "com.sun.xml.internal"; 42 43 /** Set to true for debugging */ 44 private static final boolean DEBUG = false; 45 46 47 /** Prints a message to standard error if debugging is enabled. */ 48 private static void debugPrintln(Supplier<String> msgGen) { 49 if (DEBUG) { 50 System.err.println("JAXP: " + msgGen.get()); 51 } 52 } // debugPrintln(String) 53 54 /** 55 * Figure out which ClassLoader to use. For JDK 1.2 and later use 56 * the context ClassLoader. 57 */ 58 public static ClassLoader findClassLoader() 59 { 60 if (System.getSecurityManager()!=null) { 61 //this will ensure bootclassloader is used 62 return null; 63 } 64 65 // Figure out which ClassLoader to use for loading the provider 66 // class. If there is a Context ClassLoader then use it. 67 ClassLoader context = SecuritySupport.getContextClassLoader(); 68 ClassLoader system = SecuritySupport.getSystemClassLoader(); 69 70 ClassLoader chain = system; 71 while (true) { 72 if (context == chain) { 73 // Assert: we are on JDK 1.1 or we have no Context ClassLoader 74 // or any Context ClassLoader in chain of system classloader 75 // (including extension ClassLoader) so extend to widest 76 // ClassLoader (always look in system ClassLoader if Xalan 77 // is in boot/extension/system classpath and in current 78 // ClassLoader otherwise); normal classloaders delegate 79 // back to system ClassLoader first so this widening doesn't 80 // change the fact that context ClassLoader will be consulted 81 ClassLoader current = ObjectFactory.class.getClassLoader(); 82 83 chain = system; 84 while (true) { 85 if (current == chain) { 86 // Assert: Current ClassLoader in chain of 87 // boot/extension/system ClassLoaders 88 return system; 89 } 90 if (chain == null) { 91 break; 92 } 93 chain = SecuritySupport.getParentClassLoader(chain); 94 } 95 96 // Assert: Current ClassLoader not in chain of 97 // boot/extension/system ClassLoaders 98 return current; 99 } 100 101 if (chain == null) { 102 // boot ClassLoader reached 103 break; 104 } 105 106 // Check for any extension ClassLoaders in chain up to 107 // boot ClassLoader 108 chain = SecuritySupport.getParentClassLoader(chain); 109 } 110 111 // Assert: Context ClassLoader not in chain of 112 // boot/extension/system ClassLoaders 113 return context; 114 } // findClassLoader():ClassLoader 115 116 /** 117 * Create an instance of a class using the same class loader for the ObjectFactory by default 118 * or boot class loader when Security Manager is in place 119 */ 120 public static Object newInstance(String className, boolean doFallback) 121 throws ConfigurationError 122 { 123 ClassLoader cl = System.getSecurityManager()!=null ? null : findClassLoader(); 124 try{ 125 Class providerClass = findProviderClass(className, cl, doFallback); 126 Object instance = providerClass.getConstructor().newInstance(); 127 debugPrintln(()->"created new instance of " + providerClass + 128 " using ClassLoader: " + cl); 129 return instance; 130 } catch (ClassNotFoundException x) { 131 throw new ConfigurationError( 132 "Provider " + className + " not found", x); 133 } catch (Exception x) { 134 throw new ConfigurationError( 135 "Provider " + className + " could not be instantiated: " + x, 136 x); 137 } 138 } 139 140 /** 141 * Find a Class using the same class loader for the ObjectFactory by default 142 * or boot class loader when Security Manager is in place 143 */ 144 public static Class<?> findProviderClass(String className, boolean doFallback) 145 throws ClassNotFoundException, ConfigurationError 146 { 147 return findProviderClass (className, 148 findClassLoader (), doFallback); 149 } 150 151 /** 152 * Find a Class using the specified ClassLoader 153 */ 154 private static Class<?> findProviderClass(String className, ClassLoader cl, 155 boolean doFallback) 156 throws ClassNotFoundException, ConfigurationError 157 { 158 //throw security exception if the calling thread is not allowed to access the 159 //class. Restrict the access to the package classes as specified in java.security policy. 160 SecurityManager security = System.getSecurityManager(); 161 try{ 162 if (security != null){ 163 if (className.startsWith(JAXP_INTERNAL) || 164 className.startsWith(STAX_INTERNAL)) { 165 cl = null; 166 } else { 167 final int lastDot = className.lastIndexOf("."); 168 String packageName = className; 169 if (lastDot != -1) packageName = className.substring(0, lastDot); 170 security.checkPackageAccess(packageName); 171 } 172 } 173 }catch(SecurityException e){ 174 throw e; 175 } 176 177 Class<?> providerClass; 178 if (cl == null) { 179 providerClass = Class.forName(className, false, ObjectFactory.class.getClassLoader()); 180 } else { 181 try { 182 providerClass = cl.loadClass(className); 183 } catch (ClassNotFoundException x) { 184 if (doFallback) { 185 // Fall back to current classloader 186 ClassLoader current = ObjectFactory.class.getClassLoader(); 187 if (current == null) { 188 providerClass = Class.forName(className); 189 } else if (cl != current) { 190 cl = current; 191 providerClass = cl.loadClass(className); 192 } else { 193 throw x; 194 } 195 } else { 196 throw x; 197 } 198 } 199 } 200 201 return providerClass; 202 } 203 204} // class ObjectFactory 205