Save This Page
Home » openjdk-7 » javax » xml » parsers » [javadoc | source]
    1   /*
    2    * Copyright 2003-2006 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package javax.xml.parsers;
   27   
   28   import java.io.File;
   29   import java.io.FileInputStream;
   30   
   31   import java.util.Properties;
   32   import java.io.BufferedReader;
   33   import java.io.IOException;
   34   import java.io.InputStream;
   35   import java.io.InputStreamReader;
   36   import java.net.URL;
   37   
   38   /**
   39    * <p>Implements pluggable Datatypes.</p>
   40    *
   41    * <p>This class is duplicated for each JAXP subpackage so keep it in
   42    * sync.  It is package private for secure class loading.</p>
   43    *
   44    * @author Santiago.PericasGeertsen@sun.com
   45    */
   46   class FactoryFinder {
   47   
   48       /**
   49        * Internal debug flag.
   50        */
   51       private static boolean debug = false;
   52   
   53       /**
   54        * Cache for properties in java.home/lib/jaxp.properties
   55        */
   56       static Properties cacheProps = new Properties();
   57   
   58       /**
   59        * Flag indicating if properties from java.home/lib/jaxp.properties
   60        * have been cached.
   61        */
   62       static boolean firstTime = true;
   63   
   64       /**
   65        * Security support class use to check access control before
   66        * getting certain system resources.
   67        */
   68       static SecuritySupport ss = new SecuritySupport();
   69   
   70       // Define system property "jaxp.debug" to get output
   71       static {
   72           // Use try/catch block to support applets, which throws
   73           // SecurityException out of this code.
   74           try {
   75               String val = ss.getSystemProperty("jaxp.debug");
   76               // Allow simply setting the prop to turn on debug
   77               debug = val != null && !"false".equals(val);
   78           }
   79           catch (SecurityException se) {
   80               debug = false;
   81           }
   82       }
   83   
   84       private static void dPrint(String msg) {
   85           if (debug) {
   86               System.err.println("JAXP: " + msg);
   87           }
   88       }
   89   
   90       /**
   91        * Attempt to load a class using the class loader supplied. If that fails
   92        * and fall back is enabled, the current (i.e. bootstrap) class loader is
   93        * tried.
   94        *
   95        * 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        * loader.
   98        */
   99       static private Class getProviderClass(String className, ClassLoader cl,
  100               boolean doFallback) throws ClassNotFoundException
  101       {
  102           try {
  103               if (cl == null) {
  104                   cl = ss.getContextClassLoader();
  105                   if (cl == null) {
  106                       throw new ClassNotFoundException();
  107                   }
  108                   else {
  109                       return cl.loadClass(className);
  110                   }
  111               }
  112               else {
  113                   return cl.loadClass(className);
  114               }
  115           }
  116           catch (ClassNotFoundException e1) {
  117               if (doFallback) {
  118                   // Use current class loader - should always be bootstrap CL
  119                   return Class.forName(className, true, FactoryFinder.class.getClassLoader());
  120               }
  121               else {
  122                   throw e1;
  123               }
  124           }
  125       }
  126   
  127       /**
  128        * Create an instance of a class. Delegates to method
  129        * <code>getProviderClass()</code> in order to load the class.
  130        *
  131        * @param className Name of the concrete class corresponding to the
  132        * service provider
  133        *
  134        * @param cl ClassLoader to use to load the class, null means to use
  135        * the bootstrap ClassLoader
  136        *
  137        * @param doFallback True if the current ClassLoader should be tried as
  138        * a fallback if the class is not found using cl
  139        */
  140       static Object newInstance(String className, ClassLoader cl, boolean doFallback)
  141           throws ConfigurationError
  142       {
  143           try {
  144               Class providerClass = getProviderClass(className, cl, doFallback);
  145               Object instance = providerClass.newInstance();
  146               if (debug) {    // Extra check to avoid computing cl strings
  147                   dPrint("created new instance of " + providerClass +
  148                          " using ClassLoader: " + cl);
  149               }
  150               return instance;
  151           }
  152           catch (ClassNotFoundException x) {
  153               throw new ConfigurationError(
  154                   "Provider " + className + " not found", x);
  155           }
  156           catch (Exception x) {
  157               throw new ConfigurationError(
  158                   "Provider " + className + " could not be instantiated: " + x,
  159                   x);
  160           }
  161       }
  162   
  163       /**
  164        * Finds the implementation Class object in the specified order.  Main
  165        * entry point.
  166        * @return Class object of factory, never null
  167        *
  168        * @param factoryId             Name of the factory to find, same as
  169        *                              a property name
  170        * @param fallbackClassName     Implementation class name, if nothing else
  171        *                              is found.  Use null to mean no fallback.
  172        *
  173        * Package private so this code can be shared.
  174        */
  175       static Object find(String factoryId, String fallbackClassName)
  176           throws ConfigurationError
  177       {
  178           dPrint("find factoryId =" + factoryId);
  179   
  180           // Use the system property first
  181           try {
  182               String systemProp = ss.getSystemProperty(factoryId);
  183               if (systemProp != null) {
  184                   dPrint("found system property, value=" + systemProp);
  185                   return newInstance(systemProp, null, true);
  186               }
  187           }
  188           catch (SecurityException se) {
  189               if (debug) se.printStackTrace();
  190           }
  191   
  192           // try to read from $java.home/lib/jaxp.properties
  193           try {
  194               String factoryClassName = null;
  195               if (firstTime) {
  196                   synchronized (cacheProps) {
  197                       if (firstTime) {
  198                           String configFile = ss.getSystemProperty("java.home") + File.separator +
  199                               "lib" + File.separator + "jaxp.properties";
  200                           File f = new File(configFile);
  201                           firstTime = false;
  202                           if (ss.doesFileExist(f)) {
  203                               dPrint("Read properties file "+f);
  204                               cacheProps.load(ss.getFileInputStream(f));
  205                           }
  206                       }
  207                   }
  208               }
  209               factoryClassName = cacheProps.getProperty(factoryId);
  210   
  211               if (factoryClassName != null) {
  212                   dPrint("found in $java.home/jaxp.properties, value=" + factoryClassName);
  213                   return newInstance(factoryClassName, null, true);
  214               }
  215           }
  216           catch (Exception ex) {
  217               if (debug) ex.printStackTrace();
  218           }
  219   
  220           // Try Jar Service Provider Mechanism
  221           Object provider = findJarServiceProvider(factoryId);
  222           if (provider != null) {
  223               return provider;
  224           }
  225           if (fallbackClassName == null) {
  226               throw new ConfigurationError(
  227                   "Provider for " + factoryId + " cannot be found", null);
  228           }
  229   
  230           dPrint("loaded from fallback value: " + fallbackClassName);
  231           return newInstance(fallbackClassName, null, true);
  232       }
  233   
  234       /*
  235        * Try to find provider using Jar Service Provider Mechanism
  236        *
  237        * @return instance of provider class if found or null
  238        */
  239       private static Object findJarServiceProvider(String factoryId)
  240           throws ConfigurationError
  241       {
  242           String serviceId = "META-INF/services/" + factoryId;
  243           InputStream is = null;
  244   
  245           // First try the Context ClassLoader
  246           ClassLoader cl = ss.getContextClassLoader();
  247           if (cl != null) {
  248               is = ss.getResourceAsStream(cl, serviceId);
  249   
  250               // If no provider found then try the current ClassLoader
  251               if (is == null) {
  252                   cl = FactoryFinder.class.getClassLoader();
  253                   is = ss.getResourceAsStream(cl, serviceId);
  254               }
  255           } else {
  256               // No Context ClassLoader, try the current ClassLoader
  257               cl = FactoryFinder.class.getClassLoader();
  258               is = ss.getResourceAsStream(cl, serviceId);
  259           }
  260   
  261           if (is == null) {
  262               // No provider found
  263               return null;
  264           }
  265   
  266           if (debug) {    // Extra check to avoid computing cl strings
  267               dPrint("found jar resource=" + serviceId + " using ClassLoader: " + cl);
  268           }
  269   
  270           BufferedReader rd;
  271           try {
  272               rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
  273           }
  274           catch (java.io.UnsupportedEncodingException e) {
  275               rd = new BufferedReader(new InputStreamReader(is));
  276           }
  277   
  278           String factoryClassName = null;
  279           try {
  280               // XXX Does not handle all possible input as specified by the
  281               // Jar Service Provider specification
  282               factoryClassName = rd.readLine();
  283               rd.close();
  284           } catch (IOException x) {
  285               // No provider found
  286               return null;
  287           }
  288   
  289           if (factoryClassName != null && !"".equals(factoryClassName)) {
  290               dPrint("found in resource, value=" + factoryClassName);
  291   
  292               // Note: here we do not want to fall back to the current
  293               // ClassLoader because we want to avoid the case where the
  294               // resource file was found using one ClassLoader and the
  295               // provider class was instantiated using a different one.
  296               return newInstance(factoryClassName, cl, false);
  297           }
  298   
  299           // No provider found
  300           return null;
  301       }
  302   
  303       static class ConfigurationError extends Error {
  304           private Exception exception;
  305   
  306           /**
  307            * Construct a new instance with the specified detail string and
  308            * exception.
  309            */
  310           ConfigurationError(String msg, Exception x) {
  311               super(msg);
  312               this.exception = x;
  313           }
  314   
  315           Exception getException() {
  316               return exception;
  317           }
  318       }
  319   
  320   }

Save This Page
Home » openjdk-7 » javax » xml » parsers » [javadoc | source]