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