1 /*
   2  * reserved comment block
   3  * DO NOT REMOVE OR ALTER!
   4  */
   5 /*
   6  * Copyright 2001-2004 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  * $Id: ObjectFactory.java,v 1.2.4.1 2005/09/15 02:39:54 jeffsuttor Exp $
  22  */
  23 
  24 package com.sun.org.apache.xalan.internal.utils;
  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  * @version $Id: ObjectFactory.java,v 1.11 2010-11-01 04:34:25 joehw Exp $
  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(String msg) {
  51         if (DEBUG) {
  52             System.err.println("JAXP: " + msg);
  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         if (System.getSecurityManager()!=null) {
 126             return newInstance(className, null, doFallback);
 127         } else {
 128             return newInstance(className,
 129                 findClassLoader (), doFallback);
 130         }
 131     }
 132 
 133     /**
 134      * Create an instance of a class using the specified ClassLoader
 135      */
 136     static Object newInstance(String className, ClassLoader cl,
 137                                       boolean doFallback)
 138         throws ConfigurationError
 139     {
 140         // assert(className != null);
 141         try{
 142             Class providerClass = findProviderClass(className, cl, doFallback);
 143             Object instance = providerClass.newInstance();
 144             if (DEBUG) debugPrintln("created new instance of " + providerClass +
 145                    " using ClassLoader: " + cl);
 146             return instance;
 147         } catch (ClassNotFoundException x) {
 148             throw new ConfigurationError(
 149                 "Provider " + className + " not found", x);
 150         } catch (Exception x) {
 151             throw new ConfigurationError(
 152                 "Provider " + className + " could not be instantiated: " + x,
 153                 x);
 154         }
 155     }
 156 
 157     /**
 158      * Find a Class using the same class loader for the ObjectFactory by default
 159      * or boot class loader when Security Manager is in place
 160      */
 161     public static Class<?> findProviderClass(String className, boolean doFallback)
 162         throws ClassNotFoundException, ConfigurationError
 163     {
 164         return findProviderClass (className,
 165                 findClassLoader (), doFallback);
 166     }
 167 
 168     /**
 169      * Find a Class using the specified ClassLoader
 170      */
 171     private static Class<?> findProviderClass(String className, ClassLoader cl,
 172                                            boolean doFallback)
 173         throws ClassNotFoundException, ConfigurationError
 174     {
 175         //throw security exception if the calling thread is not allowed to access the
 176         //class. Restrict the access to the package classes as specified in java.security policy.
 177         SecurityManager security = System.getSecurityManager();
 178         try{
 179             if (security != null){
 180                 if (className.startsWith(JAXP_INTERNAL) ||
 181                     className.startsWith(STAX_INTERNAL)) {
 182                     cl = null;
 183                 } else {
 184                     final int lastDot = className.lastIndexOf(".");
 185                     String packageName = className;
 186                     if (lastDot != -1) packageName = className.substring(0, lastDot);
 187                     security.checkPackageAccess(packageName);
 188                 }
 189              }
 190         }catch(SecurityException e){
 191             throw e;
 192         }
 193 
 194         Class<?> providerClass;
 195         if (cl == null) {
 196             providerClass = Class.forName(className, false, ObjectFactory.class.getClassLoader());
 197         } else {
 198             try {
 199                 providerClass = cl.loadClass(className);
 200             } catch (ClassNotFoundException x) {
 201                 if (doFallback) {
 202                     // Fall back to current classloader
 203                     ClassLoader current = ObjectFactory.class.getClassLoader();
 204                     if (current == null) {
 205                         providerClass = Class.forName(className);
 206                     } else if (cl != current) {
 207                         cl = current;
 208                         providerClass = cl.loadClass(className);
 209                     } else {
 210                         throw x;
 211                     }
 212                 } else {
 213                     throw x;
 214                 }
 215             }
 216         }
 217 
 218         return providerClass;
 219     }
 220 
 221 } // class ObjectFactory