You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ng...@apache.org on 2010/05/05 15:19:14 UTC
svn commit: r941276 - in /mina/vysper/trunk/nbxml/src:
main/java/org/apache/vysper/xml/decoder/
main/java/org/apache/vysper/xml/sax/impl/
test/java/org/apache/vysper/xml/sax/impl/
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 (dev@mina.apache.org)
+ */
+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));
}