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