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 */ XmlPullParserFactory()35 protected XmlPullParserFactory() { 36 parserClasses = new ArrayList<String>(); 37 serializerClasses = new ArrayList<String>(); 38 39 try { 40 parserClasses.add(Class.forName("com.android.org.kxml2.io.KXmlParser")); 41 serializerClasses.add(Class.forName("com.android.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 */ setFeature(String name, boolean state)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 */ getFeature(String name)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 */ setNamespaceAware(boolean awareness)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 */ isNamespaceAware()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 */ setValidating(boolean validating)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 isValidating()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 */ newPullParser()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 getParserInstance()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 getSerializerInstance()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 newInstantiationException(String message, ArrayList<Exception> exceptions)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 newSerializer()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 */ newInstance()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 */ newInstance(String unused, Class unused2)230 public static XmlPullParserFactory newInstance (String unused, Class unused2) 231 throws XmlPullParserException { 232 return newInstance(); 233 } 234 } 235