1
2
3
4
5
6
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
111 try { className = System.getProperty (property); }
112 catch (RuntimeException e) {
113
114
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
137 if (className == null) {
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176 public static XMLReader createXMLReader (String className)
177 throws SAXException
178 {
179 return loadClass (NewInstance.getClassLoader (), className);
180 }
181
182 private static XMLReader loadClass (ClassLoader loader, String className)
183 throws SAXException
184 {
185 try {
186 return (XMLReader) NewInstance.newInstance (loader, className);
187 } catch (ClassNotFoundException e1) {
188 throw new SAXException("SAX2 driver class " + className +
189 " not found", e1);
190 } catch (IllegalAccessException e2) {
191 throw new SAXException("SAX2 driver class " + className +
192 " found but cannot be loaded", e2);
193 } catch (InstantiationException e3) {
194 throw new SAXException("SAX2 driver class " + className +
195 " loaded but cannot be instantiated (no empty public constructor?)",
196 e3);
197 } catch (ClassCastException e4) {
198 throw new SAXException("SAX2 driver class " + className +
199 " does not implement XMLReader", e4);
200 }
201 }
202 }