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