001 /*
002 * Copyright 2000-2005 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 // XMLReaderFactory.java - factory for creating a new reader.
027 // http://www.saxproject.org
028 // Written by David Megginson
029 // and by David Brownell
030 // NO WARRANTY! This class is in the Public Domain.
031 // $Id: XMLReaderFactory.java,v 1.2.2.1 2005/07/31 22:48:08 jeffsuttor Exp $
032 package org.xml.sax.helpers;
033
034 import java.io.BufferedReader;
035 import java.io.InputStream;
036 import java.io.InputStreamReader;
037 import org.xml.sax.XMLReader;
038 import org.xml.sax.SAXException;
039
040 /**
041 * Factory for creating an XML reader.
042 *
043 * <blockquote>
044 * <em>This module, both source code and documentation, is in the
045 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
046 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
047 * for further information.
048 * </blockquote>
049 *
050 * <p>This class contains static methods for creating an XML reader
051 * from an explicit class name, or based on runtime defaults:</p>
052 *
053 * <pre>
054 * try {
055 * XMLReader myReader = XMLReaderFactory.createXMLReader();
056 * } catch (SAXException e) {
057 * System.err.println(e.getMessage());
058 * }
059 * </pre>
060 *
061 * <p><strong>Note to Distributions bundled with parsers:</strong>
062 * You should modify the implementation of the no-arguments
063 * <em>createXMLReader</em> to handle cases where the external
064 * configuration mechanisms aren't set up. That method should do its
065 * best to return a parser when one is in the class path, even when
066 * nothing bound its class name to <code>org.xml.sax.driver</code> so
067 * those configuration mechanisms would see it.</p>
068 *
069 * @since SAX 2.0
070 * @author David Megginson, David Brownell
071 * @version 2.0.1 (sax2r2)
072 */
073 final public class XMLReaderFactory {
074 /**
075 * Private constructor.
076 *
077 * <p>This constructor prevents the class from being instantiated.</p>
078 */
079 private XMLReaderFactory() {
080 }
081
082 private static final String property = "org.xml.sax.driver";
083
084 /**
085 * Attempt to create an XMLReader from system defaults.
086 * In environments which can support it, the name of the XMLReader
087 * class is determined by trying each these options in order, and
088 * using the first one which succeeds:</p> <ul>
089 *
090 * <li>If the system property <code>org.xml.sax.driver</code>
091 * has a value, that is used as an XMLReader class name. </li>
092 *
093 * <li>The JAR "Services API" is used to look for a class name
094 * in the <em>META-INF/services/org.xml.sax.driver</em> file in
095 * jarfiles available to the runtime.</li>
096 *
097 * <li> SAX parser distributions are strongly encouraged to provide
098 * a default XMLReader class name that will take effect only when
099 * previous options (on this list) are not successful.</li>
100 *
101 * <li>Finally, if {@link ParserFactory#makeParser()} can
102 * return a system default SAX1 parser, that parser is wrapped in
103 * a {@link ParserAdapter}. (This is a migration aid for SAX1
104 * environments, where the <code>org.xml.sax.parser</code> system
105 * property will often be usable.) </li>
106 *
107 * </ul>
108 *
109 * <p> In environments such as small embedded systems, which can not
110 * support that flexibility, other mechanisms to determine the default
111 * may be used. </p>
112 *
113 * <p>Note that many Java environments allow system properties to be
114 * initialized on a command line. This means that <em>in most cases</em>
115 * setting a good value for that property ensures that calls to this
116 * method will succeed, except when security policies intervene.
117 * This will also maximize application portability to older SAX
118 * environments, with less robust implementations of this method.
119 * </p>
120 *
121 * @return A new XMLReader.
122 * @exception org.xml.sax.SAXException If no default XMLReader class
123 * can be identified and instantiated.
124 * @see #createXMLReader(java.lang.String)
125 */
126 public static XMLReader createXMLReader() throws SAXException {
127 String className = null;
128 ClassLoader loader = NewInstance.getClassLoader();
129
130 // 1. try the JVM-instance-wide system property
131 try {
132 className = System.getProperty(property);
133 } catch (RuntimeException e) { /* normally fails for applets */
134 }
135
136 // 2. if that fails, try META-INF/services/
137 if (className == null) {
138 try {
139 String service = "META-INF/services/" + property;
140 InputStream in;
141 BufferedReader reader;
142
143 if (loader == null)
144 in = ClassLoader.getSystemResourceAsStream(service);
145 else
146 in = loader.getResourceAsStream(service);
147
148 if (in != null) {
149 reader = new BufferedReader(new InputStreamReader(
150 in, "UTF8"));
151 className = reader.readLine();
152 in.close();
153 }
154 } catch (Exception e) {
155 }
156 }
157
158 // 3. Distro-specific fallback
159 if (className == null) {
160 // BEGIN DISTRIBUTION-SPECIFIC
161
162 // EXAMPLE:
163 // className = "com.example.sax.XmlReader";
164 // or a $JAVA_HOME/jre/lib/*properties setting...
165 className = "com.sun.org.apache.xerces.internal.parsers.SAXParser";
166
167 // END DISTRIBUTION-SPECIFIC
168 }
169
170 // do we know the XMLReader implementation class yet?
171 if (className != null)
172 return loadClass(loader, className);
173
174 // 4. panic -- adapt any SAX1 parser
175 try {
176 return new ParserAdapter(ParserFactory.makeParser());
177 } catch (Exception e) {
178 throw new SAXException("Can't create default XMLReader; "
179 + "is system property org.xml.sax.driver set?");
180 }
181 }
182
183 /**
184 * Attempt to create an XML reader from a class name.
185 *
186 * <p>Given a class name, this method attempts to load
187 * and instantiate the class as an XML reader.</p>
188 *
189 * <p>Note that this method will not be usable in environments where
190 * the caller (perhaps an applet) is not permitted to load classes
191 * dynamically.</p>
192 *
193 * @return A new XML reader.
194 * @exception org.xml.sax.SAXException If the class cannot be
195 * loaded, instantiated, and cast to XMLReader.
196 * @see #createXMLReader()
197 */
198 public static XMLReader createXMLReader(String className)
199 throws SAXException {
200 return loadClass(NewInstance.getClassLoader(), className);
201 }
202
203 private static XMLReader loadClass(ClassLoader loader,
204 String className) throws SAXException {
205 try {
206 return (XMLReader) NewInstance.newInstance(loader,
207 className);
208 } catch (ClassNotFoundException e1) {
209 throw new SAXException("SAX2 driver class " + className
210 + " not found", e1);
211 } catch (IllegalAccessException e2) {
212 throw new SAXException("SAX2 driver class " + className
213 + " found but cannot be loaded", e2);
214 } catch (InstantiationException e3) {
215 throw new SAXException(
216 "SAX2 driver class "
217 + className
218 + " loaded but cannot be instantiated (no empty public constructor?)",
219 e3);
220 } catch (ClassCastException e4) {
221 throw new SAXException("SAX2 driver class " + className
222 + " does not implement XMLReader", e4);
223 }
224 }
225 }
|