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/01/03 22:26:01 UTC

svn commit: r895481 - in /mina/sandbox/vysper/branches/nbxml-sax/src: main/java/org/apache/vysper/xml/sax/impl/ test/java/org/apache/vysper/xml/sax/

Author: ngn
Date: Sun Jan  3 21:26:01 2010
New Revision: 895481

URL: http://svn.apache.org/viewvc?rev=895481&view=rev
Log:
Ugly implementation of namespace support in the parser. Next up, clean up.

Added:
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/StackNamespaceResolver2.java
    mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseNamespacesTestCase.java
Modified:
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java
    mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java
    mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/XMPPContentHandlerTestCase.java

Modified: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java?rev=895481&r1=895480&r2=895481&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java Sun Jan  3 21:26:01 2010
@@ -90,14 +90,13 @@
 
 	public String getURI(int index) {
 		if(index < 0 || index >= attributes.size()) return null;
-		
+
 		return attributes.get(index).getURI();
 	}
 
 	public String getValue(int index) {
 		if(index < 0 || index >= attributes.size()) return null;
-		
-		return attributes.get(index).getURI();
+		return attributes.get(index).getValue();
 	}
 
 	public String getValue(String qName) {

Modified: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java?rev=895481&r1=895480&r2=895481&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java Sun Jan  3 21:26:01 2010
@@ -21,11 +21,16 @@
 
 import java.nio.charset.CharsetDecoder;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Stack;
+import java.util.Map.Entry;
 import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.smartcardio.ATR;
+
 import org.apache.mina.common.ByteBuffer;
 import org.apache.vysper.xml.sax.impl.ParticleTokenizer.TokenListener;
 import org.slf4j.Logger;
@@ -52,6 +57,8 @@
 	
 	private ContentHandler contentHandler;
 	private ErrorHandler errorHandler;
+	
+	private StackNamespaceResolver2 nsResolver = new StackNamespaceResolver2();
 
 	private static enum State {
 		START,
@@ -68,7 +75,9 @@
 	private ParticleTokenizer tokenizer;
 	private State state = State.START;
 	private String qname;
-	private List<Attribute> attributes;
+	
+	// qname/value map
+	private Map<String, String> attributes;
 	private String attributeName;
 
 	// element names as {uri}qname
@@ -94,7 +103,7 @@
 		if(state == State.START) {
 			if(token.equals("<")) {
 				state = State.IN_TAG;
-				attributes = new ArrayList<Attribute>();
+				attributes = new HashMap<String, String>();
 			} else {
 				characters(token);
 			}
@@ -136,7 +145,7 @@
 			}
 		} else if(state == State.AFTER_ATTRIBUTE_EQUALS) {
 			// token must be attribute value
-			attributes.add(new Attribute(attributeName, "", attributeName, unescape(token)));
+			attributes.put(attributeName, unescape(token));
 			state = State.AFTER_START_NAME;
 		} else if(state == State.AFTER_END_NAME) {
 			// token must be >
@@ -189,11 +198,55 @@
         	return;
         }
 
-		String uri = "";
+
+		// find all namespace declarations so we can populate the NS resolver
+		Map<String, String> nsDeclarations = new HashMap<String, String>();
+		for(Entry<String, String> attribute: attributes.entrySet()) {
+			if(attribute.getKey().equals("xmlns")) {
+				// is namespace attribute
+				nsDeclarations.put("", attribute.getValue());
+			} else if(attribute.getKey().startsWith("xmlns:")) {
+				nsDeclarations.put(attribute.getKey().substring(6), attribute.getValue());
+			}
+		}
+		nsResolver.push(nsDeclarations);
+		
+		// find all non-namespace attributes
+		List<Attribute> nonNsAttributes = new ArrayList<Attribute>();
+		for(Entry<String, String> attribute: attributes.entrySet()) {
+			String attQname = attribute.getKey();
+			if(!attQname.equals("xmlns")  && !attQname.startsWith("xmlns:")) {
+				String attLocalName = extractLocalName(attQname);
+				String attPrefix = extractNsPrefix(attQname);
+				String attUri = nsResolver.resolveUri(attPrefix);
+				if(attUri == null) {
+					if(attPrefix.length() > 0) {
+						fatalError("Undeclared namespace prefix: " + attPrefix);
+						return;
+					} else {
+						attUri = "";
+					}
+				}
+				nonNsAttributes.add(new Attribute(attLocalName, attUri, attQname, attribute.getValue()));
+			}
+		}
+
+		String prefix = extractNsPrefix(qname);
+		String uri = nsResolver.resolveUri(prefix);
+		if(uri == null) {
+			if(prefix.length() > 0) {
+				fatalError("Undeclared namespace prefix: " + prefix);
+				return;
+			} else {
+				uri = "";
+			}
+		}
+		
 		String localName = extractLocalName(qname);
 		
 		elements.add(fullyQualifiedName(uri, qname));
-		contentHandler.startElement(uri, localName, qname, new DefaultAttributes(attributes));
+		
+		contentHandler.startElement(uri, localName, qname, new DefaultAttributes(nonNsAttributes));
 	}
 
 	private String extractLocalName(String qname) {
@@ -205,6 +258,17 @@
 			return qname;
 		}
 	}
+
+	private String extractNsPrefix(String qname) {
+		int index = qname.indexOf(':');
+		
+		if(index > -1 ) {
+			return qname.substring(0, index);
+		} else {
+			return "";
+		}
+	}
+
 	
 	private String fullyQualifiedName(String uri, String qname) {
 		return "{" + uri + "}" + qname;
@@ -215,7 +279,19 @@
 
 		if(state == State.CLOSED) return;
 		
-		String uri = "";
+		String prefix = extractNsPrefix(qname);
+		String uri = nsResolver.resolveUri(prefix);
+		if(uri == null) {
+			if(prefix.length() > 0) {
+				fatalError("Undeclared namespace prefix: " + prefix);
+				return;
+			} else {
+				uri = "";
+			}
+		}
+		
+		nsResolver.pop();
+		
 		String localName = extractLocalName(qname);
 		
 		String fqn = elements.pop();

Modified: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java?rev=895481&r1=895480&r2=895481&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java Sun Jan  3 21:26:01 2010
@@ -106,10 +106,12 @@
             		emit(byteBuffer, decoder);
             		emit("=", byteBuffer);
             	} else if(c == '"') {
+            		lastPosition = byteBuffer.position();
 //            		emit("\"", byteBuffer);
             		state = State.IN_DOUBLE_ATTRIBUTE_VALUE;
             	} else if(c == '\'') {
 //            		emit("\'", byteBuffer);
+            		lastPosition = byteBuffer.position();
             		state = State.IN_SINGLE_ATTRIBUTE_VALUE;
             	} else {
             		// non-whitespace char

Added: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/StackNamespaceResolver2.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/StackNamespaceResolver2.java?rev=895481&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/StackNamespaceResolver2.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/StackNamespaceResolver2.java Sun Jan  3 21:26:01 2010
@@ -0,0 +1,87 @@
+/*
+ *  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.Map;
+import java.util.Stack;
+import java.util.Map.Entry;
+
+import org.apache.vysper.xml.fragment.NamespaceResolver;
+import org.apache.vysper.xml.fragment.NamespaceURIs;
+
+
+/**
+ * Naive implementation, will be replaced in later stages of this change
+ */
+public class StackNamespaceResolver2 implements NamespaceResolver {
+	
+	private Stack<Map<String, String>> elements = new Stack<Map<String, String>>();
+	
+	public StackNamespaceResolver2() {
+	}
+
+	public void push(Map<String, String> elmXmlns) {
+		elements.push(elmXmlns);
+	}
+
+	public void pop() {
+		elements.pop();
+	}
+	
+	public String resolveUri(String prefix) {
+		// check for the reserved xml namespace
+		if(prefix.equals("xml")) {
+			return NamespaceURIs.XML;
+		} else {
+			// walk over the stack backwards
+			for(int i = elements.size() - 1; i>=0; i--) {
+				Map<String, String> ns = elements.get(i);
+				if(ns.containsKey(prefix)) {
+					return ns.get(prefix);
+				}
+			}
+		}
+		
+		
+		// could not resolve URI
+		return null;
+	}
+	
+
+	
+	public String resolvePrefix(String uri) {
+		if(uri.equals(NamespaceURIs.XML)) {
+			return "xml";
+		} else {
+			// walk over the stack backwards
+			for(int i = elements.size() - 1; i>=0; i--) {
+				Map<String, String> ns = elements.get(i);
+				for(Entry<String, String> entry : ns.entrySet()) {
+					if(entry.getValue().equals(uri)) {
+						return entry.getKey();
+					}
+				}
+			}
+		}
+
+		return null;
+	}
+}

Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java?rev=895481&r1=895480&r2=895481&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java Sun Jan  3 21:26:01 2010
@@ -89,4 +89,17 @@
 		
 		assertFalse(events.hasNext());
 	}
+
+	// Namespace declarations should not be included in attribute
+	public void testExcludeNsAttributes() throws Exception {
+		Iterator<TestEvent> events = parse("<root att='foo' xmlns:p='http://bar.com' />").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", attributes(new Attribute("att", "", "att", "foo")), events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
 }
\ No newline at end of file

Added: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseNamespacesTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseNamespacesTestCase.java?rev=895481&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseNamespacesTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseNamespacesTestCase.java Sun Jan  3 21:26:01 2010
@@ -0,0 +1,126 @@
+/*
+ *  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;
+
+import java.util.Iterator;
+
+import org.apache.vysper.xml.sax.TestHandler.TestEvent;
+import org.apache.vysper.xml.sax.impl.Attribute;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class ParseNamespacesTestCase extends AbstractAsyncXMLReaderTestCase {
+
+	public void testNamespacedElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root xmlns='urn:test'></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "root", events.next());
+		assertEndElement("urn:test", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testNamespacedAttribute() throws Exception {
+		Iterator<TestEvent> events = parse("<root p:att='foo' xmlns:p='urn:test'></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", attributes(new Attribute("att", "urn:test", "p:att", "foo")), events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	
+	public void testSimpleQNameElement() throws Exception {
+		Iterator<TestEvent> events = parse("<p:root xmlns:p='urn:test'></p:root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "p:root", events.next());
+		assertEndElement("urn:test", "root", "p:root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testNamespacedInheritanceElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root xmlns='urn:test'><child /></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "root", events.next());
+		assertStartElement("urn:test", "child", "child", events.next());
+		assertEndElement("urn:test", "child", "child", events.next());
+		assertEndElement("urn:test", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+	
+	public void testOverrideNamespacedElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root xmlns='urn:test'><child xmlns='urn:child' /></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "root", events.next());
+		assertStartElement("urn:child", "child", "child", events.next());
+		assertEndElement("urn:child", "child", "child", events.next());
+		assertEndElement("urn:test", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testResetNamespacedElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root xmlns='urn:test'><child xmlns='' /></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "root", events.next());
+		assertStartElement("", "child", "child", events.next());
+		assertEndElement("", "child", "child", events.next());
+		assertEndElement("urn:test", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testInvalidPrefixElement() throws Exception {
+		Iterator<TestEvent> events = parse("<p1:root xmlns:p1='urn:test' xmlns:p2='urn:test'></p2:root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "p1:root", events.next());
+		assertFatalError(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testInvalidNamespaceElement() throws Exception {
+		Iterator<TestEvent> events = parse("<p1:root xmlns:p1='urn:test' xmlns:p2='urn:foo'></p2:root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("urn:test", "root", "p1:root", events.next());
+		assertFatalError(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+}
\ No newline at end of file

Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/XMPPContentHandlerTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/XMPPContentHandlerTestCase.java?rev=895481&r1=895480&r2=895481&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/XMPPContentHandlerTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/XMPPContentHandlerTestCase.java Sun Jan  3 21:26:01 2010
@@ -53,7 +53,7 @@
 		
 		reader.setContentHandler(handler);
 	
-		parse(reader, "<stanza:stanza>");
+		parse(reader, "<stanza:stanza xmlns:stanza='http://etherx.jabber.org/streams'>");
 		parse(reader, "<message></message>");
 		parse(reader, "<iq>");
 		parse(reader, "</iq>");