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: }