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