jaxp/src/javax/xml/datatype/FactoryFinder.java
changeset 16953 a44e04deb948
parent 12458 d601e4bba306
child 17264 3aff554ad461
equal deleted inserted replaced
16416:bcebd3fdefc9 16953:a44e04deb948
    42  * sync.  It is package private for secure class loading.</p>
    42  * sync.  It is package private for secure class loading.</p>
    43  *
    43  *
    44  * @author Santiago.PericasGeertsen@sun.com
    44  * @author Santiago.PericasGeertsen@sun.com
    45  */
    45  */
    46 class FactoryFinder {
    46 class FactoryFinder {
       
    47     private static final String DEFAULT_PACKAGE = "com.sun.org.apache.xerces.internal";
    47 
    48 
    48     /**
    49     /**
    49      * Internal debug flag.
    50      * Internal debug flag.
    50      */
    51      */
    51     private static boolean debug = false;
    52     private static boolean debug = false;
    93      * tried.
    94      * tried.
    94      *
    95      *
    95      * If the class loader supplied is <code>null</code>, first try using the
    96      * If the class loader supplied is <code>null</code>, first try using the
    96      * context class loader followed by the current (i.e. bootstrap) class
    97      * context class loader followed by the current (i.e. bootstrap) class
    97      * loader.
    98      * loader.
       
    99      *
       
   100      * Use bootstrap classLoader if cl = null and useBSClsLoader is true
    98      */
   101      */
    99     static private Class getProviderClass(String className, ClassLoader cl,
   102     static private Class getProviderClass(String className, ClassLoader cl,
   100             boolean doFallback) throws ClassNotFoundException
   103             boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
   101     {
   104     {
   102         try {
   105         try {
   103             if (cl == null) {
   106             if (cl == null) {
   104                 cl = ss.getContextClassLoader();
   107                 if (useBSClsLoader) {
   105                 if (cl == null) {
   108                     return Class.forName(className, true, FactoryFinder.class.getClassLoader());
   106                     throw new ClassNotFoundException();
   109                 } else {
   107                 }
   110                     cl = ss.getContextClassLoader();
   108                 else {
   111                     if (cl == null) {
   109                     return cl.loadClass(className);
   112                         throw new ClassNotFoundException();
       
   113                     }
       
   114                     else {
       
   115                         return cl.loadClass(className);
       
   116                     }
   110                 }
   117                 }
   111             }
   118             }
   112             else {
   119             else {
   113                 return cl.loadClass(className);
   120                 return cl.loadClass(className);
   114             }
   121             }
   129      * <code>getProviderClass()</code> in order to load the class.
   136      * <code>getProviderClass()</code> in order to load the class.
   130      *
   137      *
   131      * @param className Name of the concrete class corresponding to the
   138      * @param className Name of the concrete class corresponding to the
   132      * service provider
   139      * service provider
   133      *
   140      *
       
   141      * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
       
   142      * current <code>Thread</code>'s context classLoader is used to load the factory class.
       
   143      *
       
   144      * @param doFallback True if the current ClassLoader should be tried as
       
   145      * a fallback if the class is not found using cl
       
   146      */
       
   147     static Object newInstance(String className, ClassLoader cl, boolean doFallback)
       
   148         throws ConfigurationError
       
   149     {
       
   150         return newInstance(className, cl, doFallback, false);
       
   151     }
       
   152 
       
   153     /**
       
   154      * Create an instance of a class. Delegates to method
       
   155      * <code>getProviderClass()</code> in order to load the class.
       
   156      *
       
   157      * @param className Name of the concrete class corresponding to the
       
   158      * service provider
       
   159      *
   134      * @param cl ClassLoader to use to load the class, null means to use
   160      * @param cl ClassLoader to use to load the class, null means to use
   135      * the bootstrap ClassLoader
   161      * the bootstrap ClassLoader
   136      *
   162      *
   137      * @param doFallback True if the current ClassLoader should be tried as
   163      * @param doFallback True if the current ClassLoader should be tried as
   138      * a fallback if the class is not found using cl
   164      * a fallback if the class is not found using cl
   139      */
   165      *
   140     static Object newInstance(String className, ClassLoader cl, boolean doFallback)
   166      * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
       
   167      * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
       
   168      */
       
   169     static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
   141         throws ConfigurationError
   170         throws ConfigurationError
   142     {
   171     {
   143         try {
   172         // make sure we have access to restricted packages
   144             Class providerClass = getProviderClass(className, cl, doFallback);
   173         if (System.getSecurityManager() != null) {
       
   174             if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
       
   175                 cl = null;
       
   176                 useBSClsLoader = true;
       
   177             }
       
   178         }
       
   179 
       
   180         try {
       
   181             Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
   145             Object instance = providerClass.newInstance();
   182             Object instance = providerClass.newInstance();
   146             if (debug) {    // Extra check to avoid computing cl strings
   183             if (debug) {    // Extra check to avoid computing cl strings
   147                 dPrint("created new instance of " + providerClass +
   184                 dPrint("created new instance of " + providerClass +
   148                        " using ClassLoader: " + cl);
   185                        " using ClassLoader: " + cl);
   149             }
   186             }
   242         String serviceId = "META-INF/services/" + factoryId;
   279         String serviceId = "META-INF/services/" + factoryId;
   243         InputStream is = null;
   280         InputStream is = null;
   244 
   281 
   245         // First try the Context ClassLoader
   282         // First try the Context ClassLoader
   246         ClassLoader cl = ss.getContextClassLoader();
   283         ClassLoader cl = ss.getContextClassLoader();
       
   284         boolean useBSClsLoader = false;
   247         if (cl != null) {
   285         if (cl != null) {
   248             is = ss.getResourceAsStream(cl, serviceId);
   286             is = ss.getResourceAsStream(cl, serviceId);
   249 
   287 
   250             // If no provider found then try the current ClassLoader
   288             // If no provider found then try the current ClassLoader
   251             if (is == null) {
   289             if (is == null) {
   252                 cl = FactoryFinder.class.getClassLoader();
   290                 cl = FactoryFinder.class.getClassLoader();
   253                 is = ss.getResourceAsStream(cl, serviceId);
   291                 is = ss.getResourceAsStream(cl, serviceId);
       
   292                 useBSClsLoader = true;
   254             }
   293             }
   255         } else {
   294         } else {
   256             // No Context ClassLoader, try the current ClassLoader
   295             // No Context ClassLoader, try the current ClassLoader
   257             cl = FactoryFinder.class.getClassLoader();
   296             cl = FactoryFinder.class.getClassLoader();
   258             is = ss.getResourceAsStream(cl, serviceId);
   297             is = ss.getResourceAsStream(cl, serviceId);
       
   298             useBSClsLoader = true;
   259         }
   299         }
   260 
   300 
   261         if (is == null) {
   301         if (is == null) {
   262             // No provider found
   302             // No provider found
   263             return null;
   303             return null;
   291 
   331 
   292             // Note: here we do not want to fall back to the current
   332             // Note: here we do not want to fall back to the current
   293             // ClassLoader because we want to avoid the case where the
   333             // ClassLoader because we want to avoid the case where the
   294             // resource file was found using one ClassLoader and the
   334             // resource file was found using one ClassLoader and the
   295             // provider class was instantiated using a different one.
   335             // provider class was instantiated using a different one.
   296             return newInstance(factoryClassName, cl, false);
   336             return newInstance(factoryClassName, cl, false, useBSClsLoader);
   297         }
   337         }
   298 
   338 
   299         // No provider found
   339         // No provider found
   300         return null;
   340         return null;
   301     }
   341     }