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