jaxp/src/javax/xml/stream/FactoryFinder.java
changeset 16953 a44e04deb948
parent 12458 d601e4bba306
child 17264 3aff554ad461
equal deleted inserted replaced
16416:bcebd3fdefc9 16953:a44e04deb948
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package javax.xml.stream;
    26 package javax.xml.stream;
    27 
    27 
       
    28 import java.io.BufferedReader;
       
    29 import java.io.File;
       
    30 import java.io.IOException;
    28 import java.io.InputStream;
    31 import java.io.InputStream;
    29 import java.io.IOException;
    32 import java.io.InputStreamReader;
    30 import java.io.File;
       
    31 import java.io.FileInputStream;
       
    32 
       
    33 import java.util.Properties;
    33 import java.util.Properties;
    34 import java.io.BufferedReader;
       
    35 import java.io.InputStreamReader;
       
    36 
    34 
    37 /**
    35 /**
    38  * <p>Implements pluggable Datatypes.</p>
    36  * <p>Implements pluggable Datatypes.</p>
    39  *
    37  *
    40  * <p>This class is duplicated for each JAXP subpackage so keep it in
    38  * <p>This class is duplicated for each JAXP subpackage so keep it in
    41  * sync.  It is package private for secure class loading.</p>
    39  * sync.  It is package private for secure class loading.</p>
    42  *
    40  *
    43  * @author Santiago.PericasGeertsen@sun.com
    41  * @author Santiago.PericasGeertsen@sun.com
    44  */
    42  */
    45 class FactoryFinder {
    43 class FactoryFinder {
       
    44     // Check we have access to package.
       
    45     private static final String DEFAULT_PACKAGE = "com.sun.xml.internal.";
    46 
    46 
    47     /**
    47     /**
    48      * Internal debug flag.
    48      * Internal debug flag.
    49      */
    49      */
    50     private static boolean debug = false;
    50     private static boolean debug = false;
    92      * tried.
    92      * tried.
    93      *
    93      *
    94      * If the class loader supplied is <code>null</code>, first try using the
    94      * If the class loader supplied is <code>null</code>, first try using the
    95      * context class loader followed by the current (i.e. bootstrap) class
    95      * context class loader followed by the current (i.e. bootstrap) class
    96      * loader.
    96      * loader.
       
    97      *
       
    98      * Use bootstrap classLoader if cl = null and useBSClsLoader is true
    97      */
    99      */
    98     static private Class getProviderClass(String className, ClassLoader cl,
   100     static private Class getProviderClass(String className, ClassLoader cl,
    99             boolean doFallback) throws ClassNotFoundException
   101             boolean doFallback, boolean useBSClsLoader) throws ClassNotFoundException
   100     {
   102     {
   101         try {
   103         try {
   102             if (cl == null) {
   104             if (cl == null) {
   103                 cl = ss.getContextClassLoader();
   105                 if (useBSClsLoader) {
   104                 if (cl == null) {
   106                     return Class.forName(className, true, FactoryFinder.class.getClassLoader());
   105                     throw new ClassNotFoundException();
   107                 } else {
   106                 }
   108                     cl = ss.getContextClassLoader();
   107                 else {
   109                     if (cl == null) {
   108                     return cl.loadClass(className);
   110                         throw new ClassNotFoundException();
       
   111                     }
       
   112                     else {
       
   113                         return cl.loadClass(className);
       
   114                     }
   109                 }
   115                 }
   110             }
   116             }
   111             else {
   117             else {
   112                 return cl.loadClass(className);
   118                 return cl.loadClass(className);
   113             }
   119             }
   128      * <code>getProviderClass()</code> in order to load the class.
   134      * <code>getProviderClass()</code> in order to load the class.
   129      *
   135      *
   130      * @param className Name of the concrete class corresponding to the
   136      * @param className Name of the concrete class corresponding to the
   131      * service provider
   137      * service provider
   132      *
   138      *
   133      * @param cl ClassLoader to use to load the class, null means to use
   139      * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
   134      * the bootstrap ClassLoader
   140      * current <code>Thread</code>'s context classLoader is used to load the factory class.
   135      *
   141      *
   136      * @param doFallback True if the current ClassLoader should be tried as
   142      * @param doFallback True if the current ClassLoader should be tried as
   137      * a fallback if the class is not found using cl
   143      * a fallback if the class is not found using cl
   138      */
   144      */
   139     static Object newInstance(String className, ClassLoader cl, boolean doFallback)
   145     static Object newInstance(String className, ClassLoader cl, boolean doFallback)
   140         throws ConfigurationError
   146         throws ConfigurationError
   141     {
   147     {
   142         try {
   148         return newInstance(className, cl, doFallback, false);
   143             Class providerClass = getProviderClass(className, cl, doFallback);
   149     }
       
   150 
       
   151     /**
       
   152      * Create an instance of a class. Delegates to method
       
   153      * <code>getProviderClass()</code> in order to load the class.
       
   154      *
       
   155      * @param className Name of the concrete class corresponding to the
       
   156      * service provider
       
   157      *
       
   158      * @param cl <code>ClassLoader</code> used to load the factory class. If <code>null</code>
       
   159      * current <code>Thread</code>'s context classLoader is used to load the factory class.
       
   160      *
       
   161      * @param doFallback True if the current ClassLoader should be tried as
       
   162      * a fallback if the class is not found using cl
       
   163      *
       
   164      * @param useBSClsLoader True if cl=null actually meant bootstrap classLoader. This parameter
       
   165      * is needed since DocumentBuilderFactory/SAXParserFactory defined null as context classLoader.
       
   166      */
       
   167     static Object newInstance(String className, ClassLoader cl, boolean doFallback, boolean useBSClsLoader)
       
   168         throws ConfigurationError
       
   169     {
       
   170         // make sure we have access to restricted packages
       
   171         if (System.getSecurityManager() != null) {
       
   172             if (className != null && className.startsWith(DEFAULT_PACKAGE)) {
       
   173                 cl = null;
       
   174                 useBSClsLoader = true;
       
   175             }
       
   176         }
       
   177 
       
   178         try {
       
   179             Class providerClass = getProviderClass(className, cl, doFallback, useBSClsLoader);
   144             Object instance = providerClass.newInstance();
   180             Object instance = providerClass.newInstance();
   145             if (debug) {    // Extra check to avoid computing cl strings
   181             if (debug) {    // Extra check to avoid computing cl strings
   146                 dPrint("created new instance of " + providerClass +
   182                 dPrint("created new instance of " + providerClass +
   147                        " using ClassLoader: " + cl);
   183                        " using ClassLoader: " + cl);
   148             }
   184             }
   231                                 "lib" + File.separator + "jaxp.properties";
   267                                 "lib" + File.separator + "jaxp.properties";
   232                             f = new File(configFile);
   268                             f = new File(configFile);
   233                             if (ss.doesFileExist(f)) {
   269                             if (ss.doesFileExist(f)) {
   234                                 dPrint("Read properties file "+f);
   270                                 dPrint("Read properties file "+f);
   235                                 cacheProps.load(ss.getFileInputStream(f));
   271                                 cacheProps.load(ss.getFileInputStream(f));
   236                             }
       
   237                         }
       
   238                     }
   272                     }
       
   273                 }
       
   274             }
   239                 }
   275                 }
   240             }
   276             }
   241             factoryClassName = cacheProps.getProperty(factoryId);
   277             factoryClassName = cacheProps.getProperty(factoryId);
   242 
   278 
   243             if (factoryClassName != null) {
   279             if (factoryClassName != null) {
   274         String serviceId = "META-INF/services/" + factoryId;
   310         String serviceId = "META-INF/services/" + factoryId;
   275         InputStream is = null;
   311         InputStream is = null;
   276 
   312 
   277         // First try the Context ClassLoader
   313         // First try the Context ClassLoader
   278         ClassLoader cl = ss.getContextClassLoader();
   314         ClassLoader cl = ss.getContextClassLoader();
       
   315         boolean useBSClsLoader = false;
   279         if (cl != null) {
   316         if (cl != null) {
   280             is = ss.getResourceAsStream(cl, serviceId);
   317             is = ss.getResourceAsStream(cl, serviceId);
   281 
   318 
   282             // If no provider found then try the current ClassLoader
   319             // If no provider found then try the current ClassLoader
   283             if (is == null) {
   320             if (is == null) {
   284                 cl = FactoryFinder.class.getClassLoader();
   321                 cl = FactoryFinder.class.getClassLoader();
   285                 is = ss.getResourceAsStream(cl, serviceId);
   322                 is = ss.getResourceAsStream(cl, serviceId);
       
   323                 useBSClsLoader = true;
   286             }
   324             }
   287         } else {
   325         } else {
   288             // No Context ClassLoader, try the current ClassLoader
   326             // No Context ClassLoader, try the current ClassLoader
   289             cl = FactoryFinder.class.getClassLoader();
   327             cl = FactoryFinder.class.getClassLoader();
   290             is = ss.getResourceAsStream(cl, serviceId);
   328             is = ss.getResourceAsStream(cl, serviceId);
       
   329             useBSClsLoader = true;
   291         }
   330         }
   292 
   331 
   293         if (is == null) {
   332         if (is == null) {
   294             // No provider found
   333             // No provider found
   295             return null;
   334             return null;
   323 
   362 
   324             // Note: here we do not want to fall back to the current
   363             // Note: here we do not want to fall back to the current
   325             // ClassLoader because we want to avoid the case where the
   364             // ClassLoader because we want to avoid the case where the
   326             // resource file was found using one ClassLoader and the
   365             // resource file was found using one ClassLoader and the
   327             // provider class was instantiated using a different one.
   366             // provider class was instantiated using a different one.
   328             return newInstance(factoryClassName, cl, false);
   367             return newInstance(factoryClassName, cl, false, useBSClsLoader);
   329         }
   368         }
   330 
   369 
   331         // No provider found
   370         // No provider found
   332         return null;
   371         return null;
   333     }
   372     }