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/01 22:11:44 UTC
svn commit: r895076 - in /mina/sandbox/vysper/branches/nbxml-sax: ./
src/main/java/org/apache/vysper/xml/decoder/
src/main/java/org/apache/vysper/xml/sax/impl/
src/test/java/org/apache/vysper/xml/decoder/
src/test/java/org/apache/vysper/xml/sax/ src/te...
Author: ngn
Date: Fri Jan 1 21:11:43 2010
New Revision: 895076
URL: http://svn.apache.org/viewvc?rev=895076&view=rev
Log:
Parser now based on a tokenizer/state machine combo. Attribute tests now all succeed. Next up, namespace support
Added:
mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLToken.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/resources/
mina/sandbox/vysper/branches/nbxml-sax/src/test/resources/log4j.properties
Removed:
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/decoder/
Modified:
mina/sandbox/vysper/branches/nbxml-sax/pom.xml
mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseElementsTestCase.java
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java
mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java
Modified: mina/sandbox/vysper/branches/nbxml-sax/pom.xml
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/pom.xml?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/pom.xml (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/pom.xml Fri Jan 1 21:11:43 2010
@@ -41,6 +41,18 @@
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
+
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-log4j12</artifactId>
+ <scope>test</scope>
+ </dependency>
+
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
Added: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLToken.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLToken.java?rev=895076&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLToken.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLToken.java Fri Jan 1 21:11:43 2010
@@ -0,0 +1,52 @@
+/*
+ * 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.decoder;
+
+
+/**
+ * holds a particle of XML, either representing an start or end element, or an elements body, or other text nodes.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class XMLToken {
+
+ public static enum Type {
+ START_NAME,
+ END_NAME,
+ ATTRIBUTE_NAME,
+ ATTRIBUTE_VALUE,
+ COMMENT,
+ TEXT
+ }
+
+ private Type type;
+ private String value;
+ public XMLToken(Type type, String value) {
+ this.type = type;
+ this.value = value;
+ }
+
+ public Type getType() {
+ return type;
+ }
+ public String getValue() {
+ return value;
+ }
+}
Modified: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java Fri Jan 1 21:11:43 2010
@@ -21,12 +21,8 @@
import java.io.IOException;
import java.nio.charset.CharsetDecoder;
-import java.util.Stack;
import org.apache.mina.common.ByteBuffer;
-import org.apache.vysper.xml.decoder.DecodingException;
-import org.apache.vysper.xml.decoder.ParticleDecoder;
-import org.apache.vysper.xml.decoder.XMLParticle;
import org.apache.vysper.xml.sax.AsyncXMLReader;
import org.xml.sax.ContentHandler;
import org.xml.sax.DTDHandler;
@@ -35,7 +31,6 @@
import org.xml.sax.SAXException;
import org.xml.sax.SAXNotRecognizedException;
import org.xml.sax.SAXNotSupportedException;
-import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
@@ -46,12 +41,8 @@
private ErrorHandler errorHandler = new DefaultHandler();
private ContentHandler contentHandler = new DefaultHandler();
-
- private boolean documentStarted = false;
- private boolean parserClosed = false;
-
- // element names as {uri}qname
- private Stack<String> elements = new Stack<String>();
+
+ private Parser parser;
/**
* {@inheritDoc}
@@ -140,74 +131,15 @@
return errorHandler;
}
- private String toFQEN(XMLParticle particle) throws DecodingException {
- return "{}" + particle.getElementName();
- }
-
- private void fatalError(String msg) throws SAXException {
- parserClosed = true;
- errorHandler.fatalError(new SAXParseException(msg, null));
- }
-
/**
* {@inheritDoc}
*/
public void parse (ByteBuffer buffer, CharsetDecoder decoder) throws IOException, SAXException {
- if(parserClosed) {
- throw new SAXException("Parser closed");
+ if(parser == null) {
+ parser = new Parser(contentHandler, errorHandler);
}
- try {
- XMLParticle particle = ParticleDecoder.decodeParticle(buffer, decoder);
- while(particle != null) {
- if(!documentStarted) {
- // TODO handle exception
- contentHandler.startDocument();
- documentStarted = true;
- }
-
- if(particle.isOpeningElement()) {
- // TODO handle exception
- contentHandler.startElement("", particle.getElementName(), particle.getElementName(), new DefaultAttributes());
- elements.push(toFQEN(particle));
- }
-
- if(particle.isClosingElement()) {
- String fqen = elements.pop();
- if(!fqen.equals(toFQEN(particle))) {
- fatalError("Incorrect closing element");
- return;
- }
-
- // TODO handle exception
- contentHandler.endElement("", particle.getElementName(), particle.getElementName());
- }
-
- if(particle.isText()) {
- if(elements.size() == 0) {
- fatalError("Illegal placement of text");
- return;
- }
-
-
- char[] ch = particle.getContent().toCharArray();
- // TODO handle exception
- contentHandler.characters(ch, 0, ch.length);
- }
-
- if(elements.size() == 0) {
- parserClosed = true;
- // TODO handle exception
- contentHandler.endDocument();
- }
-
- particle = ParticleDecoder.decodeParticle(buffer, decoder);
- }
- } catch (IOException e) {
- throw e;
- } catch(Exception e) {
- fatalError(e.getMessage());
- }
+ parser.parse(buffer, decoder);
}
Added: 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=895076&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Parser.java Fri Jan 1 21:11:43 2010
@@ -0,0 +1,250 @@
+/*
+ * 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.nio.charset.CharsetDecoder;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.vysper.xml.sax.impl.ParticleTokenizer.TokenListener;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class Parser implements TokenListener {
+
+ private Logger LOG = LoggerFactory.getLogger(Parser.class);
+
+ private static final String nameStartChar = ":A-Z_a-z\\u00C0-\\u00D6\\u00D8-\\u00F6\\u00F8-\\u02FF\\u0370-\\u037D\\u037F-\\u1FFF\\u200C-\\u200D\\u2070-\\u218F\\u2C00-\\u2FEF\\u3001-\\uD7FF\\uF900-\\uFDCF\\uFDF0-\\uFFFD";
+ private static final String nameChar = nameStartChar + "-\\.0-9\\u00B7\\u0300-\\u036F\\u203F-\\u2040";
+ public static final Pattern NAME_PATTERN = Pattern.compile("^[" + nameStartChar + "][" + nameChar + "]*$");
+ public static final Pattern NAME_PREFIX_PATTERN = Pattern.compile("^xml", Pattern.CASE_INSENSITIVE);
+
+ public static final Pattern UNESCAPE_UNICODE_PATTERN = Pattern.compile("\\&\\#(x?)(.+);");
+
+ private ContentHandler contentHandler;
+ private ErrorHandler errorHandler;
+
+ private static enum State {
+ START,
+ IN_TAG,
+ IN_END_TAG,
+ AFTER_START_NAME,
+ AFTER_END_NAME,
+ IN_EMPTY_TAG,
+ AFTER_ATTRIBUTE_NAME,
+ AFTER_ATTRIBUTE_EQUALS,
+ CLOSED
+ }
+
+ private ParticleTokenizer tokenizer;
+ private State state = State.START;
+ private String qname;
+ private List<Attribute> attributes;
+ private String attributeName;
+
+ // element names as {uri}qname
+ private Stack<String> elements = new Stack<String>();
+
+
+ public Parser(ContentHandler contentHandler, ErrorHandler errorHandler) {
+ this.contentHandler = contentHandler;
+ this.errorHandler = errorHandler;
+
+ this.tokenizer = new ParticleTokenizer(this);
+ }
+
+ public void parse(ByteBuffer byteBuffer, CharsetDecoder charsetDecoder) throws SAXException {
+ if(state == State.CLOSED) throw new SAXException("Parser is closed");
+
+ tokenizer.parse(byteBuffer, charsetDecoder);
+ }
+
+ public void token(String token) throws SAXException {
+ LOG.debug("Parser got token {} in state {}", token, state);
+
+ if(state == State.START) {
+ if(token.equals("<")) {
+ state = State.IN_TAG;
+ attributes = new ArrayList<Attribute>();
+ } else {
+ characters(token);
+ }
+ } else if(state == State.IN_TAG) {
+ // token must be element name or / for a end tag
+ if(token.equals("/")) {
+ state = State.IN_END_TAG;
+ } else {
+ qname = token;
+ state = State.AFTER_START_NAME;
+ }
+ } else if(state == State.IN_END_TAG) {
+ // token must be element name
+ qname = token;
+ state = State.AFTER_END_NAME;
+ } else if(state == State.AFTER_START_NAME) {
+ // token must be attribute name or > or /
+ if(token.equals(">")) {
+ // end of start or end tag
+ if(state == State.AFTER_START_NAME) {
+ startElement();
+ state = State.START;
+ attributes = null;
+ } else if(state == State.AFTER_END_NAME) {
+ state = State.START;
+ endElement();
+ }
+ } else if(token.equals("/")) {
+ state = State.IN_EMPTY_TAG;
+ } else {
+ // must be attribute name
+ attributeName = token;
+ state = State.AFTER_ATTRIBUTE_NAME;
+ }
+ } else if(state == State.AFTER_ATTRIBUTE_NAME) {
+ // token must be =
+ if(token.equals("=")) {
+ state = State.AFTER_ATTRIBUTE_EQUALS;
+ }
+ } else if(state == State.AFTER_ATTRIBUTE_EQUALS) {
+ // token must be attribute value
+ attributes.add(new Attribute(attributeName, "", attributeName, unescape(token)));
+ state = State.AFTER_START_NAME;
+ } else if(state == State.AFTER_END_NAME) {
+ // token must be >
+ if(token.equals(">")) {
+ state = State.START;
+ endElement();
+ }
+ } else if(state == State.IN_EMPTY_TAG) {
+ // token must be >
+ if(token.equals(">")) {
+ startElement();
+ attributes = null;
+
+ if(state != State.CLOSED) {
+ state = State.START;
+ endElement();
+ }
+ }
+ }
+ }
+
+ private void characters(String s) throws SAXException {
+ // text only allowed in element
+ if(!elements.isEmpty()) {
+ String unescaped = unescape(s);
+ LOG.debug("Parser emitting characters \"{}\"", unescaped);
+ contentHandler.characters(unescaped.toCharArray(), 0, unescaped.length());
+ } else {
+ // must start document, even that document is not wellformed
+ contentHandler.startDocument();
+ fatalError("Text only allowed in element");
+ }
+ }
+
+ private void startElement() throws SAXException {
+ LOG.debug("StartElement {}", qname);
+
+ if(elements.isEmpty()) {
+ contentHandler.startDocument();
+ }
+
+ if(!NAME_PATTERN.matcher(qname).find()) {
+ fatalError("Invalid element name: " + qname);
+ return;
+ }
+
+ // element names must not begin with "xml" in any casing
+ if(NAME_PREFIX_PATTERN.matcher(qname).find()) {
+ fatalError("Names must not start with 'xml': " + qname);
+ return;
+ }
+
+ String uri = "";
+ elements.add(fullyQualifiedName(uri, qname));
+ contentHandler.startElement(uri, qname, qname, new DefaultAttributes(attributes));
+ }
+
+ private String fullyQualifiedName(String uri, String qname) {
+ return "{" + uri + "}" + qname;
+ }
+
+ private void endElement() throws SAXException {
+ LOG.debug("EndElement {}", qname);
+
+ if(state == State.CLOSED) return;
+
+ String uri = "";
+ String fqn = elements.pop();
+ if(fqn.equals(fullyQualifiedName(uri, qname))) {
+ contentHandler.endElement(uri, qname, qname);
+
+ if(elements.isEmpty()) {
+ contentHandler.endDocument();
+ state = State.CLOSED;
+ }
+ } else {
+ fatalError("Invalid element name " + qname);
+ }
+ }
+
+ private void fatalError(String message) throws SAXException {
+ LOG.debug("Fatal error: {}", message);
+ state = State.CLOSED;
+ tokenizer.close();
+
+ errorHandler.fatalError(new SAXParseException(message, null));
+ }
+
+ private String unescape(String s) {
+ s = s.replace("&", "&").replace(">", ">").replace("<", "<").replace("'", "'").replace(""", "\"");
+
+ StringBuffer sb = new StringBuffer();
+
+ Matcher matcher = UNESCAPE_UNICODE_PATTERN.matcher(s);
+ int end = 0;
+ while(matcher.find()) {
+ boolean isHex = matcher.group(1).equals("x");
+ String unicodeCode = matcher.group(2);
+
+ int base = isHex ? 16: 10;
+ int i = Integer.valueOf(unicodeCode, base).intValue();
+ char[] c = Character.toChars(i);
+ sb.append(s.substring(end, matcher.start()));
+ end = matcher.end();
+ sb.append(c);
+ }
+ sb.append(s.substring(end, s.length()));
+
+ return sb.toString();
+ }
+}
Added: 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=895076&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/ParticleTokenizer.java Fri Jan 1 21:11:43 2010
@@ -0,0 +1,166 @@
+/*
+ * 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.nio.charset.CharacterCodingException;
+import java.nio.charset.CharsetDecoder;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.mina.common.ByteBuffer;
+import org.xml.sax.SAXException;
+
+/**
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class ParticleTokenizer {
+
+ private enum State {
+ START,
+ IN_TAG,
+ IN_DOUBLE_ATTRIBUTE_VALUE,
+ IN_SINGLE_ATTRIBUTE_VALUE,
+ IN_TEXT,
+ CLOSED
+ }
+
+ private int lastPosition = 0;
+ private State state = State.START;
+
+ public static interface TokenListener {
+ void token(String token) throws SAXException;
+ }
+
+ private TokenListener listener;
+
+ public ParticleTokenizer(TokenListener listeners) {
+ this.listener = listeners;
+ }
+
+ /**
+ * @param byteBuffer
+ * @param charsetDecoder
+ * @return the new particle or NULL, if the buffer was exhausted before the particle was completed
+ * @throws Exception
+ */
+ public void parse(ByteBuffer byteBuffer, CharsetDecoder decoder) throws SAXException {
+ lastPosition = byteBuffer.position();
+// StringBuffer sb = new StringBuffer();
+ while (byteBuffer.hasRemaining() && state != State.CLOSED) {
+ char c = (char)byteBuffer.get();
+
+ if(state == State.START) {
+ if(c == '<') {
+ emit("<", byteBuffer);
+ state = State.IN_TAG;
+ } else {
+ state = State.IN_TEXT;
+// sb.append(c);
+ }
+ } else if(state == State.IN_TEXT) {
+ if(c == '<') {
+ emit(byteBuffer, decoder);
+ emit("<", byteBuffer);
+ state = State.IN_TAG;
+ } else {
+// sb.append(c);
+ }
+ } else if(state == State.IN_TAG) {
+ if(c == '/') {
+ if(checkEmit(byteBuffer)) {
+ emit(byteBuffer, decoder);
+ }
+ emit("/", byteBuffer);
+ } else if(c == '>') {
+ if(checkEmit(byteBuffer)) {
+ emit(byteBuffer, decoder);
+ }
+ emit(">", byteBuffer);
+ state = State.START;
+ } else if(Character.isWhitespace(c)) {
+ if(checkEmit(byteBuffer)) {
+ emit(byteBuffer, decoder);
+ } else {
+ // ignore whitespace
+ lastPosition = byteBuffer.position();
+ }
+ } else if(c == '=') {
+ emit(byteBuffer, decoder);
+ emit("=", byteBuffer);
+ } else if(c == '"') {
+// emit("\"", byteBuffer);
+ state = State.IN_DOUBLE_ATTRIBUTE_VALUE;
+ } else if(c == '\'') {
+// emit("\'", byteBuffer);
+ state = State.IN_SINGLE_ATTRIBUTE_VALUE;
+ } else {
+ // non-whitespace char
+ }
+ } else if(state == State.IN_DOUBLE_ATTRIBUTE_VALUE) {
+ if(c == '"') {
+ emit(byteBuffer, decoder);
+// emit("\"", byteBuffer);
+ state = State.IN_TAG;
+ }
+ } else if(state == State.IN_SINGLE_ATTRIBUTE_VALUE) {
+ if(c == '\'') {
+ emit(byteBuffer, decoder);
+// emit("'", byteBuffer);
+ state = State.IN_TAG;
+ }
+ }
+ }
+
+ byteBuffer.position(lastPosition);
+ }
+
+ public void close() {
+ state = State.CLOSED;
+ }
+
+ private boolean checkEmit(ByteBuffer buffer) {
+ return buffer.position() > lastPosition + 1;
+ }
+
+ private void emit(String token, ByteBuffer byteBuffer) throws SAXException {
+ listener.token(token);
+
+ lastPosition = byteBuffer.position();
+ }
+
+ private void emit(ByteBuffer byteBuffer, CharsetDecoder decoder) throws SAXException {
+ int endPosition = byteBuffer.position();
+ int oldLimit = byteBuffer.limit();
+ byteBuffer.position(lastPosition);
+ byteBuffer.limit(endPosition - 1);
+
+ try {
+ listener.token(byteBuffer.getString(decoder));
+ } catch (CharacterCodingException e) {
+ throw new SAXException(e);
+ }
+ byteBuffer.limit(oldLimit);
+ byteBuffer.position(endPosition);
+ lastPosition = byteBuffer.position();
+
+
+ }
+}
Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java Fri Jan 1 21:11:43 2010
@@ -20,6 +20,7 @@
package org.apache.vysper.xml.sax;
import java.util.ArrayList;
+import java.util.Iterator;
import java.util.List;
import junit.framework.TestCase;
@@ -61,14 +62,25 @@
protected void assertStartElement(String expectedUri, String expectedLocalName, String expectedQName, Attributes expectedAttributes,
TestEvent actual) {
- if(!(actual instanceof StartElementEvent)) fail("Event must be StartElementEvent");
+ if(!(actual instanceof StartElementEvent)) fail("Event must be StartElementEvent but was " + actual.getClass());
StartElementEvent startElementEvent = (StartElementEvent) actual;
assertEquals("URI", expectedUri, startElementEvent.getURI());
assertEquals("local name", expectedLocalName, startElementEvent.getLocalName());
assertEquals("qName", expectedQName, startElementEvent.getQName());
- assertEquals("Attributes", expectedAttributes, startElementEvent.getAtts());
+ assertAttributes(expectedAttributes, startElementEvent.getAtts());
}
+ protected void assertAttributes(Attributes expectedAttrs, Attributes actualAttrs) {
+ assertEquals("Attribute count", expectedAttrs.getLength(), actualAttrs.getLength());
+
+ for(int i = 0; i<expectedAttrs.getLength(); i++) {
+ assertEquals("Local name[" + i + "]", expectedAttrs.getLocalName(i), actualAttrs.getLocalName(i));
+ assertEquals("Qname[" + i + "]", expectedAttrs.getQName(i), actualAttrs.getQName(i));
+ assertEquals("URI[" + i + "]", expectedAttrs.getURI(i), actualAttrs.getURI(i));
+ assertEquals("Value[" + i + "]", expectedAttrs.getValue(i), actualAttrs.getValue(i));
+ }
+ }
+
protected void assertEndElement(String expectedUri, String expectedLocalName, String expectedQName,
TestEvent actual) {
if(!(actual instanceof EndElementEvent)) fail("Event must be EndElementEvent");
@@ -107,4 +119,9 @@
if(!(actual instanceof FatalErrorEvent)) fail("Event must be FatalErrorEvent but is "+ actual.getClass());
}
+ protected void assertNoMoreevents(Iterator events) {
+ if(events.hasNext()) {
+ fail("Must not be any more evens, but found one " + events.next().getClass());
+ }
+ }
}
\ No newline at end of file
Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java Fri Jan 1 21:11:43 2010
@@ -22,6 +22,7 @@
import org.apache.mina.common.ByteBuffer;
import org.apache.vysper.charset.CharsetUtil;
import org.apache.vysper.xml.sax.impl.DefaultAsyncXMLReader;
+import org.xml.sax.DTDHandler;
import org.xml.sax.SAXException;
@@ -66,5 +67,30 @@
// OK
}
}
+
+ public void testSetDtdHandlerNotSupported() {
+ try {
+ new DefaultAsyncXMLReader().setDTDHandler(new DTDHandler() {
+ public void unparsedEntityDecl(String name, String publicId,
+ String systemId, String notationName) throws SAXException {
+ }
+ public void notationDecl(String name, String publicId, String systemId)
+ throws SAXException {
+ }
+ });
+ fail("Not supported, must throw RuntimeException");
+ } catch(RuntimeException e) {
+ // OK
+ }
+ }
+
+ public void testGetDtdHandlerNotSupported() {
+ try {
+ new DefaultAsyncXMLReader().getDTDHandler();
+ fail("Not supported, must throw RuntimeException");
+ } catch(RuntimeException e) {
+ // OK
+ }
+ }
}
\ No newline at end of file
Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java Fri Jan 1 21:11:43 2010
@@ -21,7 +21,7 @@
import junit.framework.TestCase;
-import org.apache.vysper.xml.decoder.XMLParticle;
+import org.apache.vysper.xml.sax.impl.Parser;
@@ -31,17 +31,17 @@
public class NameTestCase extends TestCase {
public void testValidName() {
- assertTrue(XMLParticle.NAME_PATTERN.matcher("abc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher("_abc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher(":abc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher("Aabc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher("\u00C8abc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher("\u00C8abc").find());
- assertFalse(XMLParticle.NAME_PATTERN.matcher("3abc").find());
- assertFalse(XMLParticle.NAME_PATTERN.matcher("\u2001abc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher("a3bc").find());
- assertFalse(XMLParticle.NAME_PATTERN.matcher("-abc").find());
- assertTrue(XMLParticle.NAME_PATTERN.matcher("ab-c").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("abc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("_abc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher(":abc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("Aabc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("\u00C8abc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("\u00C8abc").find());
+ assertFalse(Parser.NAME_PATTERN.matcher("3abc").find());
+ assertFalse(Parser.NAME_PATTERN.matcher("\u2001abc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("a3bc").find());
+ assertFalse(Parser.NAME_PATTERN.matcher("-abc").find());
+ assertTrue(Parser.NAME_PATTERN.matcher("ab-c").find());
}
Added: 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=895076&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseAttributesTestCase.java Fri Jan 1 21:11:43 2010
@@ -0,0 +1,92 @@
+/*
+ * 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 ParseAttributesTestCase extends AbstractAsyncXMLReaderTestCase {
+
+ public void testSimpleAttribute() throws Exception {
+ Iterator<TestEvent> events = parse("<root att='foo' />").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());
+ }
+
+ public void testMultipleAttribute() throws Exception {
+ Iterator<TestEvent> events = parse("<root att='foo' att2='bar' />").iterator();
+
+ assertStartDocument(events.next());
+ assertStartElement("", "root", "root",
+ attributes(new Attribute("att", "", "att", "foo"), new Attribute("att2", "", "att2", "bar")), events.next());
+ assertEndElement("", "root", "root", events.next());
+ assertEndDocument(events.next());
+
+ assertFalse(events.hasNext());
+ }
+
+ public void testAttributeWithDoubleQuote() throws Exception {
+ Iterator<TestEvent> events = parse("<root att='f\"oo' />").iterator();
+
+ assertStartDocument(events.next());
+ assertStartElement("", "root", "root",
+ attributes(new Attribute("att", "", "att", "f\"oo")), events.next());
+ assertEndElement("", "root", "root", events.next());
+ assertEndDocument(events.next());
+
+ assertFalse(events.hasNext());
+ }
+
+ public void testAttributeWithSingleQuote() throws Exception {
+ Iterator<TestEvent> events = parse("<root att=\"f'oo\" />").iterator();
+
+ assertStartDocument(events.next());
+ assertStartElement("", "root", "root",
+ attributes(new Attribute("att", "", "att", "f'oo")), events.next());
+ assertEndElement("", "root", "root", events.next());
+ assertEndDocument(events.next());
+
+ assertFalse(events.hasNext());
+ }
+
+ public void testAttributeWithEscapedAmp() throws Exception {
+ Iterator<TestEvent> events = parse("<root att='f&oo' />").iterator();
+
+ assertStartDocument(events.next());
+ assertStartElement("", "root", "root",
+ attributes(new Attribute("att", "", "att", "f&oo")), events.next());
+ assertEndElement("", "root", "root", events.next());
+ assertEndDocument(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/ParseElementsTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseElementsTestCase.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseElementsTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseElementsTestCase.java Fri Jan 1 21:11:43 2010
@@ -37,7 +37,7 @@
assertEndElement("", "root", "root", events.next());
assertEndDocument(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testElement() throws Exception {
@@ -48,7 +48,7 @@
assertEndElement("", "root", "root", events.next());
assertEndDocument(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testElements() throws Exception {
@@ -64,7 +64,7 @@
assertEndElement("", "root", "root", events.next());
assertEndDocument(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testIllegalClosingElement() throws Exception {
@@ -76,7 +76,7 @@
assertEndElement("", "child", "child", events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testNumberAsFirstCharInName() throws Exception {
@@ -85,7 +85,7 @@
assertStartDocument(events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testDashAsFirstCharInName() throws Exception {
@@ -94,7 +94,7 @@
assertStartDocument(events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testNumberInName() throws Exception {
@@ -105,7 +105,7 @@
assertEndElement("", "r1oot", "r1oot", events.next());
assertEndDocument(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testInvalidUnicodeInName() throws Exception {
@@ -114,7 +114,7 @@
assertStartDocument(events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testValidUnicodeInName() throws Exception {
@@ -126,7 +126,7 @@
assertEndDocument(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testXmlBeginName() throws Exception {
@@ -135,7 +135,7 @@
assertStartDocument(events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
public void testXmlInsideName() throws Exception {
@@ -146,7 +146,7 @@
assertEndElement("", "roxmlot", "roxmlot", events.next());
assertEndDocument(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
@@ -156,6 +156,6 @@
assertStartDocument(events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
}
\ No newline at end of file
Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java Fri Jan 1 21:11:43 2010
@@ -97,7 +97,7 @@
assertStartDocument(events.next());
assertFatalError(events.next());
- assertFalse(events.hasNext());
+ assertNoMoreevents(events);
}
Modified: mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java?rev=895076&r1=895075&r2=895076&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java Fri Jan 1 21:11:43 2010
@@ -162,16 +162,19 @@
public void characters(char[] ch, int start, int length)
throws SAXException {
+ System.out.println("sax characters: " + new String(ch));
events.add(new CharacterEvent(ch, start, length));
}
public void endDocument() throws SAXException {
+ System.out.println("sax end document");
events.add(new EndDocumentEvent());
}
public void endElement(String uri, String localName, String qName)
throws SAXException {
+ System.out.println("sax end element: "+ qName);
events.add(new EndElementEvent(uri, localName, qName));
}
@@ -204,6 +207,7 @@
}
public void startDocument() throws SAXException {
+ System.out.println("sax start document");
events.add(new StartDocumentEvent());
}
Added: mina/sandbox/vysper/branches/nbxml-sax/src/test/resources/log4j.properties
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/test/resources/log4j.properties?rev=895076&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/resources/log4j.properties (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/resources/log4j.properties Fri Jan 1 21:11:43 2010
@@ -0,0 +1,26 @@
+# 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.
+
+log4j.rootLogger=DEBUG, C
+
+log4j.logger.org.apache.vysper.mina.XmppIoHandlerAdapter=WARN,C
+log4j.logger.org.apache.mina.filter.executor.ExecutorFilter=WARN,C
+
+log4j.appender.C=org.apache.log4j.ConsoleAppender
+log4j.appender.C.layout=org.apache.log4j.PatternLayout
+log4j.appender.C.layout.ConversionPattern=%m%n
+