Author: ngn
Date: Wed May 5 13:19:13 2010
New Revision: 941276
URL: http://svn.apache.org/viewvc?rev=941276&view=rev
Log:
Moving stream restart into the parser, rather than in the decoder
Added:
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/StreamRestartTestCase.java
Modified:
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/DefaultNonBlockingXMLReader.java
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLParser.java
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/AbstractAsyncXMLReaderTestCase.java
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/ParseCommentsTestCase.java
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/TestHandler.java
Modified:
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java
(original)
+++
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPContentHandler.java
Wed May 5 13:19:13 2010
@@ -187,5 +187,8 @@ public class XMPPContentHandler implemen
/**
* {...@inheritdoc}
*/
- public void startDocument() throws SAXException { /* ignore */ }
+ public void startDocument() throws SAXException {
+ depth = 0;
+ builder = null;
+ }
}
Modified:
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java
(original)
+++
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/decoder/XMPPDecoder.java
Wed May 5 13:19:13 2010
@@ -75,17 +75,16 @@ public class XMPPDecoder extends Cumulat
IoBuffer in, ProtocolDecoderOutput out) throws
Exception {
NonBlockingXMLReader reader = (NonBlockingXMLReader)
session.getAttribute(SESSION_ATTRIBUTE_NAME);
- // peek to find XML stream resets
- // TODO this is a bit ugly, revisit
- in.mark();
- String peek = in.getString(14, CharsetUtil.UTF8_DECODER);
- in.reset();
-
- if (reader == null || STREAM_STREAM.equals(peek) || (peek != null &&
peek.startsWith(XML_DECL))) {
+ if (reader == null) {
reader = new DefaultNonBlockingXMLReader();
// we need to check the jabber:client/jabber:server NS
declarations
reader.setFeature(DefaultNonBlockingXMLReader.FEATURE_NAMESPACE_PREFIXES, true);
+
+ // allow parser to restart XML stream
+
reader.setFeature(DefaultNonBlockingXMLReader.FEATURE_RESTART_ALLOWED, true);
+
reader.setProperty(DefaultNonBlockingXMLReader.PROPERTY_RESTART_QNAME,
"stream:stream");
+
reader.setContentHandler(new
XMPPContentHandler(builderFactory));
session.setAttribute(SESSION_ATTRIBUTE_NAME, reader);
Modified:
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/DefaultNonBlockingXMLReader.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/DefaultNonBlockingXMLReader.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/DefaultNonBlockingXMLReader.java
(original)
+++
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/DefaultNonBlockingXMLReader.java
Wed May 5 13:19:13 2010
@@ -44,6 +44,8 @@ public class DefaultNonBlockingXMLReader
public static final String FEATURE_NAMESPACES =
"http://xml.org/sax/features/namespaces";
public static final String FEATURE_NAMESPACE_PREFIXES =
"http://xml.org/sax/features/namespace-prefixes";
public static final String FEATURE_COMMENTS_ALLOWED =
"http://mina.apache.org/vysper/features/comments-allowed";
+ public static final String FEATURE_RESTART_ALLOWED =
"http://mina.apache.org/vysper/features/restart-allowed";
+ public static final String PROPERTY_RESTART_QNAME =
"http://mina.apache.org/vysper/properties/restart-qname";
private ErrorHandler errorHandler = new DefaultHandler();
private ContentHandler contentHandler = new DefaultHandler();
@@ -51,12 +53,14 @@ public class DefaultNonBlockingXMLReader
private XMLParser parser;
private Map<String, Boolean> features = new HashMap<String, Boolean>();
+ private Map<String, Object> properties = new HashMap<String, Object>();
public DefaultNonBlockingXMLReader() {
// set default features
features.put(FEATURE_NAMESPACES, true);
features.put(FEATURE_NAMESPACE_PREFIXES, false);
features.put(FEATURE_COMMENTS_ALLOWED, true);
+ features.put(FEATURE_RESTART_ALLOWED, false);
}
/**
@@ -91,6 +95,8 @@ public class DefaultNonBlockingXMLReader
features.put(FEATURE_NAMESPACE_PREFIXES, value);
} else if(name.equals(FEATURE_COMMENTS_ALLOWED)) {
features.put(FEATURE_COMMENTS_ALLOWED, value);
+ } else if(name.equals(FEATURE_RESTART_ALLOWED)) {
+ features.put(FEATURE_RESTART_ALLOWED, value);
} else {
throw new SAXNotSupportedException("Not supported");
}
@@ -105,7 +111,7 @@ public class DefaultNonBlockingXMLReader
*/
public Object getProperty (String name)
throws SAXNotRecognizedException, SAXNotSupportedException {
- return null;
+ return properties.get(name);
}
/**
@@ -113,7 +119,7 @@ public class DefaultNonBlockingXMLReader
*/
public void setProperty (String name, Object value)
throws SAXNotRecognizedException, SAXNotSupportedException {
-
+ properties.put(name, value);
}
/**
@@ -174,7 +180,7 @@ public class DefaultNonBlockingXMLReader
*/
public void parse (IoBuffer buffer, CharsetDecoder decoder) throws
IOException, SAXException {
if(parser == null) {
- parser = new XMLParser(contentHandler, errorHandler, features);
+ parser = new XMLParser(contentHandler, errorHandler, features,
properties);
}
parser.parse(buffer, decoder);
Modified:
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLParser.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLParser.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLParser.java
(original)
+++
mina/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xml/sax/impl/XMLParser.java
Wed May 5 13:19:13 2010
@@ -94,16 +94,22 @@ public class XMLParser implements TokenL
private boolean sentStartDocument = false;
// features
- boolean reportNsAttributes = false;
- boolean commentsAllowed = true;
+ private boolean reportNsAttributes = false;
+ private boolean commentsAllowed = true;
+ private boolean restartsAllowed = false;
+ private String restartQname = null;
- public XMLParser(ContentHandler contentHandler, ErrorHandler
errorHandler, Map<String, Boolean> features) {
+ public XMLParser(ContentHandler contentHandler, ErrorHandler
errorHandler, Map<String, Boolean> features, Map<String, Object> properties) {
this.contentHandler = contentHandler;
this.errorHandler = errorHandler;
commentsAllowed = feature(features,
DefaultNonBlockingXMLReader.FEATURE_COMMENTS_ALLOWED, true);
reportNsAttributes = feature(features,
DefaultNonBlockingXMLReader.FEATURE_NAMESPACE_PREFIXES, false);
+ reportNsAttributes = feature(features,
DefaultNonBlockingXMLReader.FEATURE_NAMESPACE_PREFIXES, false);
+ restartsAllowed = feature(features,
DefaultNonBlockingXMLReader.FEATURE_RESTART_ALLOWED, false);
+ restartQname =
(String)properties.get(DefaultNonBlockingXMLReader.PROPERTY_RESTART_QNAME);
+
this.tokenizer = new XMLTokenizer(this);
}
@@ -148,6 +154,7 @@ public class XMLParser implements TokenL
state = State.IN_END_TAG;
} else if(c == '?') {
state = State.IN_DECLARATION;
+ xmlDeclaration();
} else if(c == '!') {
if(commentsAllowed) {
state = State.AFTER_COMMENT_BANG;
@@ -320,6 +327,31 @@ public class XMLParser implements TokenL
return NAME_PATTERN.matcher(name).find() &&
!NAME_PREFIX_PATTERN.matcher(name).find();
}
+ private boolean needsRestart() {
+ return elements.size() > 0;
+ }
+
+ private void restart() {
+ log.trace("Restarting XML stream");
+
+ elements.clear();
+ nsResolver = new ParserNamespaceResolver();
+ sentStartDocument = false;
+ }
+
+ private void xmlDeclaration() {
+ // we got an XML declaration, should we restart stream?
+ // TODO could also be a PI, if we want to support PIs, this
code needs further attention
+ if(needsRestart()) {
+ if(restartsAllowed) {
+ // ok, restart
+ restart();
+ } else {
+ // restarts not allowed, fail
+ }
+ }
+ }
+
private void startDocument() throws SAXException {
if(!sentStartDocument) {
contentHandler.startDocument();
@@ -330,6 +362,11 @@ public class XMLParser implements TokenL
private void startElement() throws SAXException {
log.trace("StartElement {}", qname);
+ // check if this should restart stream
+ if(restartsAllowed && needsRestart() &&
qname.equals(restartQname)) {
+ restart();
+ }
+
if(elements.isEmpty()) {
startDocument();
}
Modified:
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/AbstractAsyncXMLReaderTestCase.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/AbstractAsyncXMLReaderTestCase.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/AbstractAsyncXMLReaderTestCase.java
(original)
+++
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/AbstractAsyncXMLReaderTestCase.java
Wed May 5 13:19:13 2010
@@ -117,10 +117,10 @@ public abstract class AbstractAsyncXMLRe
}
protected List<TestEvent> parse(String xml) throws Exception {
- return parse(xml, null);
+ return parse(xml, null, null);
}
- protected List<TestEvent> parse(String xml, Map<String, Boolean>
features) throws Exception {
+ protected List<TestEvent> parse(String xml, Map<String, Boolean>
features, Map<String, Object> properties) throws Exception {
TestHandler handler = new TestHandler();
NonBlockingXMLReader reader = new DefaultNonBlockingXMLReader();
if(features != null) {
@@ -128,6 +128,11 @@ public abstract class AbstractAsyncXMLRe
reader.setFeature(feature.getKey(),
feature.getValue());
}
}
+ if(properties != null) {
+ for(Entry<String, Object> property :
properties.entrySet()) {
+ reader.setProperty(property.getKey(),
property.getValue());
+ }
+ }
reader.setContentHandler(handler);
reader.setErrorHandler(handler);
Modified:
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/ParseCommentsTestCase.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/ParseCommentsTestCase.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/ParseCommentsTestCase.java
(original)
+++
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/ParseCommentsTestCase.java
Wed May 5 13:19:13 2010
@@ -117,7 +117,7 @@ public class ParseCommentsTestCase exten
Map<String, Boolean> features = new HashMap<String, Boolean>();
features.put("http://mina.apache.org/vysper/features/comments-allowed", false);
- Iterator<TestEvent> events = parse("<root><!-- comment
--></root>", features).iterator();
+ Iterator<TestEvent> events = parse("<root><!-- comment
--></root>", features, null).iterator();
assertStartDocument(events.next());
assertStartElement("", "root", "root", events.next());
Added:
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/StreamRestartTestCase.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/StreamRestartTestCase.java?rev=941276&view=auto
==============================================================================
---
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/StreamRestartTestCase.java
(added)
+++
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/StreamRestartTestCase.java
Wed May 5 13:19:13 2010
@@ -0,0 +1,76 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+package org.apache.vysper.xml.sax.impl;
+
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.vysper.xml.sax.impl.TestHandler.TestEvent;
+
+
+/**
+ * @author The Apache MINA Project ([email protected])
+ */
+public class StreamRestartTestCase extends AbstractAsyncXMLReaderTestCase {
+
+ public void testRestartByXmlDeclaration() throws Exception {
+ Map<String, Boolean> features = new HashMap<String, Boolean>();
+
features.put(DefaultNonBlockingXMLReader.FEATURE_RESTART_ALLOWED, true);
+
+ Iterator<TestEvent> events = parse("<?xml version=\"1.0\"?>\n
<root><?xml version=\"1.0\"?><root />", features, null).iterator();
+
+ assertStartDocument(events.next());
+ // no event for the declaration
+ assertStartElement("", "root", "root", events.next());
+
+ // parser gets restarted
+ assertStartDocument(events.next());
+ assertStartElement("", "root", "root", events.next());
+ assertEndElement("", "root", "root", events.next());
+ assertEndDocument(events.next());
+
+ assertNoMoreevents(events);
+ }
+
+ public void testRestartByQName() throws Exception {
+ Map<String, Boolean> features = new HashMap<String, Boolean>();
+
features.put(DefaultNonBlockingXMLReader.FEATURE_RESTART_ALLOWED, true);
+
+ Map<String, Object> properties = new HashMap<String, Object>();
+
properties.put(DefaultNonBlockingXMLReader.PROPERTY_RESTART_QNAME, "root");
+
+ Iterator<TestEvent> events = parse("<root><foo><root />",
features, properties).iterator();
+
+ assertStartDocument(events.next());
+ // no event for the declaration
+ assertStartElement("", "root", "root", events.next());
+ assertStartElement("", "foo", "foo", events.next());
+
+ // parser gets restarted
+ assertStartDocument(events.next());
+ assertStartElement("", "root", "root", events.next());
+ assertEndElement("", "root", "root", events.next());
+ assertEndDocument(events.next());
+
+ assertNoMoreevents(events);
+ }
+
+}
Modified:
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/TestHandler.java
URL:
http://svn.apache.org/viewvc/mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/TestHandler.java?rev=941276&r1=941275&r2=941276&view=diff
==============================================================================
---
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/TestHandler.java
(original)
+++
mina/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xml/sax/impl/TestHandler.java
Wed May 5 13:19:13 2010
@@ -213,6 +213,7 @@ public class TestHandler implements Cont
public void startElement(String uri, String localName, String qName,
Attributes atts) throws SAXException {
+ System.out.println("sax start element " + qName);
events.add(new StartElementEvent(uri, localName, qName, atts));
}