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.xerces.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 code is designed to implement the JAXP 1.1 spec pluggability 32 * feature and is designed to run on JDK version 1.1 and 33 * later, and to compile on JDK 1.2 and onward. 34 * The code also runs both as part of an unbundled jar file and 35 * when bundled as part of the JDK. 36 * <p> 37 * 38 * @LastModified: Oct 2017 39 */ 40 public final class ObjectFactory { 41 42 // 43 // Constants 44 // 45 private static final String JAXP_INTERNAL = "com.sun.org.apache"; 46 private static final String STAX_INTERNAL = "com.sun.xml.internal"; 47 48 /** Set to true for debugging */ 49 private static final boolean DEBUG = isDebugEnabled(); 50 51 52 // 53 // Private static methods 54 // 55 56 /** Returns true if debug has been enabled. */ 57 private static boolean isDebugEnabled() { 58 try { 59 String val = SecuritySupport.getSystemProperty("xerces.debug"); 60 // Allow simply setting the prop to turn on debug 61 return (val != null && (!"false".equals(val))); 62 } 63 catch (SecurityException se) {} 64 return false; 65 } // isDebugEnabled() 66 67 /** Prints a message to standard error if debugging is enabled. */ 68 private static void debugPrintln(Supplier<String> msgGen) { 69 if (DEBUG) { 70 System.err.println("XERCES: " + msgGen.get()); 71 } 72 } // debugPrintln(String) 73 74 /** 75 * Figure out which ClassLoader to use. For JDK 1.2 and later use 76 * the context ClassLoader. 77 */ 78 public static ClassLoader findClassLoader() 79 throws ConfigurationError 80 { 81 if (System.getSecurityManager()!=null) { 82 //this will ensure bootclassloader is used 83 return null; 84 } 85 // Figure out which ClassLoader to use for loading the provider 86 // class. If there is a Context ClassLoader then use it. 87 ClassLoader context = SecuritySupport.getContextClassLoader(); 88 ClassLoader system = SecuritySupport.getSystemClassLoader(); 89 90 ClassLoader chain = system; 91 while (true) { 92 if (context == chain) { 93 // Assert: we are on JDK 1.1 or we have no Context ClassLoader 94 // or any Context ClassLoader in chain of system classloader 95 // (including extension ClassLoader) so extend to widest 96 // ClassLoader (always look in system ClassLoader if Xerces 97 // is in boot/extension/system classpath and in current 98 // ClassLoader otherwise); normal classloaders delegate 99 // back to system ClassLoader first so this widening doesn't 100 // change the fact that context ClassLoader will be consulted 101 ClassLoader current = ObjectFactory.class.getClassLoader(); 102 103 chain = system; 104 while (true) { 105 if (current == chain) { 106 // Assert: Current ClassLoader in chain of 107 // boot/extension/system ClassLoaders 108 return system; 109 } 110 if (chain == null) { 111 break; 112 } 113 chain = SecuritySupport.getParentClassLoader(chain); 114 } 115 116 // Assert: Current ClassLoader not in chain of 117 // boot/extension/system ClassLoaders 118 return current; 119 } 120 121 if (chain == null) { 122 // boot ClassLoader reached 123 break; 124 } 125 126 // Check for any extension ClassLoaders in chain up to 127 // boot ClassLoader 128 chain = SecuritySupport.getParentClassLoader(chain); 129 } 130 131 // Assert: Context ClassLoader not in chain of 132 // boot/extension/system ClassLoaders 133 return context; 134 } // findClassLoader():ClassLoader 135 136 /** 137 * Create an instance of a class using the same classloader for the ObjectFactory by default 138 * or bootclassloader when Security Manager is in place 139 */ 140 public static Object newInstance(String className, boolean doFallback) 141 throws ConfigurationError 142 { 143 if (System.getSecurityManager()!=null) { 144 return newInstance(className, null, doFallback); 145 } else { 146 return newInstance(className, 147 findClassLoader (), doFallback); 148 } 149 } 150 151 /** 152 * Create an instance of a class using the specified ClassLoader 153 */ 154 public static Object newInstance(String className, ClassLoader cl, 155 boolean doFallback) 156 throws ConfigurationError 157 { 158 // assert(className != null); 159 try{ 160 Class<?> providerClass = findProviderClass(className, cl, doFallback); 161 Object instance = providerClass.getConstructor().newInstance(); 162 debugPrintln(()->"created new instance of " + providerClass + 163 " using ClassLoader: " + cl); 164 return instance; 165 } catch (ClassNotFoundException x) { 166 throw new ConfigurationError( 167 "Provider " + className + " not found", x); 168 } catch (Exception x) { 169 throw new ConfigurationError( 170 "Provider " + className + " could not be instantiated: " + x, 171 x); 172 } 173 } 174 175 /** 176 * Find a Class using the same classloader for the ObjectFactory by default 177 * or bootclassloader when Security Manager is in place 178 */ 179 public static Class<?> findProviderClass(String className, boolean doFallback) 180 throws ClassNotFoundException, ConfigurationError 181 { 182 return findProviderClass (className, 183 findClassLoader (), doFallback); 184 } 185 /** 186 * Find a Class using the specified ClassLoader 187 */ 188 public static Class<?> findProviderClass(String className, ClassLoader cl, 189 boolean doFallback) 190 throws ClassNotFoundException, ConfigurationError 191 { 192 //throw security exception if the calling thread is not allowed to access the package 193 //restrict the access to package as speicified in java.security policy 194 SecurityManager security = System.getSecurityManager(); 195 if (security != null) { 196 if (className.startsWith(JAXP_INTERNAL) || 197 className.startsWith(STAX_INTERNAL)) { 198 cl = null; 199 } else { 200 final int lastDot = className.lastIndexOf("."); 201 String packageName = className; 202 if (lastDot != -1) packageName = className.substring(0, lastDot); 203 security.checkPackageAccess(packageName); 204 } 205 } 206 Class<?> providerClass; 207 if (cl == null) { 208 //use the bootstrap ClassLoader. 209 providerClass = Class.forName(className, false, ObjectFactory.class.getClassLoader()); 210 } else { 211 try { 212 providerClass = cl.loadClass(className); 213 } catch (ClassNotFoundException x) { 214 if (doFallback) { 215 // Fall back to current classloader 216 ClassLoader current = ObjectFactory.class.getClassLoader(); 217 if (current == null) { 218 providerClass = Class.forName(className); 219 } else if (cl != current) { 220 cl = current; 221 providerClass = cl.loadClass(className); 222 } else { 223 throw x; 224 } 225 } else { 226 throw x; 227 } 228 } 229 } 230 231 return providerClass; 232 } 233 234 } // class ObjectFactory