Home | History | Annotate | Download | only in v1
      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.util.ArrayList;
      7 import java.util.HashMap;
      8 import java.util.Map;
      9 
     10 /**
     11  * This class is used to create implementations of XML Pull Parser defined in XMPULL V1 API.
     12  *
     13  * @see XmlPullParser
     14  *
     15  * @author <a href="http://www.extreme.indiana.edu/~aslom/">Aleksander Slominski</a>
     16  * @author Stefan Haustein
     17  */
     18 
     19 public class XmlPullParserFactory {
     20 
     21     public static final String PROPERTY_NAME = "org.xmlpull.v1.XmlPullParserFactory";
     22     protected ArrayList parserClasses;
     23     protected ArrayList serializerClasses;
     24 
     25     /** Unused, but we have to keep it because it's public API. */
     26     protected String classNamesLocation = null;
     27 
     28     // features are kept there
     29     // TODO: This can't be made final because it's a public API.
     30     protected HashMap<String, Boolean> features = new HashMap<String, Boolean>();
     31 
     32     /**
     33      * Protected constructor to be called by factory implementations.
     34      */
     35     protected XmlPullParserFactory() {
     36         parserClasses = new ArrayList<String>();
     37         serializerClasses = new ArrayList<String>();
     38 
     39         try {
     40             parserClasses.add(Class.forName("org.kxml2.io.KXmlParser"));
     41             serializerClasses.add(Class.forName("org.kxml2.io.KXmlSerializer"));
     42         } catch (ClassNotFoundException e) {
     43             throw new AssertionError();
     44         }
     45     }
     46 
     47     /**
     48      * Set the features to be set when XML Pull Parser is created by this factory.
     49      * <p><b>NOTE:</b> factory features are not used for XML Serializer.
     50      *
     51      * @param name string with URI identifying feature
     52      * @param state if true feature will be set; if false will be ignored
     53      */
     54     public void setFeature(String name, boolean state) throws XmlPullParserException {
     55         features.put(name, state);
     56     }
     57 
     58 
     59     /**
     60      * Return the current value of the feature with given name.
     61      * <p><b>NOTE:</b> factory features are not used for XML Serializer.
     62      *
     63      * @param name The name of feature to be retrieved.
     64      * @return The value of named feature.
     65      *     Unknown features are <string>always</strong> returned as false
     66      */
     67     public boolean getFeature(String name) {
     68         Boolean value = features.get(name);
     69         return value != null ? value.booleanValue() : false;
     70     }
     71 
     72     /**
     73      * Specifies that the parser produced by this factory will provide
     74      * support for XML namespaces.
     75      * By default the value of this is set to false.
     76      *
     77      * @param awareness true if the parser produced by this code
     78      *    will provide support for XML namespaces;  false otherwise.
     79      */
     80     public void setNamespaceAware(boolean awareness) {
     81         features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, awareness);
     82     }
     83 
     84     /**
     85      * Indicates whether or not the factory is configured to produce
     86      * parsers which are namespace aware
     87      * (it simply set feature XmlPullParser.FEATURE_PROCESS_NAMESPACES to true or false).
     88      *
     89      * @return  true if the factory is configured to produce parsers
     90      *    which are namespace aware; false otherwise.
     91      */
     92     public boolean isNamespaceAware() {
     93         return getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES);
     94     }
     95 
     96     /**
     97      * Specifies that the parser produced by this factory will be validating
     98      * (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false).
     99      *
    100      * By default the value of this is set to false.
    101      *
    102      * @param validating - if true the parsers created by this factory  must be validating.
    103      */
    104     public void setValidating(boolean validating) {
    105         features.put(XmlPullParser.FEATURE_VALIDATION, validating);
    106     }
    107 
    108     /**
    109      * Indicates whether or not the factory is configured to produce parsers
    110      * which validate the XML content during parse.
    111      *
    112      * @return   true if the factory is configured to produce parsers
    113      * which validate the XML content during parse; false otherwise.
    114      */
    115 
    116     public boolean isValidating() {
    117         return getFeature(XmlPullParser.FEATURE_VALIDATION);
    118     }
    119 
    120     /**
    121      * Creates a new instance of a XML Pull Parser
    122      * using the currently configured factory features.
    123      *
    124      * @return A new instance of a XML Pull Parser.
    125      */
    126     public XmlPullParser newPullParser() throws XmlPullParserException {
    127         final XmlPullParser pp = getParserInstance();
    128         for (Map.Entry<String, Boolean> entry : features.entrySet()) {
    129             // NOTE: This test is needed for compatibility reasons. We guarantee
    130             // that we only set a feature on a parser if its value is true.
    131             if (entry.getValue()) {
    132                 pp.setFeature(entry.getKey(), entry.getValue());
    133             }
    134         }
    135 
    136         return pp;
    137     }
    138 
    139     private XmlPullParser getParserInstance() throws XmlPullParserException {
    140         ArrayList<Exception> exceptions = null;
    141 
    142         if (parserClasses != null && !parserClasses.isEmpty()) {
    143             exceptions = new ArrayList<Exception>();
    144             for (Object o : parserClasses) {
    145                 try {
    146                     if (o != null) {
    147                         Class<?> parserClass = (Class<?>) o;
    148                         return (XmlPullParser) parserClass.newInstance();
    149                     }
    150                 } catch (InstantiationException e) {
    151                     exceptions.add(e);
    152                 } catch (IllegalAccessException e) {
    153                     exceptions.add(e);
    154                 } catch (ClassCastException e) {
    155                     exceptions.add(e);
    156                 }
    157             }
    158         }
    159 
    160         throw newInstantiationException("Invalid parser class list", exceptions);
    161     }
    162 
    163     private XmlSerializer getSerializerInstance() throws XmlPullParserException {
    164         ArrayList<Exception> exceptions = null;
    165 
    166         if (serializerClasses != null && !serializerClasses.isEmpty()) {
    167             exceptions = new ArrayList<Exception>();
    168             for (Object o : serializerClasses) {
    169                 try {
    170                     if (o != null) {
    171                         Class<?> serializerClass = (Class<?>) o;
    172                         return (XmlSerializer) serializerClass.newInstance();
    173                     }
    174                 } catch (InstantiationException e) {
    175                     exceptions.add(e);
    176                 } catch (IllegalAccessException e) {
    177                     exceptions.add(e);
    178                 } catch (ClassCastException e) {
    179                     exceptions.add(e);
    180                 }
    181             }
    182         }
    183 
    184         throw newInstantiationException("Invalid serializer class list", exceptions);
    185     }
    186 
    187     private static XmlPullParserException newInstantiationException(String message,
    188             ArrayList<Exception> exceptions) {
    189         if (exceptions == null || exceptions.isEmpty()) {
    190             return new XmlPullParserException(message);
    191         } else {
    192             XmlPullParserException exception = new XmlPullParserException(message);
    193             for (Exception ex : exceptions) {
    194                 exception.addSuppressed(ex);
    195             }
    196 
    197             return exception;
    198         }
    199     }
    200 
    201     /**
    202      * Creates a new instance of a XML Serializer.
    203      *
    204      * <p><b>NOTE:</b> factory features are not used for XML Serializer.
    205      *
    206      * @return A new instance of a XML Serializer.
    207      * @throws XmlPullParserException if a parser cannot be created which satisfies the
    208      * requested configuration.
    209      */
    210 
    211     public XmlSerializer newSerializer() throws XmlPullParserException {
    212         return getSerializerInstance();
    213     }
    214 
    215     /**
    216      * Creates a new instance of a PullParserFactory that can be used
    217      * to create XML pull parsers. The factory will always return instances
    218      * of Android's built-in {@link XmlPullParser} and {@link XmlSerializer}.
    219      */
    220     public static XmlPullParserFactory newInstance () throws XmlPullParserException {
    221         return new XmlPullParserFactory();
    222     }
    223 
    224     /**
    225      * Creates a factory that always returns instances of Android's built-in
    226      * {@link XmlPullParser} and {@link XmlSerializer} implementation. This
    227      * <b>does not</b> support factories capable of creating arbitrary parser
    228      * and serializer implementations. Both arguments to this method are unused.
    229      */
    230     public static XmlPullParserFactory newInstance (String unused, Class unused2)
    231         throws XmlPullParserException {
    232         return newInstance();
    233     }
    234 }
    235