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));
                
        }


Reply via email to