diff options
author | Narayan Kamath <narayan@google.com> | 2014-02-11 11:41:38 +0000 |
---|---|---|
committer | Narayan Kamath <narayan@google.com> | 2014-02-13 12:42:42 +0000 |
commit | 34543a94c2e11f602114d2097a8f977d40d56cb9 (patch) | |
tree | eae43adb83dc416d7706c1f245c34c4a6d8a75c3 /xml/src/main/java/org | |
parent | 2e413ba8dfbd9d6c7720afc36699b26eda7aebac (diff) | |
download | libcore-34543a94c2e11f602114d2097a8f977d40d56cb9.zip libcore-34543a94c2e11f602114d2097a8f977d40d56cb9.tar.gz libcore-34543a94c2e11f602114d2097a8f977d40d56cb9.tar.bz2 |
Fix compatibility issues in XmlPullParserFactory.
- We should set features on a parser only if the feature
value is true. I.e, we guarantee that we'll never call
XmlPullParser.setFeature(..., false).
- In change 0363556bad8930a, we didn't consider the fact
that apps could extend XmlPullParserFactory and modify
protected fields to change the parser / serializer that's
instantiated. I've reinstated this feature, despite the
fact that it's a particularly pointless feature on a
more-or-less pointless public API. Apps can and should
instantiate their own parser instances directly instead
of going through this factory.
bug: 12956724
Change-Id: I793eba335b5385eb641e023b3613bba4515a85bf
Diffstat (limited to 'xml/src/main/java/org')
-rw-r--r-- | xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java | 113 |
1 files changed, 86 insertions, 27 deletions
diff --git a/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java index 32e4f20..41db89c 100644 --- a/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java +++ b/xml/src/main/java/org/xmlpull/v1/XmlPullParserFactory.java @@ -20,18 +20,13 @@ import java.util.Map; */ public class XmlPullParserFactory { - // TODO: Deprecate or remove these fields. They're currently unused - // but are public APIs. - /** Currently unused. */ - public static final String PROPERTY_NAME = - "org.xmlpull.v1.XmlPullParserFactory"; - /** Currently unused */ + public static final String PROPERTY_NAME = "org.xmlpull.v1.XmlPullParserFactory"; + protected ArrayList parserClasses; + protected ArrayList serializerClasses; + + /** Unused, but we have to keep it because it's public API. */ protected String classNamesLocation = null; - /** Currently unused */ - protected ArrayList parserClasses = null; - /** Currently unused */ - protected ArrayList serializerClasses = null; // features are kept there // TODO: This can't be made final because it's a public API. @@ -40,12 +35,18 @@ public class XmlPullParserFactory { /** * Protected constructor to be called by factory implementations. */ - protected XmlPullParserFactory() { + parserClasses = new ArrayList<String>(); + serializerClasses = new ArrayList<String>(); + + try { + parserClasses.add(Class.forName("org.kxml2.io.KXmlParser")); + serializerClasses.add(Class.forName("org.kxml2.io.KXmlSerializer")); + } catch (ClassNotFoundException e) { + throw new AssertionError(); + } } - - /** * Set the features to be set when XML Pull Parser is created by this factory. * <p><b>NOTE:</b> factory features are not used for XML Serializer. @@ -53,7 +54,6 @@ public class XmlPullParserFactory { * @param name string with URI identifying feature * @param state if true feature will be set; if false will be ignored */ - public void setFeature(String name, boolean state) throws XmlPullParserException { features.put(name, state); } @@ -67,8 +67,7 @@ public class XmlPullParserFactory { * @return The value of named feature. * Unknown features are <string>always</strong> returned as false */ - - public boolean getFeature (String name) { + public boolean getFeature(String name) { Boolean value = features.get(name); return value != null ? value.booleanValue() : false; } @@ -81,7 +80,6 @@ public class XmlPullParserFactory { * @param awareness true if the parser produced by this code * will provide support for XML namespaces; false otherwise. */ - public void setNamespaceAware(boolean awareness) { features.put (XmlPullParser.FEATURE_PROCESS_NAMESPACES, awareness); } @@ -94,12 +92,10 @@ public class XmlPullParserFactory { * @return true if the factory is configured to produce parsers * which are namespace aware; false otherwise. */ - public boolean isNamespaceAware() { - return getFeature (XmlPullParser.FEATURE_PROCESS_NAMESPACES); + return getFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES); } - /** * Specifies that the parser produced by this factory will be validating * (it simply set feature XmlPullParser.FEATURE_VALIDATION to true or false). @@ -108,9 +104,8 @@ public class XmlPullParserFactory { * * @param validating - if true the parsers created by this factory must be validating. */ - public void setValidating(boolean validating) { - features.put (XmlPullParser.FEATURE_VALIDATION, validating); + features.put(XmlPullParser.FEATURE_VALIDATION, validating); } /** @@ -122,7 +117,7 @@ public class XmlPullParserFactory { */ public boolean isValidating() { - return getFeature (XmlPullParser.FEATURE_VALIDATION); + return getFeature(XmlPullParser.FEATURE_VALIDATION); } /** @@ -131,16 +126,80 @@ public class XmlPullParserFactory { * * @return A new instance of a XML Pull Parser. */ - public XmlPullParser newPullParser() throws XmlPullParserException { - final XmlPullParser pp = new KXmlParser(); + final XmlPullParser pp = getParserInstance(); for (Map.Entry<String, Boolean> entry : features.entrySet()) { - pp.setFeature(entry.getKey(), entry.getValue()); + // NOTE: This test is needed for compatibility reasons. We guarantee + // that we only set a feature on a parser if its value is true. + if (entry.getValue()) { + pp.setFeature(entry.getKey(), entry.getValue()); + } } return pp; } + private XmlPullParser getParserInstance() throws XmlPullParserException { + ArrayList<Exception> exceptions = null; + + if (parserClasses != null && !parserClasses.isEmpty()) { + exceptions = new ArrayList<Exception>(); + for (Object o : parserClasses) { + try { + if (o != null) { + Class<?> parserClass = (Class<?>) o; + return (XmlPullParser) parserClass.newInstance(); + } + } catch (InstantiationException e) { + exceptions.add(e); + } catch (IllegalAccessException e) { + exceptions.add(e); + } catch (ClassCastException e) { + exceptions.add(e); + } + } + } + + throw newInstantiationException("Invalid parser class list", exceptions); + } + + private XmlSerializer getSerializerInstance() throws XmlPullParserException { + ArrayList<Exception> exceptions = null; + + if (serializerClasses != null && !serializerClasses.isEmpty()) { + exceptions = new ArrayList<Exception>(); + for (Object o : serializerClasses) { + try { + if (o != null) { + Class<?> serializerClass = (Class<?>) o; + return (XmlSerializer) serializerClass.newInstance(); + } + } catch (InstantiationException e) { + exceptions.add(e); + } catch (IllegalAccessException e) { + exceptions.add(e); + } catch (ClassCastException e) { + exceptions.add(e); + } + } + } + + throw newInstantiationException("Invalid serializer class list", exceptions); + } + + private static XmlPullParserException newInstantiationException(String message, + ArrayList<Exception> exceptions) { + if (exceptions == null || exceptions.isEmpty()) { + return new XmlPullParserException(message); + } else { + XmlPullParserException exception = new XmlPullParserException(message); + for (Exception ex : exceptions) { + exception.addSuppressed(ex); + } + + return exception; + } + } /** * Creates a new instance of a XML Serializer. @@ -153,7 +212,7 @@ public class XmlPullParserFactory { */ public XmlSerializer newSerializer() throws XmlPullParserException { - return new KXmlSerializer(); + return getSerializerInstance(); } /** |