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