~ubuntu-branches/ubuntu/gutsy/libjaxp1.3-java/gutsy

« back to all changes in this revision

Viewing changes to org/xml/sax/helpers/XMLReaderFactory.java

  • Committer: Bazaar Package Importer
  • Author(s): Arnaud Vandyck
  • Date: 2006-08-03 10:30:58 UTC
  • Revision ID: james.westby@ubuntu.com-20060803103058-7jwwiqv9g8w9094d
Tags: upstream-1.3.03
ImportĀ upstreamĀ versionĀ 1.3.03

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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 226251 2005-06-21 19:19:22Z mrglavas $
 
7
 
 
8
package org.xml.sax.helpers;
 
9
import java.io.BufferedReader;
 
10
import java.io.IOException;
 
11
import java.io.InputStream;
 
12
import java.io.InputStreamReader;
 
13
import org.xml.sax.XMLReader;
 
14
import org.xml.sax.SAXException;
 
15
 
 
16
 
 
17
/**
 
18
 * Factory for creating an XML reader.
 
19
 *
 
20
 * <blockquote>
 
21
 * <em>This module, both source code and documentation, is in the
 
22
 * Public Domain, and comes with <strong>NO WARRANTY</strong>.</em>
 
23
 * See <a href='http://www.saxproject.org'>http://www.saxproject.org</a>
 
24
 * for further information.
 
25
 * </blockquote>
 
26
 *
 
27
 * <p>This class contains static methods for creating an XML reader
 
28
 * from an explicit class name, or based on runtime defaults:</p>
 
29
 *
 
30
 * <pre>
 
31
 * try {
 
32
 *   XMLReader myReader = XMLReaderFactory.createXMLReader();
 
33
 * } catch (SAXException e) {
 
34
 *   System.err.println(e.getMessage());
 
35
 * }
 
36
 * </pre>
 
37
 *
 
38
 * <p><strong>Note to Distributions bundled with parsers:</strong>
 
39
 * You should modify the implementation of the no-arguments
 
40
 * <em>createXMLReader</em> to handle cases where the external
 
41
 * configuration mechanisms aren't set up.  That method should do its
 
42
 * best to return a parser when one is in the class path, even when
 
43
 * nothing bound its class name to <code>org.xml.sax.driver</code> so
 
44
 * those configuration mechanisms would see it.</p>
 
45
 *
 
46
 * @since SAX 2.0
 
47
 * @author David Megginson, David Brownell
 
48
 * @version 2.0.1 (sax2r2)
 
49
 */
 
50
final public class XMLReaderFactory
 
51
{
 
52
    /**
 
53
     * Private constructor.
 
54
     *
 
55
     * <p>This constructor prevents the class from being instantiated.</p>
 
56
     */
 
57
    private XMLReaderFactory ()
 
58
    {
 
59
    }
 
60
    
 
61
    private static final String property = "org.xml.sax.driver";
 
62
    
 
63
    /**
 
64
     * Default columns per line.
 
65
     */
 
66
    private static final int DEFAULT_LINE_LENGTH = 80;
 
67
    
 
68
    /**
 
69
     * Attempt to create an XMLReader from system defaults.
 
70
     * In environments which can support it, the name of the XMLReader
 
71
     * class is determined by trying each these options in order, and
 
72
     * using the first one which succeeds:</p> <ul>
 
73
     *
 
74
     * <li>If the system property <code>org.xml.sax.driver</code>
 
75
     * has a value, that is used as an XMLReader class name. </li>
 
76
     *
 
77
     * <li>The JAR "Services API" is used to look for a class name
 
78
     * in the <em>META-INF/services/org.xml.sax.driver</em> file in
 
79
     * jarfiles available to the runtime.</li>
 
80
     *
 
81
     * <li> SAX parser distributions are strongly encouraged to provide
 
82
     * a default XMLReader class name that will take effect only when
 
83
     * previous options (on this list) are not successful.</li>
 
84
     *
 
85
     * <li>Finally, if {@link ParserFactory#makeParser()} can
 
86
     * return a system default SAX1 parser, that parser is wrapped in
 
87
     * a {@link ParserAdapter}.  (This is a migration aid for SAX1
 
88
     * environments, where the <code>org.xml.sax.parser</code> system
 
89
     * property will often be usable.) </li>
 
90
     *
 
91
     * </ul>
 
92
     *
 
93
     * <p> In environments such as small embedded systems, which can not
 
94
     * support that flexibility, other mechanisms to determine the default
 
95
     * may be used. </p>
 
96
     *
 
97
     * <p>Note that many Java environments allow system properties to be
 
98
     * initialized on a command line.  This means that <em>in most cases</em>
 
99
     * setting a good value for that property ensures that calls to this
 
100
     * method will succeed, except when security policies intervene.
 
101
     * This will also maximize application portability to older SAX
 
102
     * environments, with less robust implementations of this method.
 
103
     * </p>
 
104
     *
 
105
     * @return A new XMLReader.
 
106
     * @exception org.xml.sax.SAXException If no default XMLReader class
 
107
     *            can be identified and instantiated.
 
108
     * @see #createXMLReader(java.lang.String)
 
109
     */
 
110
    public static XMLReader createXMLReader ()
 
111
    throws SAXException
 
112
    {
 
113
        String          className = null;
 
114
        SecuritySupport ss = SecuritySupport.getInstance();
 
115
        ClassLoader     loader = NewInstance.getClassLoader ();
 
116
        
 
117
        // 1. try the JVM-instance-wide system property
 
118
        try { className = ss.getSystemProperty (property); }
 
119
        catch (Exception e) { /* normally fails for applets */ }
 
120
        
 
121
        // 2. if that fails, try META-INF/services/
 
122
        if (className == null) {
 
123
            String      service = "META-INF/services/" + property;
 
124
            
 
125
            InputStream is = null;
 
126
            
 
127
            // First try the Context ClassLoader
 
128
            ClassLoader cl = ss.getContextClassLoader();
 
129
            if (cl != null) {
 
130
                is = ss.getResourceAsStream(cl, service);
 
131
                
 
132
                // If no provider found then try the current ClassLoader
 
133
                if (is == null) {
 
134
                    cl = XMLReaderFactory.class.getClassLoader();
 
135
                    is = ss.getResourceAsStream(cl, service);
 
136
                }
 
137
            } else {
 
138
                // No Context ClassLoader or JDK 1.1 so try the current
 
139
                // ClassLoader
 
140
                cl = XMLReaderFactory.class.getClassLoader();
 
141
                is = ss.getResourceAsStream(cl, service);
 
142
            }
 
143
            
 
144
            if (is != null) {
 
145
                
 
146
                // Read the service provider name in UTF-8 as specified in
 
147
                // the jar spec.  Unfortunately this fails in Microsoft
 
148
                // VJ++, which does not implement the UTF-8
 
149
                // encoding. Theoretically, we should simply let it fail in
 
150
                // that case, since the JVM is obviously broken if it
 
151
                // doesn't support such a basic standard.  But since there
 
152
                // are still some users attempting to use VJ++ for
 
153
                // development, we have dropped in a fallback which makes a
 
154
                // second attempt using the platform's default encoding. In
 
155
                // VJ++ this is apparently ASCII, which is a subset of
 
156
                // UTF-8... and since the strings we'll be reading here are
 
157
                // also primarily limited to the 7-bit ASCII range (at
 
158
                // least, in English versions), this should work well
 
159
                // enough to keep us on the air until we're ready to
 
160
                // officially decommit from VJ++. [Edited comment from
 
161
                // jkesselm]
 
162
                BufferedReader rd;
 
163
                try {
 
164
                    rd = new BufferedReader(new InputStreamReader(is, "UTF-8"), DEFAULT_LINE_LENGTH);
 
165
                } catch (java.io.UnsupportedEncodingException e) {
 
166
                    rd = new BufferedReader(new InputStreamReader(is), DEFAULT_LINE_LENGTH);
 
167
                }
 
168
                
 
169
                try {
 
170
                    // XXX Does not handle all possible input as specified by the
 
171
                    // Jar Service Provider specification
 
172
                    className = rd.readLine();
 
173
                } 
 
174
                catch (Exception x) {
 
175
                    // No provider found
 
176
                } 
 
177
                finally {
 
178
                    try { 
 
179
                        // try to close the reader. 
 
180
                        rd.close(); 
 
181
                    } 
 
182
                    // Ignore the exception. 
 
183
                    catch (IOException exc) {}
 
184
                }
 
185
            }
 
186
        }
 
187
        
 
188
        // 3. Distro-specific fallback
 
189
        if (className == null) {
 
190
            // BEGIN DISTRIBUTION-SPECIFIC
 
191
            
 
192
            // EXAMPLE:
 
193
            // className = "com.example.sax.XmlReader";
 
194
            // or a $JAVA_HOME/jre/lib/*properties setting...
 
195
            className = "org.apache.xerces.parsers.SAXParser";
 
196
            
 
197
            // END DISTRIBUTION-SPECIFIC
 
198
        }
 
199
        
 
200
        // do we know the XMLReader implementation class yet?
 
201
        if (className != null)
 
202
            return loadClass (loader, className);
 
203
        
 
204
        // 4. panic -- adapt any SAX1 parser
 
205
        try {
 
206
            return new ParserAdapter (ParserFactory.makeParser ());
 
207
        } catch (Exception e) {
 
208
            throw new SAXException ("Can't create default XMLReader; "
 
209
                    + "is system property org.xml.sax.driver set?");
 
210
        }
 
211
    }
 
212
    
 
213
    
 
214
    /**
 
215
     * Attempt to create an XML reader from a class name.
 
216
     *
 
217
     * <p>Given a class name, this method attempts to load
 
218
     * and instantiate the class as an XML reader.</p>
 
219
     *
 
220
     * <p>Note that this method will not be usable in environments where
 
221
     * the caller (perhaps an applet) is not permitted to load classes
 
222
     * dynamically.</p>
 
223
     *
 
224
     * @return A new XML reader.
 
225
     * @exception org.xml.sax.SAXException If the class cannot be
 
226
     *            loaded, instantiated, and cast to XMLReader.
 
227
     * @see #createXMLReader()
 
228
     */
 
229
    public static XMLReader createXMLReader (String className)
 
230
    throws SAXException
 
231
    {
 
232
        return loadClass (NewInstance.getClassLoader (), className);
 
233
    }
 
234
    
 
235
    private static XMLReader loadClass (ClassLoader loader, String className)
 
236
    throws SAXException
 
237
    {
 
238
        try {
 
239
            return (XMLReader) NewInstance.newInstance (loader, className);
 
240
        } catch (ClassNotFoundException e1) {
 
241
            throw new SAXException("SAX2 driver class " + className +
 
242
                    " not found", e1);
 
243
        } catch (IllegalAccessException e2) {
 
244
            throw new SAXException("SAX2 driver class " + className +
 
245
                    " found but cannot be loaded", e2);
 
246
        } catch (InstantiationException e3) {
 
247
            throw new SAXException("SAX2 driver class " + className +
 
248
                    " loaded but cannot be instantiated (no empty public constructor?)",
 
249
                    e3);
 
250
        } catch (ClassCastException e4) {
 
251
            throw new SAXException("SAX2 driver class " + className +
 
252
                    " does not implement XMLReader", e4);
 
253
        }
 
254
    }
 
255
}