Home » xml-commons-external-1.4.01-src » org.xml » sax » helpers » [javadoc | source]

    1   // XMLReaderFactory.java - factory for creating a new reader.
    2   // http://www.saxproject.org
    3   // Written by David Megginson
    4   // and by David Brownell
    5   // NO WARRANTY!  This class is in the Public Domain.
    6   // $Id: XMLReaderFactory.java 670295 2008-06-22 01:46:43Z mrglavas $
    7   
    8   package org.xml.sax.helpers;
    9   import java.io.BufferedReader;
   10   import java.io.IOException;
   11   import java.io.InputStream;
   12   import java.io.InputStreamReader;
   13   import org.xml.sax.XMLReader;
   14   import org.xml.sax.SAXException;
   15   
   16   
   17   /**
   18    * Factory for creating an XML reader.
   19    *
   20    * <blockquote>
   21    * <em>This module, both source code and documentation, is in the
   22    * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
   23    * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
   24    * for further information.
   25    * </blockquote>
   26    *
   27    * <p>This class contains static methods for creating an XML reader
   28    * from an explicit class name, or based on runtime defaults:</p>
   29    *
   30    * <pre>
   31    * try {
   32    *   XMLReader myReader = XMLReaderFactory.createXMLReader();
   33    * } catch (SAXException e) {
   34    *   System.err.println(e.getMessage());
   35    * }
   36    * </pre>
   37    *
   38    * <p><strong>Note to Distributions bundled with parsers:</strong>
   39    * You should modify the implementation of the no-arguments
   40    * <em>createXMLReader</em> to handle cases where the external
   41    * configuration mechanisms aren't set up.  That method should do its
   42    * best to return a parser when one is in the class path, even when
   43    * nothing bound its class name to <code>org.xml.sax.driver</code> so
   44    * those configuration mechanisms would see it.</p>
   45    *
   46    * @since SAX 2.0
   47    * @author David Megginson, David Brownell
   48    * @version 2.0.1 (sax2r2)
   49    */
   50   final public class XMLReaderFactory
   51   {
   52       /**
   53        * Private constructor.
   54        *
   55        * <p>This constructor prevents the class from being instantiated.</p>
   56        */
   57       private XMLReaderFactory ()
   58       {
   59       }
   60       
   61       private static final String property = "org.xml.sax.driver";
   62       
   63       /**
   64        * Default columns per line.
   65        */
   66       private static final int DEFAULT_LINE_LENGTH = 80;
   67       
   68       /**
   69        * Attempt to create an XMLReader from system defaults.
   70        * In environments which can support it, the name of the XMLReader
   71        * class is determined by trying each these options in order, and
   72        * using the first one which succeeds:</p> <ul>
   73        *
   74        * <li>If the system property <code>org.xml.sax.driver</code>
   75        * has a value, that is used as an XMLReader class name. </li>
   76        *
   77        * <li>The JAR "Services API" is used to look for a class name
   78        * in the <em>META-INF/services/org.xml.sax.driver</em> file in
   79        * jarfiles available to the runtime.</li>
   80        *
   81        * <li> SAX parser distributions are strongly encouraged to provide
   82        * a default XMLReader class name that will take effect only when
   83        * previous options (on this list) are not successful.</li>
   84        *
   85        * <li>Finally, if {@link ParserFactory#makeParser()} can
   86        * return a system default SAX1 parser, that parser is wrapped in
   87        * a {@link ParserAdapter}.  (This is a migration aid for SAX1
   88        * environments, where the <code>org.xml.sax.parser</code> system
   89        * property will often be usable.) </li>
   90        *
   91        * </ul>
   92        *
   93        * <p> In environments such as small embedded systems, which can not
   94        * support that flexibility, other mechanisms to determine the default
   95        * may be used. </p>
   96        *
   97        * <p>Note that many Java environments allow system properties to be
   98        * initialized on a command line.  This means that <em>in most cases</em>
   99        * setting a good value for that property ensures that calls to this
  100        * method will succeed, except when security policies intervene.
  101        * This will also maximize application portability to older SAX
  102        * environments, with less robust implementations of this method.
  103        * </p>
  104        *
  105        * @return A new XMLReader.
  106        * @exception org.xml.sax.SAXException If no default XMLReader class
  107        *            can be identified and instantiated.
  108        * @see #createXMLReader(java.lang.String)
  109        */
  110       public static XMLReader createXMLReader ()
  111       throws SAXException
  112       {
  113           String		className = null;
  114           ClassLoader	loader = NewInstance.getClassLoader ();
  115           
  116           // 1. try the JVM-instance-wide system property
  117           try { className = SecuritySupport.getSystemProperty (property); }
  118           catch (Exception e) { /* normally fails for applets */ }
  119           
  120           // 2. if that fails, try META-INF/services/
  121           if (className == null || className.length() == 0) {
  122               String      service = "META-INF/services/" + property;
  123               
  124               InputStream is = null;
  125               className = null;
  126               
  127               // First try the Context ClassLoader
  128               ClassLoader cl = SecuritySupport.getContextClassLoader();
  129               if (cl != null) {
  130                   is = SecuritySupport.getResourceAsStream(cl, service);
  131                   
  132                   // If no provider found then try the current ClassLoader
  133                   if (is == null) {
  134                       cl = XMLReaderFactory.class.getClassLoader();
  135                       is = SecuritySupport.getResourceAsStream(cl, service);
  136                   }
  137               } else {
  138                   // No Context ClassLoader or JDK 1.1 so try the current
  139                   // ClassLoader
  140                   cl = XMLReaderFactory.class.getClassLoader();
  141                   is = SecuritySupport.getResourceAsStream(cl, service);
  142               }
  143               
  144               if (is != null) {
  145                   
  146                   // Read the service provider name in UTF-8 as specified in
  147                   // the jar spec.  Unfortunately this fails in Microsoft
  148                   // VJ++, which does not implement the UTF-8
  149                   // encoding. Theoretically, we should simply let it fail in
  150                   // that case, since the JVM is obviously broken if it
  151                   // doesn't support such a basic standard.  But since there
  152                   // are still some users attempting to use VJ++ for
  153                   // development, we have dropped in a fallback which makes a
  154                   // second attempt using the platform's default encoding. In
  155                   // VJ++ this is apparently ASCII, which is a subset of
  156                   // UTF-8... and since the strings we'll be reading here are
  157                   // also primarily limited to the 7-bit ASCII range (at
  158                   // least, in English versions), this should work well
  159                   // enough to keep us on the air until we're ready to
  160                   // officially decommit from VJ++. [Edited comment from
  161                   // jkesselm]
  162                   BufferedReader rd;
  163                   try {
  164                       rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
  165                   } catch (java.io.UnsupportedEncodingException e) {
  166                       rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
  167                   }
  168                   
  169                   try {
  170                       // XXX Does not handle all possible input as specified by the
  171                       // Jar Service Provider specification
  172                       className = rd.readLine();
  173                   } 
  174                   catch (Exception x) {
  175                       // No provider found
  176                   } 
  177                   finally {
  178                       try { 
  179                           // try to close the reader. 
  180                           rd.close(); 
  181                       } 
  182                       // Ignore the exception. 
  183                       catch (IOException exc) {}
  184                   }
  185               }
  186           }
  187           
  188           // 3. Distro-specific fallback
  189           if (className == null) {
  190               // BEGIN DISTRIBUTION-SPECIFIC
  191               
  192               // EXAMPLE:
  193               // className = "com.example.sax.XmlReader";
  194               // or a $JAVA_HOME/jre/lib/*properties setting...
  195               className = "org.apache.xerces.parsers.SAXParser";
  196               
  197               // END DISTRIBUTION-SPECIFIC
  198           }
  199           
  200           // do we know the XMLReader implementation class yet?
  201           if (className != null)
  202               return loadClass (loader, className);
  203           
  204           // 4. panic -- adapt any SAX1 parser
  205           try {
  206               return new ParserAdapter (ParserFactory.makeParser ());
  207           } catch (Exception e) {
  208               throw new SAXException ("Can't create default XMLReader; "
  209                       + "is system property org.xml.sax.driver set?");
  210           }
  211       }
  212       
  213       
  214       /**
  215        * Attempt to create an XML reader from a class name.
  216        *
  217        * <p>Given a class name, this method attempts to load
  218        * and instantiate the class as an XML reader.</p>
  219        *
  220        * <p>Note that this method will not be usable in environments where
  221        * the caller (perhaps an applet) is not permitted to load classes
  222        * dynamically.</p>
  223        *
  224        * @return A new XML reader.
  225        * @exception org.xml.sax.SAXException If the class cannot be
  226        *            loaded, instantiated, and cast to XMLReader.
  227        * @see #createXMLReader()
  228        */
  229       public static XMLReader createXMLReader (String className)
  230       throws SAXException
  231       {
  232           return loadClass (NewInstance.getClassLoader (), className);
  233       }
  234       
  235       private static XMLReader loadClass (ClassLoader loader, String className)
  236       throws SAXException
  237       {
  238           try {
  239               return (XMLReader) NewInstance.newInstance (loader, className);
  240           } catch (ClassNotFoundException e1) {
  241               throw new SAXException("SAX2 driver class " + className +
  242                       " not found", e1);
  243           } catch (IllegalAccessException e2) {
  244               throw new SAXException("SAX2 driver class " + className +
  245                       " found but cannot be loaded", e2);
  246           } catch (InstantiationException e3) {
  247               throw new SAXException("SAX2 driver class " + className +
  248                       " loaded but cannot be instantiated (no empty public constructor?)",
  249                       e3);
  250           } catch (ClassCastException e4) {
  251               throw new SAXException("SAX2 driver class " + className +
  252                       " does not implement XMLReader", e4);
  253           }
  254       }
  255   }

Home » xml-commons-external-1.4.01-src » org.xml » sax » helpers » [javadoc | source]