summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatParser.java16
-rw-r--r--xml/src/main/java/org/apache/harmony/xml/ExpatReader.java17
-rw-r--r--xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp120
-rw-r--r--xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java63
4 files changed, 167 insertions, 49 deletions
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java b/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java
index 60d74b8..be933ca 100644
--- a/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatParser.java
@@ -18,6 +18,7 @@ package org.apache.harmony.xml;
import org.xml.sax.Attributes;
import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
import org.xml.sax.EntityResolver;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
@@ -226,6 +227,20 @@ class ExpatParser {
}
}
+ /*package*/ void notationDecl(String name, String publicId, String systemId) throws SAXException {
+ DTDHandler dtdHandler = xmlReader.dtdHandler;
+ if (dtdHandler != null) {
+ dtdHandler.notationDecl(name, publicId, systemId);
+ }
+ }
+
+ /*package*/ void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException {
+ DTDHandler dtdHandler = xmlReader.dtdHandler;
+ if (dtdHandler != null) {
+ dtdHandler.unparsedEntityDecl(name, publicId, systemId, notationName);
+ }
+ }
+
/**
* Handles an external entity.
*
@@ -791,4 +806,3 @@ class ExpatParser {
}
}
}
-
diff --git a/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
index a6a83a0..dbe3a3a 100644
--- a/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
+++ b/xml/src/main/java/org/apache/harmony/xml/ExpatReader.java
@@ -37,15 +37,12 @@ import java.util.logging.Logger;
* Does not support {@link DTDHandler}.
*/
public class ExpatReader implements XMLReader {
-
- private static final Logger logger
- = Logger.getLogger(ExpatReader.class.getName());
-
/*
* ExpatParser accesses these fields directly during parsing. The user
* should be able to safely change them during parsing.
*/
/*package*/ ContentHandler contentHandler;
+ /*package*/ DTDHandler dtdHandler;
/*package*/ EntityResolver entityResolver;
/*package*/ ErrorHandler errorHandler;
/*package*/ LexicalHandler lexicalHandler;
@@ -170,18 +167,12 @@ public class ExpatReader implements XMLReader {
return entityResolver;
}
- /**
- * Not implemented.
- */
- public void setDTDHandler(DTDHandler ignored) {
- logger.warning("DTD handlers aren't supported.");
+ public void setDTDHandler(DTDHandler dtdHandler) {
+ this.dtdHandler = dtdHandler;
}
- /**
- * Always returns null.
- */
public DTDHandler getDTDHandler() {
- return null;
+ return dtdHandler;
}
public void setContentHandler(ContentHandler handler) {
diff --git a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
index 701dbd9..f16e905 100644
--- a/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
+++ b/xml/src/main/native/org_apache_harmony_xml_ExpatParser.cpp
@@ -31,7 +31,7 @@
/**
* Wrapper around an interned string.
*/
-typedef struct {
+struct InternedString {
/** The interned string itself. */
jstring interned;
@@ -41,22 +41,22 @@ typedef struct {
/** Hash code of the interned string. */
int hash;
-} InternedString;
+};
/**
* Keeps track of strings between start and end events.
*/
-typedef struct {
+struct StringStack {
jstring* array;
int capacity;
int size;
-} StringStack;
+};
/**
* Data passed to parser handler method by the parser.
*/
-typedef struct {
+struct ParsingContext {
/**
* The JNI environment for the current thread. This should only be used
@@ -87,21 +87,23 @@ typedef struct {
/** Cache of interned strings. */
InternedString** internedStrings[BUCKET_COUNT];
-} ParsingContext;
+};
-static jmethodID startElementMethod;
-static jmethodID endElementMethod;
-static jmethodID textMethod;
static jmethodID commentMethod;
-static jmethodID startCdataMethod;
static jmethodID endCdataMethod;
-static jmethodID startDtdMethod;
static jmethodID endDtdMethod;
-static jmethodID startNamespaceMethod;
+static jmethodID endElementMethod;
static jmethodID endNamespaceMethod;
-static jmethodID processingInstructionMethod;
static jmethodID handleExternalEntityMethod;
static jmethodID internMethod;
+static jmethodID notationDeclMethod;
+static jmethodID processingInstructionMethod;
+static jmethodID startCdataMethod;
+static jmethodID startDtdMethod;
+static jmethodID startElementMethod;
+static jmethodID startNamespaceMethod;
+static jmethodID textMethod;
+static jmethodID unparsedEntityDeclMethod;
static jclass stringClass;
static jstring emptyString;
@@ -879,6 +881,53 @@ static int handleExternalEntity(XML_Parser parser, const char* context,
return env->ExceptionCheck() ? XML_STATUS_ERROR : XML_STATUS_OK;
}
+static void unparsedEntityDecl(void* data, const char* name, const char* base, const char* systemId, const char* publicId, const char* notationName) {
+ ParsingContext* parsingContext = reinterpret_cast<ParsingContext*>(data);
+ jobject javaParser = parsingContext->object;
+ JNIEnv* env = parsingContext->env;
+
+ // Bail out if a previously called handler threw an exception.
+ if (env->ExceptionCheck()) return;
+
+ jstring javaName = env->NewStringUTF(name);
+ if (env->ExceptionCheck()) return;
+ jstring javaPublicId = env->NewStringUTF(publicId);
+ if (env->ExceptionCheck()) return;
+ jstring javaSystemId = env->NewStringUTF(systemId);
+ if (env->ExceptionCheck()) return;
+ jstring javaNotationName = env->NewStringUTF(notationName);
+ if (env->ExceptionCheck()) return;
+
+ env->CallVoidMethod(javaParser, unparsedEntityDeclMethod, javaName, javaPublicId, javaSystemId, javaNotationName);
+
+ env->DeleteLocalRef(javaName);
+ env->DeleteLocalRef(javaPublicId);
+ env->DeleteLocalRef(javaSystemId);
+ env->DeleteLocalRef(javaNotationName);
+}
+
+static void notationDecl(void* data, const char* name, const char* base, const char* systemId, const char* publicId) {
+ ParsingContext* parsingContext = reinterpret_cast<ParsingContext*>(data);
+ jobject javaParser = parsingContext->object;
+ JNIEnv* env = parsingContext->env;
+
+ // Bail out if a previously called handler threw an exception.
+ if (env->ExceptionCheck()) return;
+
+ jstring javaName = env->NewStringUTF(name);
+ if (env->ExceptionCheck()) return;
+ jstring javaPublicId = env->NewStringUTF(publicId);
+ if (env->ExceptionCheck()) return;
+ jstring javaSystemId = env->NewStringUTF(systemId);
+ if (env->ExceptionCheck()) return;
+
+ env->CallVoidMethod(javaParser, notationDeclMethod, javaName, javaPublicId, javaSystemId);
+
+ env->DeleteLocalRef(javaName);
+ env->DeleteLocalRef(javaPublicId);
+ env->DeleteLocalRef(javaSystemId);
+}
+
/**
* Releases the parsing context.
*/
@@ -945,15 +994,15 @@ static jint initialize(JNIEnv* env, jobject object, jstring javaEncoding,
XML_SetNamespaceDeclHandler(parser, startNamespace, endNamespace);
}
- XML_SetCommentHandler(parser, comment);
XML_SetCdataSectionHandler(parser, startCdata, endCdata);
-
- XML_SetElementHandler(parser, startElement, endElement);
XML_SetCharacterDataHandler(parser, text);
+ XML_SetCommentHandler(parser, comment);
XML_SetDoctypeDeclHandler(parser, startDtd, endDtd);
- XML_SetProcessingInstructionHandler(parser, processingInstruction);
+ XML_SetElementHandler(parser, startElement, endElement);
XML_SetExternalEntityRefHandler(parser, handleExternalEntity);
-
+ XML_SetNotationDeclHandler(parser, notationDecl);
+ XML_SetProcessingInstructionHandler(parser, processingInstruction);
+ XML_SetUnparsedEntityDeclHandler(parser, unparsedEntityDecl);
XML_SetUserData(parser, context);
} else {
releaseParsingContext(env, context);
@@ -1358,51 +1407,60 @@ static void freeAttributes(JNIEnv* env, jobject clazz, jint pointer) {
*
* @param clazz Java ExpatParser class
*/
-static void staticInitialize(JNIEnv* env, jobject clazz, jstring empty) {
- startElementMethod = env->GetMethodID((jclass) clazz, "startElement",
+static void staticInitialize(JNIEnv* env, jobject classObject, jstring empty) {
+ jclass clazz = reinterpret_cast<jclass>(classObject);
+ startElementMethod = env->GetMethodID(clazz, "startElement",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;II)V");
if (startElementMethod == NULL) return;
- endElementMethod = env->GetMethodID((jclass) clazz, "endElement",
+ endElementMethod = env->GetMethodID(clazz, "endElement",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (endElementMethod == NULL) return;
- textMethod = env->GetMethodID((jclass) clazz, "text", "([CI)V");
+ textMethod = env->GetMethodID(clazz, "text", "([CI)V");
if (textMethod == NULL) return;
- commentMethod = env->GetMethodID((jclass) clazz, "comment", "([CI)V");
+ commentMethod = env->GetMethodID(clazz, "comment", "([CI)V");
if (commentMethod == NULL) return;
- startCdataMethod = env->GetMethodID((jclass) clazz, "startCdata", "()V");
+ startCdataMethod = env->GetMethodID(clazz, "startCdata", "()V");
if (startCdataMethod == NULL) return;
- endCdataMethod = env->GetMethodID((jclass) clazz, "endCdata", "()V");
+ endCdataMethod = env->GetMethodID(clazz, "endCdata", "()V");
if (endCdataMethod == NULL) return;
- startDtdMethod = env->GetMethodID((jclass) clazz, "startDtd",
+ startDtdMethod = env->GetMethodID(clazz, "startDtd",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (startDtdMethod == NULL) return;
- endDtdMethod = env->GetMethodID((jclass) clazz, "endDtd", "()V");
+ endDtdMethod = env->GetMethodID(clazz, "endDtd", "()V");
if (endDtdMethod == NULL) return;
- startNamespaceMethod = env->GetMethodID((jclass) clazz, "startNamespace",
+ startNamespaceMethod = env->GetMethodID(clazz, "startNamespace",
"(Ljava/lang/String;Ljava/lang/String;)V");
if (startNamespaceMethod == NULL) return;
- endNamespaceMethod = env->GetMethodID((jclass) clazz, "endNamespace",
+ endNamespaceMethod = env->GetMethodID(clazz, "endNamespace",
"(Ljava/lang/String;)V");
if (endNamespaceMethod == NULL) return;
- processingInstructionMethod = env->GetMethodID((jclass) clazz,
+ processingInstructionMethod = env->GetMethodID(clazz,
"processingInstruction", "(Ljava/lang/String;Ljava/lang/String;)V");
if (processingInstructionMethod == NULL) return;
- handleExternalEntityMethod = env->GetMethodID((jclass) clazz,
+ handleExternalEntityMethod = env->GetMethodID(clazz,
"handleExternalEntity",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
if (handleExternalEntityMethod == NULL) return;
+ notationDeclMethod = env->GetMethodID(clazz, "notationDecl",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ if (notationDeclMethod == NULL) return;
+
+ unparsedEntityDeclMethod = env->GetMethodID(clazz, "unparsedEntityDecl",
+ "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
+ if (unparsedEntityDeclMethod == NULL) return;
+
// Look up String class.
stringClass = env->FindClass("java/lang/String");
diff --git a/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java b/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java
index 480bca3..f781611 100644
--- a/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java
+++ b/xml/src/test/java/org/apache/harmony/xml/ExpatParserTest.java
@@ -501,27 +501,67 @@ public class ExpatParserTest extends TestCase {
}
}
- public void testDtd() throws Exception {
- Reader in = new StringReader(
- "<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee'><a></a>");
+ private TestDtdHandler runDtdTest(String s) throws Exception {
+ Reader in = new StringReader(s);
ExpatReader reader = new ExpatReader();
TestDtdHandler handler = new TestDtdHandler();
reader.setContentHandler(handler);
+ reader.setDTDHandler(handler);
reader.setLexicalHandler(handler);
reader.parse(new InputSource(in));
+ return handler;
+ }
+ public void testDtdDoctype() throws Exception {
+ TestDtdHandler handler = runDtdTest("<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee'><a></a>");
assertEquals("foo", handler.name);
assertEquals("bar", handler.publicId);
assertEquals("tee", handler.systemId);
-
assertTrue(handler.ended);
}
+ public void testDtdUnparsedEntity_system() throws Exception {
+ TestDtdHandler handler = runDtdTest("<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee' [ <!ENTITY ent SYSTEM 'blah' NDATA poop> ]><a></a>");
+ assertEquals("ent", handler.ueName);
+ assertEquals(null, handler.uePublicId);
+ assertEquals("blah", handler.ueSystemId);
+ assertEquals("poop", handler.ueNotationName);
+ }
+
+ public void testDtdUnparsedEntity_public() throws Exception {
+ TestDtdHandler handler = runDtdTest("<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee' [ <!ENTITY ent PUBLIC 'a' 'b' NDATA poop> ]><a></a>");
+ assertEquals("ent", handler.ueName);
+ assertEquals("a", handler.uePublicId);
+ assertEquals("b", handler.ueSystemId);
+ assertEquals("poop", handler.ueNotationName);
+ }
+
+ public void testDtdNotation_system() throws Exception {
+ TestDtdHandler handler = runDtdTest("<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee' [ <!NOTATION sn SYSTEM 'nf2'> ]><a></a>");
+ assertEquals("sn", handler.ndName);
+ assertEquals(null, handler.ndPublicId);
+ assertEquals("nf2", handler.ndSystemId);
+ }
+
+ public void testDtdNotation_public() throws Exception {
+ TestDtdHandler handler = runDtdTest("<?xml version=\"1.0\"?><!DOCTYPE foo PUBLIC 'bar' 'tee' [ <!NOTATION pn PUBLIC 'nf1'> ]><a></a>");
+ assertEquals("pn", handler.ndName);
+ assertEquals("nf1", handler.ndPublicId);
+ assertEquals(null, handler.ndSystemId);
+ }
+
static class TestDtdHandler extends DefaultHandler2 {
String name;
String publicId;
String systemId;
+ String ndName;
+ String ndPublicId;
+ String ndSystemId;
+ String ueName;
+ String uePublicId;
+ String ueSystemId;
+ String ueNotationName;
boolean ended;
@@ -543,6 +583,21 @@ public class ExpatParserTest extends TestCase {
public void setDocumentLocator(Locator locator) {
this.locator = locator;
}
+
+ @Override
+ public void notationDecl(String name, String publicId, String systemId) {
+ this.ndName = name;
+ this.ndPublicId = publicId;
+ this.ndSystemId = systemId;
+ }
+
+ @Override
+ public void unparsedEntityDecl(String entityName, String publicId, String systemId, String notationName) {
+ this.ueName = entityName;
+ this.uePublicId = publicId;
+ this.ueSystemId = systemId;
+ this.ueNotationName = notationName;
+ }
}
public void testCdata() throws Exception {