KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > xmlpull > v1 > XmlPullParserFactory


1 /* -*- c-basic-offset: 4; indent-tabs-mode: nil; -*- //------100-columns-wide------>|*/
2 // for license please see accompanying LICENSE.txt file (available also at http://www.xmlpull.org/)
3

4 package org.xmlpull.v1;
5
6 import java.io.InputStream JavaDoc;
7 import java.io.IOException JavaDoc;
8 import java.io.Reader JavaDoc;
9 import java.io.Writer JavaDoc;
10 import java.util.Enumeration JavaDoc;
11 import java.util.Hashtable JavaDoc;
12 import java.util.Vector JavaDoc;
13
14 /**
15  * This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API.
16  * The name of actual facotry class will be determied based on several parameters.
17  * It works similar to JAXP but tailored to work in J2ME environments
18  * (no access to system properties or file system) so name of parser class factory to use
19  * and its class used for loading (no classloader - on J2ME no access to context class loaders)
20  * must be passed explicitly. If no name of parser factory was passed (or is null)
21  * it will try to find name by searching in CLASSPATH for
22  * META-INF/services/org.xmlpull.v1.XmlPullParserFactory resource that should contain
23  * a comma separated list of class names of factories or parsers to try (in order from
24  * left to the right). If none found, it will throw an exception.
25  *
26  * <p><strong>NOTE:</strong>In J2SE or J2EE environments, you may want to use
27  * <code>newInstance(property, classLoaderCtx)</code>
28  * where first argument is
29  * <code>System.getProperty(XmlPullParserFactory.PROPERTY_NAME)</code>
30  * and second is <code>Thread.getContextClassLoader().getClass()</code> .
31  *
32  * @see XmlPullParser
33  *
34  * @author <a HREF="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
35  * @author Stefan Haustein
36  */

37
38 public class XmlPullParserFactory {
39
40     /** Name of the system or midlet property that should be used for
41      a system property containing a comma separated list of factory
42      or parser class names (value:
43      org.xmlpull.v1.XmlPullParserFactory). */

44
45
46     public static final String JavaDoc PROPERTY_NAME =
47         "org.xmlpull.v1.XmlPullParserFactory";
48
49     private static final String JavaDoc RESOURCE_NAME =
50         "/META-INF/services/" + PROPERTY_NAME;
51
52
53     // public static final String DEFAULT_PROPERTY =
54
// "org.xmlpull.xpp3.XmlPullParser,org.kxml2.io.KXmlParser";
55

56
57     protected Vector JavaDoc parserClasses;
58     protected String JavaDoc classNamesLocation;
59
60     protected Vector JavaDoc serializerClasses;
61
62
63     // features are kept there
64
protected Hashtable JavaDoc features = new Hashtable JavaDoc();
65
66
67     /**
68      * Protected constructor to be called by factory implementations.
69      */

70
71     protected XmlPullParserFactory() {
72     }
73
74
75
76     /**
77      * Set the features to be set when XML Pull Parser is created by this factory.
78      * <p><b>NOTE:</b> factory features are not used for XML Serializer.
79      *
80      * @param name string with URI identifying feature
81      * @param state if true feature will be set; if false will be ignored
82      */

83
84     public void setFeature(String JavaDoc name,
85                            boolean state) throws XmlPullParserException {
86
87         features.put(name, new Boolean JavaDoc(state));
88     }
89
90
91     /**
92      * Return the current value of the feature with given name.
93      * <p><b>NOTE:</b> factory features are not used for XML Serializer.
94      *
95      * @param name The name of feature to be retrieved.
96      * @return The value of named feature.
97      * Unknown features are <string>always</strong> returned as false
98      */

99
100     public boolean getFeature (String JavaDoc name) {
101         Boolean JavaDoc value = (Boolean JavaDoc) features.get(name);
102         return value != null ? value.booleanValue() : false;
103     }
104
105     /**
106      * Specifies that the parser produced by this factory will provide
107      * support for XML namespaces.
108      * By default the value of this is set to false.
109      *
110      * @param awareness true if the parser produced by this code
111      * will provide support for XML namespaces; false otherwise.
112      */

113
114     public void setNamespaceAware(boolean awareness) {
115         features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, new Boolean JavaDoc (awareness));
116     }
117
118     /**
119      * Indicates whether or not the factory is configured to produce
120      * parsers which are namespace aware
121      * (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false).
122      *
123      * @return true if the factory is configured to produce parsers
124      * which are namespace aware; false otherwise.
125      */

126
127     public boolean isNamespaceAware() {
128         return getFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES);
129     }
130
131
132     /**
133      * Specifies that the parser produced by this factory will be validating
134      * (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false).
135      *
136      * By default the value of this is set to false.
137      *
138      * @param validating - if true the parsers created by this factory must be validating.
139      */

140
141     public void setValidating(boolean validating) {
142         features.put (XmlPullParser.FEATURE_VALIDATION, new Boolean JavaDoc (validating));
143     }
144
145     /**
146      * Indicates whether or not the factory is configured to produce parsers
147      * which validate the XML content during parse.
148      *
149      * @return true if the factory is configured to produce parsers
150      * which validate the XML content during parse; false otherwise.
151      */

152
153     public boolean isValidating() {
154         return getFeature (XmlPullParser.FEATURE_VALIDATION);
155     }
156
157     /**
158      * Creates a new instance of a XML Pull Parser
159      * using the currently configured factory features.
160      *
161      * @return A new instance of a XML Pull Parser.
162      * @throws XmlPullParserException if a parser cannot be created which satisfies the
163      * requested configuration.
164      */

165
166     public XmlPullParser newPullParser() throws XmlPullParserException {
167
168         if (parserClasses == null) throw new XmlPullParserException
169                 ("Factory initialization was incomplete - has not tried "+classNamesLocation);
170
171         if (parserClasses.size() == 0) throw new XmlPullParserException
172                 ("No valid parser classes found in "+classNamesLocation);
173
174         StringBuffer JavaDoc issues = new StringBuffer JavaDoc ();
175
176         for (int i = 0; i < parserClasses.size (); i++) {
177             Class JavaDoc ppClass = (Class JavaDoc) parserClasses.elementAt (i);
178             try {
179                 XmlPullParser pp = (XmlPullParser) ppClass.newInstance();
180                 // if( ! features.isEmpty() ) {
181
//Enumeration keys = features.keys();
182
// while(keys.hasMoreElements()) {
183

184                 for (Enumeration JavaDoc e = features.keys (); e.hasMoreElements ();) {
185                     String JavaDoc key = (String JavaDoc) e.nextElement();
186                     Boolean JavaDoc value = (Boolean JavaDoc) features.get(key);
187                     if(value != null && value.booleanValue()) {
188                         pp.setFeature(key, true);
189                     }
190                 }
191                 return pp;
192
193             } catch(Exception JavaDoc ex) {
194                 issues.append (ppClass.getName () + ": "+ ex.toString ()+"; ");
195             }
196         }
197
198         throw new XmlPullParserException ("could not create parser: "+issues);
199     }
200
201
202     /**
203      * Creates a new instance of a XML Serializer.
204      *
205      * <p><b>NOTE:</b> factory features are not used for XML Serializer.
206      *
207      * @return A new instance of a XML Serializer.
208      * @throws XmlPullParserException if a parser cannot be created which satisfies the
209      * requested configuration.
210      */

211
212     public XmlSerializer newSerializer() throws XmlPullParserException {
213
214         if (serializerClasses == null) {
215             throw new XmlPullParserException
216                 ("Factory initialization incomplete - has not tried "+classNamesLocation);
217         }
218         if(serializerClasses.size() == 0) {
219             throw new XmlPullParserException
220                 ("No valid serializer classes found in "+classNamesLocation);
221         }
222
223         StringBuffer JavaDoc issues = new StringBuffer JavaDoc ();
224
225         for (int i = 0; i < serializerClasses.size (); i++) {
226             Class JavaDoc ppClass = (Class JavaDoc) serializerClasses.elementAt (i);
227             try {
228                 XmlSerializer ser = (XmlSerializer) ppClass.newInstance();
229
230                 // for (Enumeration e = features.keys (); e.hasMoreElements ();) {
231
// String key = (String) e.nextElement();
232
// Boolean value = (Boolean) features.get(key);
233
// if(value != null && value.booleanValue()) {
234
// ser.setFeature(key, true);
235
// }
236
// }
237
return ser;
238
239             } catch(Exception JavaDoc ex) {
240                 issues.append (ppClass.getName () + ": "+ ex.toString ()+"; ");
241             }
242         }
243
244         throw new XmlPullParserException ("could not create serializer: "+issues);
245     }
246
247     /**
248      * Create a new instance of a PullParserFactory that can be used
249      * to create XML pull parsers (see class description for more
250      * details).
251      *
252      * @return a new instance of a PullParserFactory, as returned by newInstance (null, null); */

253
254     public static XmlPullParserFactory newInstance () throws XmlPullParserException {
255         return newInstance(null, null);
256     }
257
258
259
260     public static XmlPullParserFactory newInstance (String JavaDoc classNames, Class JavaDoc context)
261         throws XmlPullParserException {
262
263         if (context == null) context = "".getClass ();
264
265         String JavaDoc classNamesLocation = null;
266
267
268         if (classNames == null || classNames.length() == 0 || "DEFAULT".equals(classNames)) {
269             try {
270                 InputStream JavaDoc is = context.getResourceAsStream (RESOURCE_NAME);
271
272                 if (is == null) {
273                     classNames = "org.xmlpull.mxp1.MXParserFactory";
274                 } else {
275
276                     StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
277     
278                     while (true) {
279                         int ch = is.read();
280                         if (ch < 0) break;
281                         else if (ch > ' ')
282                             sb.append((char) ch);
283                     }
284                     is.close ();
285     
286                     classNames = sb.toString ();
287                 }
288             }
289             catch (Exception JavaDoc e) {
290                 throw new XmlPullParserException (null, null, e);
291             }
292             classNamesLocation = "resource "+RESOURCE_NAME+" that contained '"+classNames+"'";
293         } else {
294             classNamesLocation =
295                 "parameter classNames to newInstance() that contained '"+classNames+"'";
296         }
297
298         XmlPullParserFactory factory = null;
299         Vector JavaDoc parserClasses = new Vector JavaDoc ();
300         Vector JavaDoc serializerClasses = new Vector JavaDoc ();
301         int pos = 0;
302
303         while (pos < classNames.length ()) {
304             int cut = classNames.indexOf (',', pos);
305
306             if (cut == -1) cut = classNames.length ();
307             String JavaDoc name = classNames.substring (pos, cut);
308
309             Class JavaDoc candidate = null;
310             Object JavaDoc instance = null;
311
312             try {
313                 candidate = Class.forName (name);
314                 // neccessary because of J2ME .class issue
315
instance = candidate.newInstance ();
316             }
317             catch (Exception JavaDoc e) {}
318
319             if (candidate != null) {
320                 boolean recognized = false;
321                 if (instance instanceof XmlPullParser) {
322                     parserClasses.addElement (candidate);
323                     recognized = true;
324                 }
325                 if (instance instanceof XmlSerializer) {
326                     serializerClasses.addElement (candidate);
327                     recognized = true;
328                 }
329                 if (instance instanceof XmlPullParserFactory) {
330                     if (factory == null) {
331                         factory = (XmlPullParserFactory) instance;
332                     }
333                     recognized = true;
334                 }
335                 if (!recognized) {
336                     throw new XmlPullParserException ("incompatible class: "+name);
337                 }
338             }
339             pos = cut + 1;
340         }
341
342         if (factory == null) {
343             factory = new XmlPullParserFactory ();
344         }
345         factory.parserClasses = parserClasses;
346         factory.serializerClasses = serializerClasses;
347         factory.classNamesLocation = classNamesLocation;
348         return factory;
349     }
350 }
351
352
353
Popular Tags