Source for org.xml.sax.helpers.XMLReaderFactory

   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,v 1.1 2004/12/23 22:38:42 mark Exp $
   7: 
   8: package org.xml.sax.helpers;
   9: import java.io.BufferedReader;
  10: import java.io.InputStream;
  11: import java.io.InputStreamReader;
  12: import org.xml.sax.XMLReader;
  13: import org.xml.sax.SAXException;
  14: 
  15: 
  16: /**
  17:  * Factory for creating an XML reader.
  18:  *
  19:  * <blockquote>
  20:  * <em>This module, both source code and documentation, is in the
  21:  * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
  22:  * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
  23:  * for further information.
  24:  * </blockquote>
  25:  *
  26:  * <p>This class contains static methods for creating an XML reader
  27:  * from an explicit class name, or based on runtime defaults:</p>
  28:  *
  29:  * <pre>
  30:  * try {
  31:  *   XMLReader myReader = XMLReaderFactory.createXMLReader();
  32:  * } catch (SAXException e) {
  33:  *   System.err.println(e.getMessage());
  34:  * }
  35:  * </pre>
  36:  *
  37:  * <p><strong>Note to Distributions bundled with parsers:</strong>
  38:  * You should modify the implementation of the no-arguments
  39:  * <em>createXMLReader</em> to handle cases where the external
  40:  * configuration mechanisms aren't set up.  That method should do its
  41:  * best to return a parser when one is in the class path, even when
  42:  * nothing bound its class name to <code>org.xml.sax.driver</code> so
  43:  * those configuration mechanisms would see it.</p>
  44:  *
  45:  * @since SAX 2.0
  46:  * @author David Megginson, David Brownell
  47:  * @version 2.0.1 (sax2r2)
  48:  */
  49: final public class XMLReaderFactory
  50: {
  51:     /**
  52:      * Private constructor.
  53:      *
  54:      * <p>This constructor prevents the class from being instantiated.</p>
  55:      */
  56:     private XMLReaderFactory ()
  57:     {
  58:     }
  59: 
  60:     private static final String property = "org.xml.sax.driver";
  61: 
  62:     /**
  63:      * Attempt to create an XMLReader from system defaults.
  64:      * In environments which can support it, the name of the XMLReader
  65:      * class is determined by trying each these options in order, and
  66:      * using the first one which succeeds:</p> <ul>
  67:      *
  68:      * <li>If the system property <code>org.xml.sax.driver</code>
  69:      * has a value, that is used as an XMLReader class name. </li>
  70:      *
  71:      * <li>The JAR "Services API" is used to look for a class name
  72:      * in the <em>META-INF/services/org.xml.sax.driver</em> file in
  73:      * jarfiles available to the runtime.</li>
  74:      *
  75:      * <li> SAX parser distributions are strongly encouraged to provide
  76:      * a default XMLReader class name that will take effect only when
  77:      * previous options (on this list) are not successful.</li>
  78:      *
  79:      * <li>Finally, if {@link ParserFactory#makeParser()} can
  80:      * return a system default SAX1 parser, that parser is wrapped in
  81:      * a {@link ParserAdapter}.  (This is a migration aid for SAX1
  82:      * environments, where the <code>org.xml.sax.parser</code> system
  83:      * property will often be usable.) </li>
  84:      *
  85:      * </ul>
  86:      *
  87:      * <p> In environments such as small embedded systems, which can not
  88:      * support that flexibility, other mechanisms to determine the default
  89:      * may be used. </p>
  90:      *
  91:      * <p>Note that many Java environments allow system properties to be
  92:      * initialized on a command line.  This means that <em>in most cases</em>
  93:      * setting a good value for that property ensures that calls to this
  94:      * method will succeed, except when security policies intervene.
  95:      * This will also maximize application portability to older SAX
  96:      * environments, with less robust implementations of this method.
  97:      * </p>
  98:      *
  99:      * @return A new XMLReader.
 100:      * @exception org.xml.sax.SAXException If no default XMLReader class
 101:      *            can be identified and instantiated.
 102:      * @see #createXMLReader(java.lang.String)
 103:      */
 104:     public static XMLReader createXMLReader ()
 105:     throws SAXException
 106:     {
 107:     String        className = null;
 108:     ClassLoader    loader = NewInstance.getClassLoader ();
 109:     
 110:     // 1. try the JVM-instance-wide system property
 111:     try { className = System.getProperty (property); }
 112:     catch (RuntimeException e) { /* normally fails for applets */ }
 113: 
 114:     // 2. if that fails, try META-INF/services/
 115:     if (className == null) {
 116:         try {
 117:         String        service = "META-INF/services/" + property;
 118:         InputStream    in;
 119:         BufferedReader    reader;
 120: 
 121:         if (loader == null)
 122:             in = ClassLoader.getSystemResourceAsStream (service);
 123:         else
 124:             in = loader.getResourceAsStream (service);
 125: 
 126:         if (in != null) {
 127:             reader = new BufferedReader (
 128:                 new InputStreamReader (in, "UTF8"));
 129:             className = reader.readLine ();
 130:             in.close ();
 131:         }
 132:         } catch (Exception e) {
 133:         }
 134:     }
 135: 
 136:     // 3. Distro-specific fallback
 137:     if (className == null) {
 138: // BEGIN DISTRIBUTION-SPECIFIC
 139: 
 140:         // CLASSPATH LOCAL: have to code in the backup.
 141:         // Among other things, see PR 31303, and this thread:
 142:         // http://gcc.gnu.org/ml/java-patches/2007-q1/msg00661.html
 143:         className = "gnu.xml.stream.SAXParser";
 144: 
 145:         // EXAMPLE:
 146:         // className = "com.example.sax.XmlReader";
 147:         // or a $JAVA_HOME/jre/lib/*properties setting...
 148: 
 149: // END DISTRIBUTION-SPECIFIC
 150:     }
 151:     
 152:     // do we know the XMLReader implementation class yet?
 153:     if (className != null)
 154:         return loadClass (loader, className);
 155: 
 156:     // 4. panic -- adapt any SAX1 parser
 157:     try {
 158:         return new ParserAdapter (ParserFactory.makeParser ());
 159:     } catch (Exception e) {
 160:         throw new SAXException ("Can't create default XMLReader; "
 161:             + "is system property org.xml.sax.driver set?");
 162:     }
 163:     }
 164: 
 165: 
 166:     /**
 167:      * Attempt to create an XML reader from a class name.
 168:      *
 169:      * <p>Given a class name, this method attempts to load
 170:      * and instantiate the class as an XML reader.</p>
 171:      *
 172:      * <p>Note that this method will not be usable in environments where
 173:      * the caller (perhaps an applet) is not permitted to load classes
 174:      * dynamically.</p>
 175:      *
 176:      * @return A new XML reader.
 177:      * @exception org.xml.sax.SAXException If the class cannot be
 178:      *            loaded, instantiated, and cast to XMLReader.
 179:      * @see #createXMLReader()
 180:      */
 181:     public static XMLReader createXMLReader (String className)
 182:     throws SAXException
 183:     {
 184:     return loadClass (NewInstance.getClassLoader (), className);
 185:     }
 186: 
 187:     private static XMLReader loadClass (ClassLoader loader, String className)
 188:     throws SAXException
 189:     {
 190:     try {
 191:         return (XMLReader) NewInstance.newInstance (loader, className);
 192:     } catch (ClassNotFoundException e1) {
 193:         throw new SAXException("SAX2 driver class " + className +
 194:                    " not found", e1);
 195:     } catch (IllegalAccessException e2) {
 196:         throw new SAXException("SAX2 driver class " + className +
 197:                    " found but cannot be loaded", e2);
 198:     } catch (InstantiationException e3) {
 199:         throw new SAXException("SAX2 driver class " + className +
 200:        " loaded but cannot be instantiated (no empty public constructor?)",
 201:                    e3);
 202:     } catch (ClassCastException e4) {
 203:         throw new SAXException("SAX2 driver class " + className +
 204:                    " does not implement XMLReader", e4);
 205:     }
 206:     }
 207: }