summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile22
-rw-r--r--build.xml10
-rw-r--r--src/com/isode/stroke/parser/AaltoXMLParser.java91
-rw-r--r--src/com/isode/stroke/parser/PlatformXMLParserFactory.java2
-rw-r--r--src/com/isode/stroke/parser/PullXMLParser.java219
-rw-r--r--test/com/isode/stroke/parser/XMLParserTest.java6
6 files changed, 116 insertions, 234 deletions
diff --git a/Makefile b/Makefile
index 2880ade..30c97a4 100644
--- a/Makefile
+++ b/Makefile
@@ -1,5 +1,9 @@
all: dist/lib/stroke.jar
+DEFINES = -Dxpp-dir=third-party/xpp -Djzlib-dir=third-party/jzlib -Dicu4j-dir=third-party/ -Dstax2-dir=third-party/stax2/ -Daalto-dir=third-party/aalto/
+
+JUNIT ?= /usr/share/junit/junit.jar
+
.PHONY : clean
clean:
ant clean
@@ -10,12 +14,20 @@ distclean: clean
rm -rf third-party
.PHONY : dist/lib/stroke.jar
-dist/lib/stroke.jar: third-party/xpp/xpp.jar third-party/jzlib/jzlib.jar third-party/icu4j.jar
- ant -Dxpp-dir=third-party/xpp -Djzlib-dir=third-party/jzlib -Dicu4j-dir=third-party/
+dist/lib/stroke.jar: third-party/jzlib/jzlib.jar third-party/icu4j.jar third-party/aalto/aalto-xml.jar third-party/stax2/stax2-api.jar
+ ant ${DEFINES}
+
+.PHONY : test
+test: dist/lib/stroke.jar
+ ant ${DEFINES} -DJUNIT_JAR=${JUNIT} test
+
+third-party/aalto/aalto-xml.jar:
+ mkdir -p third-party/aalto
+ curl http://repo2.maven.org/maven2/com/fasterxml/aalto-xml/0.9.8/aalto-xml-0.9.8.jar -o third-party/aalto/aalto-xml.jar
-third-party/xpp/xpp.jar:
- mkdir -p third-party/xpp
- curl http://www.extreme.indiana.edu/dist/java-repository/xpp3/jars/xpp3-1.1.4c.jar -o third-party/xpp/xpp.jar
+third-party/stax2/stax2-api.jar:
+ mkdir -p third-party/stax2
+ curl http://repository.codehaus.org/org/codehaus/woodstox/stax2-api/3.0.3/stax2-api-3.0.3.jar -o third-party/stax2/stax2-api.jar
third-party/jzlib/jzlib.jar:
mkdir -p third-party
diff --git a/build.xml b/build.xml
index 6aaf392..454325d 100644
--- a/build.xml
+++ b/build.xml
@@ -16,12 +16,14 @@
<property name="main-class" value="com.isode.stroke.examples.gui.StrokeGUI"/>
<property name="compile.debug" value="true"/>
<property name="testsuiteclass" value="com.isode.stroke.unittest.StrokeTestSuite" />
- <property name="xpp-dir" value="../third-party/xpp"/>
+ <property name="aalto-dir" value="../third-party/aalto"/>
+ <property name="stax2-dir" value="../third-party/stax2"/>
<property name="jzlib-dir" value="../third-party/jzlib"/>
<property name="icu4j-dir" value="../third-party/icu4j"/>
<path id="classpath">
- <fileset dir="${xpp-dir}" includes="xpp.jar"/>
+ <fileset dir="${aalto-dir}" includes="aalto-xml.jar"/>
+ <fileset dir="${stax2-dir}" includes="stax2-api.jar"/>
<fileset dir="${jzlib-dir}" includes="jzlib.jar"/>
<fileset dir="${icu4j-dir}" includes="icu4j.jar"/>
</path>
@@ -93,9 +95,9 @@
sourcepath="${src}"
destdir="${doc}"
windowtitle="Stroke">
- <classpath>
+ <!--<classpath>
<fileset dir="${xpp-dir}" includes="xpp.jar"/>
- </classpath>
+ </classpath>-->
<link href="http://docs.oracle.com/javase/6/docs/api/"/>
</javadoc>
</target>
diff --git a/src/com/isode/stroke/parser/AaltoXMLParser.java b/src/com/isode/stroke/parser/AaltoXMLParser.java
new file mode 100644
index 0000000..041dc1e
--- /dev/null
+++ b/src/com/isode/stroke/parser/AaltoXMLParser.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * All rights reserved.
+ */
+package com.isode.stroke.parser;
+
+import com.fasterxml.aalto.AsyncInputFeeder;
+import com.fasterxml.aalto.AsyncXMLStreamReader;
+import com.fasterxml.aalto.stax.InputFactoryImpl;
+import com.isode.stroke.base.ByteArray;
+import com.isode.stroke.eventloop.EventLoop;
+import java.util.logging.Logger;
+import javax.xml.namespace.QName;
+import javax.xml.stream.XMLStreamConstants;
+import javax.xml.stream.XMLStreamException;
+
+/**
+ * Parser based around the Aalto XML parser
+ */
+class AaltoXMLParser extends XMLParser {
+
+ private final Logger logger_ = Logger.getLogger(this.getClass().getName());
+ private boolean error_ = false;
+ private final EventLoop eventLoop_;
+ private final AsyncXMLStreamReader xmlReader_ = new InputFactoryImpl().createAsyncXMLStreamReader();
+
+ public AaltoXMLParser(XMLParserClient client, EventLoop eventLoop) {
+ super(client);
+ eventLoop_ = eventLoop;
+ }
+
+
+ /**
+ * Cause the parser thread to parse these data.
+ */
+ @Override
+ public boolean parse(String data) {
+ if (data.isEmpty()) {
+ return false;
+ }
+ final AsyncInputFeeder inputFeeder = xmlReader_.getInputFeeder();
+ final byte[] xmlBytes = new ByteArray(data).getData();
+ int type = 0;
+ boolean error = false;
+
+ try {
+ inputFeeder.feedInput(xmlBytes, 0, xmlBytes.length);
+ } catch (XMLStreamException ex) {
+ error = true;
+ throw new IllegalStateException(ex);
+ }
+
+ try {
+ while ((type = xmlReader_.next()) != XMLStreamConstants.END_DOCUMENT && type != AsyncXMLStreamReader.EVENT_INCOMPLETE) {
+ QName name;
+ switch (type) {
+ case XMLStreamConstants.START_ELEMENT:
+ name = xmlReader_.getName();
+ AttributeMap attributes = new AttributeMap();
+ for (int i = 0; i < xmlReader_.getAttributeCount(); i++) {
+ QName attributeName = xmlReader_.getAttributeName(i);
+ attributes.addAttribute(attributeName.getLocalPart(), attributeName.getNamespaceURI(), xmlReader_.getAttributeValue(i));
+ }
+ getClient().handleStartElement(name.getLocalPart(), name.getNamespaceURI(), attributes);
+ break;
+ case XMLStreamConstants.END_ELEMENT:
+ name = xmlReader_.getName();
+ getClient().handleEndElement(name.getLocalPart(), name.getNamespaceURI());
+ break;
+ case XMLStreamConstants.CHARACTERS:
+ getClient().handleCharacterData(xmlReader_.getText());
+ break;
+ }
+
+ }
+ } catch (XMLStreamException e) {
+ error = true;
+ throw new IllegalStateException(e);
+ }
+ if (type == XMLStreamConstants.END_DOCUMENT) {
+ try {
+ xmlReader_.close();
+ } catch (XMLStreamException ex) {
+ /* If the parser errors while we're shutting down, it's not much of an error.*/
+ }
+ }
+ return !error;
+ }
+
+
+}
diff --git a/src/com/isode/stroke/parser/PlatformXMLParserFactory.java b/src/com/isode/stroke/parser/PlatformXMLParserFactory.java
index c1e44d6..000eb7f 100644
--- a/src/com/isode/stroke/parser/PlatformXMLParserFactory.java
+++ b/src/com/isode/stroke/parser/PlatformXMLParserFactory.java
@@ -16,6 +16,6 @@ public class PlatformXMLParserFactory {
* Unlike Swiften, this may be threaded, and therefore needs an eventloop.
*/
public static XMLParser createXMLParser(XMLParserClient client, EventLoop eventLoop) {
- return new PullXMLParser(client, eventLoop);
+ return new AaltoXMLParser(client, eventLoop);
}
}
diff --git a/src/com/isode/stroke/parser/PullXMLParser.java b/src/com/isode/stroke/parser/PullXMLParser.java
deleted file mode 100644
index 845dfbc..0000000
--- a/src/com/isode/stroke/parser/PullXMLParser.java
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * Copyright (c) 2010, Isode Limited, London, England.
- * All rights reserved.
- */
-package com.isode.stroke.parser;
-
-import com.isode.stroke.base.ByteArray;
-import com.isode.stroke.eventloop.Event.Callback;
-import com.isode.stroke.eventloop.EventLoop;
-import java.io.IOException;
-import java.io.PipedInputStream;
-import java.io.PipedOutputStream;
-import java.util.concurrent.ArrayBlockingQueue;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import org.xmlpull.mxp1.MXParser;
-import org.xmlpull.v1.XmlPullParser;
-import org.xmlpull.v1.XmlPullParserException;
-
-/**
- * Parser based around the XmlPullParser
- */
-class PullXMLParser extends XMLParser {
-
- private final Logger logger_ = Logger.getLogger(this.getClass().getName());
- private final XmlPullParser parser_ = new MXParser();
- private final PipedInputStream reader_;
- private final PipedOutputStream writer_;
- private final ArrayBlockingQueue<Event> events_ = new ArrayBlockingQueue<Event>(20);
- private final Thread parserThread_;
- private boolean error_ = false;
- private final EventLoop eventLoop_;
-
-
- private enum EventType {Start, End, Text};
-
- /**
- * XML Event struct.
- */
- private class Event {
- private final EventType type;
- private final String name;
- private final String namespace;
- private final AttributeMap attributes;
- public Event(EventType type, String name, String namespace, AttributeMap attributes) {
- this.type = type;
- this.name = name;
- this.namespace = namespace;
- this.attributes = attributes;
- }
-
- public Event(String name) {
- this(EventType.Text, name, null, null);
- }
-
-
- public Event(String name, String namespace) {
- this(EventType.End, name, namespace, null);
- }
-
- public Event(String name, String namespace, AttributeMap attributes) {
- this(EventType.Start, name, namespace, attributes);
- }
-
- }
-
- /**
- * Put an XML event onto the queue ready for the main thread to pick up later.
- */
- private void addEvent(Event event) throws InterruptedException {
- events_.put(event);
- }
-
- /**
- * Deal with whatever was just read out of the parser_.
- */
- private void handleEvent(int eventType) throws XmlPullParserException, InterruptedException {
- if (eventType == XmlPullParser.START_TAG) {
- AttributeMap map = new AttributeMap();
- for (int i = 0; i < parser_.getAttributeCount(); i++) {
- map.addAttribute(parser_.getAttributeName(i), parser_.getAttributeNamespace(i), parser_.getAttributeValue(i));
- }
- addEvent(new Event(parser_.getName(), parser_.getNamespace(), map));
- bump();
- } else if (eventType == XmlPullParser.END_TAG) {
- addEvent(new Event(parser_.getName(), parser_.getNamespace()));
- bump();
- } else if (eventType == XmlPullParser.TEXT) {
- StringBuilder text = new StringBuilder();
- int holderForStartAndLength[] = new int[2];
- char ch[] = parser_.getTextCharacters(holderForStartAndLength);
- int start = holderForStartAndLength[0];
- int length = holderForStartAndLength[1];
- for (int i = start; i < start + length; i++) {
- text.append(ch[i]);
- }
- addEvent(new Event(text.toString()));
- bump();
- } else if (eventType == XmlPullParser.START_DOCUMENT) {
- //System.out.println("Starting document");
- } else if (eventType == XmlPullParser.END_DOCUMENT) {
- //System.out.println("Ending document");
-
- } else {
- //System.out.println("Unhandled event");
- }
- }
-
- /**
- * Cause the main thread to process any outstanding events.
- */
- private void bump() {
- eventLoop_.postEvent(new Callback() {
- public void run() {
- processEvents();
- }
- });
- }
-
- public PullXMLParser(XMLParserClient client, EventLoop eventLoop) {
- super(client);
- eventLoop_ = eventLoop;
- writer_ = new PipedOutputStream();
- try {
- reader_ = new PipedInputStream(writer_, 128000);
- } catch (IOException ex) {
- Logger.getLogger(PullXMLParser.class.getName()).log(Level.SEVERE, null, ex);
- throw new IllegalStateException(ex);
- }
- try {
- parser_.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, true);
- parser_.setInput(reader_, "UTF-8");
- } catch (XmlPullParserException ex) {
- Logger.getLogger(PullXMLParser.class.getName()).log(Level.SEVERE, null, ex);
- throw new IllegalStateException(ex);
- }
- Runnable parserRunnable = new Runnable() {
- public void run() {
- int eventType = XmlPullParser.END_DOCUMENT - 1; /* Anything to make the following not true*/
- while (eventType != XmlPullParser.END_DOCUMENT) {
- try {
- parser_.next();
- eventType = parser_.getEventType();
- handleEvent(eventType);
- } catch (XmlPullParserException ex) {
- error_ = true;
- Logger.getLogger(PullXMLParser.class.getName()).log(Level.SEVERE, null, ex);
- break;
- } catch (IOException ex) {
- error_ = true;
- Logger.getLogger(PullXMLParser.class.getName()).log(Level.SEVERE, null, ex);
- break;
- } catch (InterruptedException ex) {
- /* The thread was interrupted while trying to process an event - presumably this is because we're shutting down.*/
- error_ = true;
- Logger.getLogger(PullXMLParser.class.getName()).log(Level.SEVERE, null, ex);
- break;
- }
- }
- }
- };
- parserThread_ = new Thread(parserRunnable);
- parserThread_.setDaemon(true);
- parserThread_.start();
- }
-
- /**
- * Do not do this!
- * This is only to allow the unit tests to join onto it.
- * @return
- */
- Thread getParserThread() {
- return parserThread_;
- }
-
- /**
- * Process outstanding events.
- * Call in the main thread only.
- */
- private void processEvents() {
- while (events_.size() > 0) {
- processEvent(events_.poll());
- }
- }
-
- /**
- * Main thread only.
- */
- private void processEvent(Event event) {
- String name = event.name;
- String namespace = event.namespace;
- AttributeMap attributes = event.attributes;
- switch (event.type) {
- case Start: getClient().handleStartElement(name, namespace, attributes); break;
- case End: getClient().handleEndElement(name, namespace); break;
- case Text: getClient().handleCharacterData(name); break;
- }
- }
-
- /**
- * Cause the parser thread to parse these data later.
- * Note that the return code is a best guess based on previous parsing,
- * and will almost always give a false negative on a stanza before a
- * true negative. True negatives will always mean an error in the stream.
- */
- @Override
- public boolean parse(String data) {
- try {
- writer_.write(new ByteArray(data).getData());
- writer_.flush();
- } catch (IOException ex) {
- error_ = true;
- Logger.getLogger(PullXMLParser.class.getName()).log(Level.SEVERE, null, ex);
- }
- return !error_;
- }
-
-
-}
diff --git a/test/com/isode/stroke/parser/XMLParserTest.java b/test/com/isode/stroke/parser/XMLParserTest.java
index e3f054b..a1b5d1c 100644
--- a/test/com/isode/stroke/parser/XMLParserTest.java
+++ b/test/com/isode/stroke/parser/XMLParserTest.java
@@ -31,11 +31,7 @@ public class XMLParserTest {
}
private void join(XMLParser parser) {
- try {
- ((PullXMLParser) parser).getParserThread().join(300);
- } catch (InterruptedException ex) {
- Logger.getLogger(XMLParserTest.class.getName()).log(Level.SEVERE, null, ex);
- }
+
}
@Test