gdata-java-client
http://code.google.com/p/gdata-java-client/
The root cause is reported in detail as Issue 9493.
http://code.google.com/p/android/issues/detail?id=9493
The first solution that came to my mind is to replace SAXParserFactory using the system property "javax.xml.parsers.SAXParserFactory". This mechanism is described also in Android's online document.
http://developer.android.com/reference/javax/xml/parsers/SAXParser.html
So, I tried the following code to replace the implementation of SAXParserFactory with xerces's one.
System.setProperty("javax.xml.parsers.SAXParserFactory", "org.apache.xerces.jaxp.SAXParserFactoryImpl");
However, this did not work, and I finally found that Android's SAXParserFactory does not support the mechanism to replace the implementation.
http://www.java2s.com/Open-Source/Android/android-core/platform-libcore/javax/xml/parsers/SAXParserFactory.java.htm
/**
* Returns Android's implementation of {@code SAXParserFactory}. Unlike
* other Java implementations, this method does not consult system
* properties, property files, or the services API.
*
* @return a new SAXParserFactory.
*
* @exception FactoryConfigurationError never. Included for API
* compatibility with other Java implementations.
*/
public static SAXParserFactory newInstance() {
// instantiate the class directly rather than using reflection
return new SAXParserFactoryImpl();
}
So, I returned back to the report of Issue 9493. It says that gdata-java-client defines and uses SecureGenericXMLFactory and it intentionally disables some features that are needed to parse YouTube responses.
The actual source code lines to disable the necessary features are written in the constructor of SecureSAXParserFactory, which is an internal class of SecureGenericXMLFactory.
/* Setting the attribute
* http://apache.org/xml/features/disallow-doctype-decl to true causes an
* immediate exception when a DTD is encountered. Unfortunately, an XML
* document will sometimes include a harmless DTD so we cannot ban DTDs
* outright.
*/
try {
factory.setFeature(
"http://xml.org/sax/features/external-general-entities",
false);
} catch (IllegalArgumentException e) {
/* OK. Not all parsers will support this attribute */
} catch (SAXNotRecognizedException e) {
/* OK. Not all parsers will support this attribute */
}
try {
factory.setFeature(
"http://xml.org/sax/features/external-parameter-entities",false);
} catch (IllegalArgumentException e) {
/* OK. Not all parsers will support this attribute */
} catch (SAXNotRecognizedException e) {
/* OK. Not all parsers will support this attribute */
}
After seeing this fact, the solution I adopted was to replace the implementation of SecureGenericXMLFactory with my own. The concrete steps were as follows.
(1) Remove the original SecureGenericXMLFactory from gdata-core-1.0.jar
cd gdata-src.java-1.46.0/gdata/java/lib
mkdir gdata-core-1.0-no-SecureGenericXMLFactory
cd gdata-core-1.0-no-SecureGenericXMLFactory
jar xf ../gdata-core-1.0.jar
rm -rf com/google/gdata/util/common/xml/parsing
jar cfm ../gdata-core-1.0-no-SecureGenericXMLFactory.jar META-INF/MANIFEST.MF com
(2) Replace the original JAR file with the new one created by the step (1) in Eclipse.
(3) Copy the original source code of SecureGenericXMLFactory to my Android project.
(4) Add an unconditional 'return' in the constructor of SecureSAXParserFactory before the code lines that disable the necessary features.
// "if (true)" was added to avoid a compilation error in Eclipse.
if (true)
{
return;
}
The detailed report of Issue 9493 was really helpful. I want to thank the reporter.