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 2009/12/15 14:55:00 UTC

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

Author: ngn
Date: Tue Dec 15 13:54:58 2009
New Revision: 890796

URL: http://svn.apache.org/viewvc?rev=890796&view=rev
Log:
First stab at a SAX based parser, not yet supporting attributes, namespaces nor special constructs like comments and PIs

Added:
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/AsyncXMLReader.java
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Attribute.java
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java
    mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/
    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
Removed:
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xmpp/
Modified:
    mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLParticle.java

Modified: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLParticle.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLParticle.java?rev=890796&r1=890795&r2=890796&view=diff
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLParticle.java (original)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/decoder/XMLParticle.java Tue Dec 15 13:54:58 2009
@@ -29,6 +29,16 @@
  */
 public class XMLParticle {
 
+	//private static final String nameStartChar = "[:A-Z_a-z] | [#xC0-#xD6] | [#xD8-#xF6] | [#xF8-#x2FF] | [#x370-#x37D] | [#x37F-#x1FFF] | [#x200C-#x200D] | [#x2070-#x218F] | [#x2C00-#x2FEF] | [#x3001-#xD7FF] | [#xF900-#xFDCF] | [#xFDF0-#xFFFD] | [#x10000-#xEFFFF]
+	
+	// TODO how do we handle \\U00010000-\\U000EFFFF ?
+    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 boolean isOpeningElement = false;
     private boolean isClosingElement = false;
     private boolean isSpecialElement = false;
@@ -91,7 +101,35 @@
     }
 
     public String getContent() {
-        return content;
+    	if(isText()) {
+    		return unescape(content);
+    	} else {
+    		return content;
+    	}
+    }
+    
+    
+    private String unescape(String s) {
+    	s = s.replace("&amp;", "&").replace("&gt;", ">").replace("&lt;", "<").replace("&apos;", "'").replace("&quot;", "\"");
+    
+    	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();
     }
 
     public String getContentWithoutElement() throws DecodingException {
@@ -128,22 +166,23 @@
                 if (current == '!' || current == '?' || current == '/') continue; // TODO check, if next char is '>'
             }
             if (beforeElement) {
-                if (!isLegitemateNameStartChar(current)) {
-                    throw new DecodingException("cannot start element name with char " + (char)current);
-                }
                 beforeElement = false;
             } else {
-                if (!isLegitemateNameChar(current)) {
-                    if (!isWhitespace(current) &&  current != '>' && current != '/') {
-                        throw new DecodingException("char not allowed in element name: " + (char)current);
-                    } else {
-                        break; // name is completed
-                    }
+                if (isWhitespace(current) || current == '>' || current == '/') {
+                    break; // name is completed
                 }
             }
             elementNameBuilder.append((char)current);
         }
-        return elementNameBuilder.toString();
+        
+        String elementName = elementNameBuilder.toString();
+        
+        if(!NAME_PATTERN.matcher(elementName).find()) throw new DecodingException("Invalid element name: " + elementName);
+
+        // element names must not begin with "xml" in any casing
+        if(NAME_PREFIX_PATTERN.matcher(elementName).find()) throw new DecodingException("Names must not start with 'xml': " + elementName);
+        
+        return elementName;
     }
 
     private boolean isWhitespace(int current) {
@@ -151,19 +190,4 @@
                 current == '!' || current == '?' /* TODO check, if next char is '>'*/
                );
     }
-
-    /**
-     *
-     * NameChar	 ::=  Letter | Digit | '.' | '-' | '_' | ':' | CombiningChar | Extender
-     * @param c
-     * @return
-     */
-    private boolean isLegitemateNameChar(int c) {
-        return isLegitemateNameStartChar(c) || Character.isDigit(c) || c == '.' || c == '-';
-    }
-
-    private boolean isLegitemateNameStartChar(int c) {
-        return Character.isLetter(c) || c == '_' || c == ':';
-    }
-
 }

Added: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/AsyncXMLReader.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/AsyncXMLReader.java?rev=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/AsyncXMLReader.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/AsyncXMLReader.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,307 @@
+/*
+ *  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.io.IOException;
+import java.nio.charset.CharsetDecoder;
+
+import org.apache.mina.common.ByteBuffer;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.DTDHandler;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXNotRecognizedException;
+import org.xml.sax.SAXNotSupportedException;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public interface AsyncXMLReader {
+
+    ////////////////////////////////////////////////////////////////////
+    // Configuration.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Look up the value of a feature flag.
+     *
+     * <p>The feature name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a feature name but
+     * temporarily be unable to return its value.
+     * Some feature values may be available only in specific
+     * contexts, such as before, during, or after a parse.
+     * Also, some feature values may not be programmatically accessible.
+     * (In the case of an adapter for SAX1 {@link Parser}, there is no
+     * implementation-independent way to expose whether the underlying
+     * parser is performing validation, expanding external entities,
+     * and so forth.) </p>
+     *
+     * <p>All XMLReaders are required to recognize the
+     * http://xml.org/sax/features/namespaces and the
+     * http://xml.org/sax/features/namespace-prefixes feature names.</p>
+     *
+     * <p>Typical usage is something like this:</p>
+     *
+     * <pre>
+     * XMLReader r = new MySAXDriver();
+     *
+     *                         // try to activate validation
+     * try {
+     *   r.setFeature("http://xml.org/sax/features/validation", true);
+     * } catch (SAXException e) {
+     *   System.err.println("Cannot activate validation."); 
+     * }
+     *
+     *                         // register event handlers
+     * r.setContentHandler(new MyContentHandler());
+     * r.setErrorHandler(new MyErrorHandler());
+     *
+     *                         // parse the first document
+     * try {
+     *   r.parse("http://www.foo.com/mydoc.xml");
+     * } catch (IOException e) {
+     *   System.err.println("I/O exception reading XML document");
+     * } catch (SAXException e) {
+     *   System.err.println("XML exception reading document.");
+     * }
+     * </pre>
+     *
+     * <p>Implementors are free (and encouraged) to invent their own features,
+     * using names built on their own URIs.</p>
+     *
+     * @param name The feature name, which is a fully-qualified URI.
+     * @return The current value of the feature (true or false).
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the feature name but 
+     *            cannot determine its value at this time.
+     * @see #setFeature
+     */
+    public boolean getFeature (String name)
+        throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Set the value of a feature flag.
+     *
+     * <p>The feature name is any fully-qualified URI.  It is
+     * possible for an XMLReader to expose a feature value but
+     * to be unable to change the current value.
+     * Some feature values may be immutable or mutable only 
+     * in specific contexts, such as before, during, or after 
+     * a parse.</p>
+     *
+     * <p>All XMLReaders are required to support setting
+     * http://xml.org/sax/features/namespaces to true and
+     * http://xml.org/sax/features/namespace-prefixes to false.</p>
+     *
+     * @param name The feature name, which is a fully-qualified URI.
+     * @param value The requested value of the feature (true or false).
+     * @exception org.xml.sax.SAXNotRecognizedException If the feature
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the feature name but 
+     *            cannot set the requested value.
+     * @see #getFeature
+     */
+    public void setFeature (String name, boolean value)
+	throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Look up the value of a property.
+     *
+     * <p>The property name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a property name but
+     * temporarily be unable to return its value.
+     * Some property values may be available only in specific
+     * contexts, such as before, during, or after a parse.</p>
+     *
+     * <p>XMLReaders are not required to recognize any specific
+     * property names, though an initial core set is documented for
+     * SAX2.</p>
+     *
+     * <p>Implementors are free (and encouraged) to invent their own properties,
+     * using names built on their own URIs.</p>
+     *
+     * @param name The property name, which is a fully-qualified URI.
+     * @return The current value of the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the property name but 
+     *            cannot determine its value at this time.
+     * @see #setProperty
+     */
+    public Object getProperty (String name)
+	throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+    /**
+     * Set the value of a property.
+     *
+     * <p>The property name is any fully-qualified URI.  It is
+     * possible for an XMLReader to recognize a property name but
+     * to be unable to change the current value.
+     * Some property values may be immutable or mutable only 
+     * in specific contexts, such as before, during, or after 
+     * a parse.</p>
+     *
+     * <p>XMLReaders are not required to recognize setting
+     * any specific property names, though a core set is defined by 
+     * SAX2.</p>
+     *
+     * <p>This method is also the standard mechanism for setting
+     * extended handlers.</p>
+     *
+     * @param name The property name, which is a fully-qualified URI.
+     * @param value The requested value for the property.
+     * @exception org.xml.sax.SAXNotRecognizedException If the property
+     *            value can't be assigned or retrieved.
+     * @exception org.xml.sax.SAXNotSupportedException When the
+     *            XMLReader recognizes the property name but 
+     *            cannot set the requested value.
+     */
+    public void setProperty (String name, Object value)
+	throws SAXNotRecognizedException, SAXNotSupportedException;
+
+
+
+    ////////////////////////////////////////////////////////////////////
+    // Event handlers.
+    ////////////////////////////////////////////////////////////////////
+
+
+    /**
+     * Allow an application to register an entity resolver.
+     *
+     * <p>If the application does not register an entity resolver,
+     * the XMLReader will perform its own default resolution.</p>
+     *
+     * <p>Applications may register a new or different resolver in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * resolver immediately.</p>
+     *
+     * @param resolver The entity resolver.
+     * @see #getEntityResolver
+     */
+    public void setEntityResolver (EntityResolver resolver);
+
+
+    /**
+     * Return the current entity resolver.
+     *
+     * @return The current entity resolver, or null if none
+     *         has been registered.
+     * @see #setEntityResolver
+     */
+    public EntityResolver getEntityResolver ();
+
+
+    /**
+     * Allow an application to register a DTD event handler.
+     *
+     * <p>If the application does not register a DTD handler, all DTD
+     * events reported by the SAX parser will be silently ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The DTD handler.
+     * @see #getDTDHandler
+     */
+    public void setDTDHandler (DTDHandler handler);
+
+
+    /**
+     * Return the current DTD handler.
+     *
+     * @return The current DTD handler, or null if none
+     *         has been registered.
+     * @see #setDTDHandler
+     */
+    public DTDHandler getDTDHandler ();
+
+
+    /**
+     * Allow an application to register a content event handler.
+     *
+     * <p>If the application does not register a content handler, all
+     * content events reported by the SAX parser will be silently
+     * ignored.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The content handler.
+     * @see #getContentHandler
+     */
+    public void setContentHandler (ContentHandler handler);
+
+
+    /**
+     * Return the current content handler.
+     *
+     * @return The current content handler, or null if none
+     *         has been registered.
+     * @see #setContentHandler
+     */
+    public ContentHandler getContentHandler ();
+
+
+    /**
+     * Allow an application to register an error event handler.
+     *
+     * <p>If the application does not register an error handler, all
+     * error events reported by the SAX parser will be silently
+     * ignored; however, normal processing may not continue.  It is
+     * highly recommended that all SAX applications implement an
+     * error handler to avoid unexpected bugs.</p>
+     *
+     * <p>Applications may register a new or different handler in the
+     * middle of a parse, and the SAX parser must begin using the new
+     * handler immediately.</p>
+     *
+     * @param handler The error handler.
+     * @see #getErrorHandler
+     */
+    public void setErrorHandler (ErrorHandler handler);
+
+
+    /**
+     * Return the current error handler.
+     *
+     * @return The current error handler, or null if none
+     *         has been registered.
+     * @see #setErrorHandler
+     */
+    public ErrorHandler getErrorHandler ();
+
+    public void parse (ByteBuffer buffer, CharsetDecoder decoder) throws IOException, SAXException;
+
+
+
+}
\ No newline at end of file

Added: mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Attribute.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Attribute.java?rev=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Attribute.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/Attribute.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,69 @@
+/**
+ * 
+ */
+package org.apache.vysper.xml.sax.impl;
+
+public class Attribute {
+	private String localName;
+	private String uri;
+	private String qname;
+	private String value;
+	public Attribute(String localName, String uri, String qname,
+			String value) {
+		this.localName = localName;
+		this.uri = uri;
+		this.qname = qname;
+		this.value = value;
+	}
+	public String getLocalName() {
+		return localName;
+	}
+	public String getURI() {
+		return uri;
+	}
+	public String getQname() {
+		return qname;
+	}
+	public String getValue() {
+		return value;
+	}
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((localName == null) ? 0 : localName.hashCode());
+		result = prime * result + ((qname == null) ? 0 : qname.hashCode());
+		result = prime * result + ((uri == null) ? 0 : uri.hashCode());
+		result = prime * result + ((value == null) ? 0 : value.hashCode());
+		return result;
+	}
+	
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) return true;
+		if (obj == null) return false;
+		if (getClass() != obj.getClass()) return false;
+		Attribute other = (Attribute) obj;
+		
+		if (localName == null) {
+			if (other.localName != null) return false;
+		} else if (!localName.equals(other.localName)) return false;
+		
+		if (qname == null) {
+			if (other.qname != null) return false;
+		} else if (!qname.equals(other.qname)) return false;
+		
+		if (uri == null) {
+			if (other.uri != null) return false;
+		} else if (!uri.equals(other.uri)) return false;
+		
+		if (value == null) {
+			if (other.value != null) return false;
+		} else if (!value.equals(other.value)) return false;
+		
+		return true;
+	}
+	
+	
+}
\ No newline at end of file

Added: 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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAsyncXMLReader.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,215 @@
+/*
+ *  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.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;
+import org.xml.sax.EntityResolver;
+import org.xml.sax.ErrorHandler;
+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;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class DefaultAsyncXMLReader implements AsyncXMLReader {
+
+	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>();
+	
+	/**
+	 * {@inheritDoc}
+	 */
+    public boolean getFeature (String name)
+        throws SAXNotRecognizedException, SAXNotSupportedException {
+    	return false;
+    }
+
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public void setFeature (String name, boolean value)
+		throws SAXNotRecognizedException, SAXNotSupportedException {
+    	
+    }
+
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public Object getProperty (String name)
+	throws SAXNotRecognizedException, SAXNotSupportedException {
+    	return null;
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public void setProperty (String name, Object value)
+    	throws SAXNotRecognizedException, SAXNotSupportedException {
+    	
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public void setEntityResolver (EntityResolver resolver) {
+    	throw new RuntimeException("Entity resolver not supported");
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public EntityResolver getEntityResolver () {
+    	throw new RuntimeException("Entity resolver not supported");
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public void setDTDHandler (DTDHandler handler) {
+    	throw new RuntimeException("DTD handler not supported");
+    }
+
+    public DTDHandler getDTDHandler () {
+    	throw new RuntimeException("DTD handler not supported");
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public void setContentHandler (ContentHandler handler) {
+    	this.contentHandler = handler;
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public ContentHandler getContentHandler () {
+    	return contentHandler;
+    }
+
+	/**
+	 * {@inheritDoc}
+	 */
+    public void setErrorHandler (ErrorHandler handler) {
+    	this.errorHandler = handler;
+    }
+
+    /**
+	 * {@inheritDoc}
+	 */
+    public ErrorHandler getErrorHandler () {
+    	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");
+    	}
+    	
+    	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());
+		}
+    }
+
+
+
+}
\ No newline at end of file

Added: 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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/main/java/org/apache/vysper/xml/sax/impl/DefaultAttributes.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,135 @@
+/*
+ *  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.Collections;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class DefaultAttributes implements Attributes {
+
+	private List<Attribute> attributes;
+
+	public DefaultAttributes() {
+		this.attributes = Collections.emptyList();
+	}
+	
+	public DefaultAttributes(List<Attribute> attributes) {
+		this.attributes = attributes;
+	}
+	
+	public int getIndex(String qName) {
+		for(int i = 0; i<attributes.size(); i++) {
+			Attribute attribute = attributes.get(i);
+			if(qName.equals(attribute.getQname())) return i;
+		}
+		
+		return -1;
+	}
+
+	public int getIndex(String uri, String localName) {
+		for(int i = 0; i<attributes.size(); i++) {
+			Attribute attribute = attributes.get(i);
+			if(uri.equals(attribute.getURI()) && localName.equals(attribute.getLocalName())) return i;
+		}
+		
+		return -1;
+	}
+
+	public int getLength() {
+		return attributes.size();
+	}
+
+	public String getLocalName(int index) {
+		if(index < 0 || index >= attributes.size()) return null;
+		
+		return attributes.get(index).getLocalName();
+	}
+
+	public String getQName(int index) {
+		if(index < 0 || index >= attributes.size()) return null;
+		
+		return attributes.get(index).getQname();
+	}
+
+	public String getType(int index) {
+		if(index < 0 || index >= attributes.size()) return null;
+
+		return "CDATA";
+	}
+
+	public String getType(String qName) {
+		return getType(getIndex(qName));
+	}
+
+	public String getType(String uri, String localName) {
+		return getType(getIndex(uri, localName));
+	}
+
+	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();
+	}
+
+	public String getValue(String qName) {
+		return getValue(getIndex(qName));
+	}
+
+	public String getValue(String uri, String localName) {
+		return getValue(getIndex(uri, localName));
+	}
+
+	@Override
+	public int hashCode() {
+		final int prime = 31;
+		int result = 1;
+		result = prime * result
+				+ ((attributes == null) ? 0 : attributes.hashCode());
+		return result;
+	}
+
+	@Override
+	public boolean equals(Object obj) {
+		if (this == obj) return true;
+		if (obj == null) return false;
+		if (getClass() != obj.getClass()) return false;
+		
+		DefaultAttributes other = (DefaultAttributes) obj;
+		if (attributes == null) {
+			if (other.attributes != null) return false;
+		} else if (!attributes.equals(other.attributes)) return false;
+		
+		return true;
+	}
+
+
+}
\ No newline at end of file

Added: 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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/AbstractAsyncXMLReaderTestCase.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,110 @@
+/*
+ *  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.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.vysper.charset.CharsetUtil;
+import org.apache.vysper.xml.sax.TestHandler.CharacterEvent;
+import org.apache.vysper.xml.sax.TestHandler.EndDocumentEvent;
+import org.apache.vysper.xml.sax.TestHandler.EndElementEvent;
+import org.apache.vysper.xml.sax.TestHandler.FatalErrorEvent;
+import org.apache.vysper.xml.sax.TestHandler.StartDocumentEvent;
+import org.apache.vysper.xml.sax.TestHandler.StartElementEvent;
+import org.apache.vysper.xml.sax.TestHandler.TestEvent;
+import org.apache.vysper.xml.sax.impl.Attribute;
+import org.apache.vysper.xml.sax.impl.DefaultAsyncXMLReader;
+import org.apache.vysper.xml.sax.impl.DefaultAttributes;
+import org.xml.sax.Attributes;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public abstract class AbstractAsyncXMLReaderTestCase extends TestCase {
+
+	private static final Attributes EMPTY_ATTRIBUTES = new DefaultAttributes();
+	
+	protected void assertStartElement(String expectedUri, String expectedLocalName, String expectedQName, 
+			TestEvent actual) {
+		assertStartElement(expectedUri, expectedLocalName, expectedQName, EMPTY_ATTRIBUTES, actual);
+	}
+
+	protected Attributes attributes(Attribute...attributes) {
+		List<Attribute> list = new ArrayList<Attribute>();
+		for(Attribute attribute : attributes) {
+			list.add(attribute);
+		}
+		return new DefaultAttributes(list);
+	}
+	
+	protected void assertStartElement(String expectedUri, String expectedLocalName, String expectedQName, Attributes expectedAttributes, 
+			TestEvent actual) {
+		if(!(actual instanceof StartElementEvent)) fail("Event must be StartElementEvent");
+		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());
+	}
+
+	protected void assertEndElement(String expectedUri, String expectedLocalName, String expectedQName, 
+			TestEvent actual) {
+		if(!(actual instanceof EndElementEvent)) fail("Event must be EndElementEvent");
+		EndElementEvent endElementEvent = (EndElementEvent) actual;
+		assertEquals("URI", expectedUri, endElementEvent.getURI());
+		assertEquals("local name", expectedLocalName, endElementEvent.getLocalName());
+		assertEquals("qName", expectedQName, endElementEvent.getQName());
+	}
+
+	protected void assertStartDocument(TestEvent actual) {
+		if(!(actual instanceof StartDocumentEvent)) fail("Event must be StartDocumentEvent");
+	}
+
+	protected void assertEndDocument(TestEvent actual) {
+		if(!(actual instanceof EndDocumentEvent)) fail("Event must be EndDocumentEvent");
+	}
+
+	protected void assertText(String expected, TestEvent actual) {
+		if(!(actual instanceof CharacterEvent)) fail("Event must be CharacterEvent");
+		
+		assertEquals(expected, ((CharacterEvent)actual).getCharacters());
+	}
+
+	protected List<TestEvent> parse(String xml) throws Exception {
+		TestHandler handler = new TestHandler();
+		AsyncXMLReader reader = new DefaultAsyncXMLReader();
+		reader.setContentHandler(handler);
+		reader.setErrorHandler(handler);
+
+		reader.parse(ByteBuffer.wrap(xml.getBytes("UTF-8")), CharsetUtil.UTF8_DECODER);
+		
+		return handler.getEvents();
+	}
+
+	protected void assertFatalError(TestEvent actual) {
+		if(!(actual instanceof FatalErrorEvent)) fail("Event must be FatalErrorEvent but is "+ actual.getClass());
+	}
+
+}
\ No newline at end of file

Added: 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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/DefaultAsyncXMLReaderTestCase.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,70 @@
+/*
+ *  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 org.apache.mina.common.ByteBuffer;
+import org.apache.vysper.charset.CharsetUtil;
+import org.apache.vysper.xml.sax.impl.DefaultAsyncXMLReader;
+import org.xml.sax.SAXException;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class DefaultAsyncXMLReaderTestCase extends AbstractAsyncXMLReaderTestCase {
+
+	public void testParseAfterFatalError() throws Exception {
+		TestHandler handler = new TestHandler();
+		AsyncXMLReader reader = new DefaultAsyncXMLReader();
+		reader.setContentHandler(handler);
+		reader.setErrorHandler(handler);
+
+		// causes a fatal error
+		reader.parse(ByteBuffer.wrap("<root></error>".getBytes("UTF-8")), CharsetUtil.UTF8_DECODER);
+		
+		try {
+			// not allowed to parse after an error
+			reader.parse(ByteBuffer.wrap("<root>".getBytes("UTF-8")), CharsetUtil.UTF8_DECODER);
+			fail("Must throw SAXException");
+		} catch(SAXException e) {
+			// OK
+		}
+	}
+
+	
+	public void testParseAfterEndDocument() throws Exception {
+		TestHandler handler = new TestHandler();
+		AsyncXMLReader reader = new DefaultAsyncXMLReader();
+		reader.setContentHandler(handler);
+		reader.setErrorHandler(handler);
+
+		// causes a fatal error
+		reader.parse(ByteBuffer.wrap("<root></root>".getBytes("UTF-8")), CharsetUtil.UTF8_DECODER);
+		
+		try {
+			// not allowed to parse after end of document
+			reader.parse(ByteBuffer.wrap("<root>".getBytes("UTF-8")), CharsetUtil.UTF8_DECODER);
+			fail("Must throw SAXException");
+		} catch(SAXException e) {
+			// OK
+		}
+	}
+
+}
\ No newline at end of file

Added: 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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/NameTestCase.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,48 @@
+/*
+ *  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 junit.framework.TestCase;
+
+import org.apache.vysper.xml.decoder.XMLParticle;
+
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+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());
+		
+	}
+
+}
\ No newline at end of file

Added: 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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseElementsTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseElementsTestCase.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,161 @@
+/*
+ *  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;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class ParseElementsTestCase extends AbstractAsyncXMLReaderTestCase {
+
+	public void testEmptyElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root />").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testElements() throws Exception {
+		Iterator<TestEvent> events = parse("<root><child><inner /></child></root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertStartElement("", "child", "child", events.next());
+		assertStartElement("", "inner", "inner", events.next());
+		
+		assertEndElement("", "inner", "inner", events.next());
+		assertEndElement("", "child", "child", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testIllegalClosingElement() throws Exception {
+		Iterator<TestEvent> events = parse("<root><child /></error>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertStartElement("", "child", "child", events.next());
+		assertEndElement("", "child", "child", events.next());
+		assertFatalError(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testNumberAsFirstCharInName() throws Exception {
+		Iterator<TestEvent> events = parse("<1root />").iterator();
+
+		assertStartDocument(events.next());
+		assertFatalError(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testDashAsFirstCharInName() throws Exception {
+		Iterator<TestEvent> events = parse("<-root />").iterator();
+
+		assertStartDocument(events.next());
+		assertFatalError(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testNumberInName() throws Exception {
+		Iterator<TestEvent> events = parse("<r1oot />").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "r1oot", "r1oot", events.next());
+		assertEndElement("", "r1oot", "r1oot", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testInvalidUnicodeInName() throws Exception {
+		Iterator<TestEvent> events = parse("<r\u2190oot />").iterator();
+
+		assertStartDocument(events.next());
+		assertFatalError(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testValidUnicodeInName() throws Exception {
+		Iterator<TestEvent> events = parse("<r\u218Foot />").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "r\u218Foot", "r\u218Foot", events.next());
+		assertEndElement("", "r\u218Foot", "r\u218Foot", events.next());
+		assertEndDocument(events.next());
+
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testXmlBeginName() throws Exception {
+		Iterator<TestEvent> events = parse("<xmlroot />").iterator();
+
+		assertStartDocument(events.next());
+		assertFatalError(events.next());
+
+		assertFalse(events.hasNext());
+	}
+
+	public void testXmlInsideName() throws Exception {
+		Iterator<TestEvent> events = parse("<roxmlot />").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "roxmlot", "roxmlot", events.next());
+		assertEndElement("", "roxmlot", "roxmlot", events.next());
+		assertEndDocument(events.next());
+
+		assertFalse(events.hasNext());
+	}
+
+	
+	public void testMixedXmlBeginName() throws Exception {
+		Iterator<TestEvent> events = parse("<XmLroot />").iterator();
+
+		assertStartDocument(events.next());
+		assertFatalError(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/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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/ParseTextTestCase.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,104 @@
+/*
+ *  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;
+
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class ParseTextTestCase extends AbstractAsyncXMLReaderTestCase {
+
+	public void testSimpleText() throws Exception {
+		Iterator<TestEvent> events = parse("<root>text</root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertText("text", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testEscapedAmp() throws Exception {
+		Iterator<TestEvent> events = parse("<root>t&amp;ext</root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertText("t&ext", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	public void testDoubleEscapedAmp() throws Exception {
+		Iterator<TestEvent> events = parse("<root>t&amp;amp;ext</root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertText("t&amp;ext", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+
+	
+	public void testUnicodeEscape() throws Exception {
+		Iterator<TestEvent> events = parse("<root>t&#251;ext</root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertText("tžext", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+	
+	public void testUnicodeHexEscape() throws Exception {
+		Iterator<TestEvent> events = parse("<root>t&#xFB;ext</root>").iterator();
+
+		assertStartDocument(events.next());
+		assertStartElement("", "root", "root", events.next());
+		assertText("tžext", events.next());
+		assertEndElement("", "root", "root", events.next());
+		assertEndDocument(events.next());
+		
+		assertFalse(events.hasNext());
+	}
+	
+	public void testTextOnly() throws Exception {
+		Iterator<TestEvent> events = parse("text</root>").iterator();
+
+		assertStartDocument(events.next());
+		assertFatalError(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/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=890796&view=auto
==============================================================================
--- mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java (added)
+++ mina/sandbox/vysper/branches/nbxml-sax/src/test/java/org/apache/vysper/xml/sax/TestHandler.java Tue Dec 15 13:54:58 2009
@@ -0,0 +1,235 @@
+/*
+ *  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.ArrayList;
+import java.util.List;
+
+import org.xml.sax.Attributes;
+import org.xml.sax.ContentHandler;
+import org.xml.sax.ErrorHandler;
+import org.xml.sax.Locator;
+import org.xml.sax.SAXException;
+import org.xml.sax.SAXParseException;
+
+
+/**
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ */
+public class TestHandler implements ContentHandler, ErrorHandler {
+
+	public static interface TestEvent {
+		
+	}
+
+	public static class StartDocumentEvent implements TestEvent {
+		
+	}
+
+	public static class EndDocumentEvent implements TestEvent {
+		
+	}
+
+	public static class StartElementEvent implements TestEvent {
+		private String uri;
+		private String localName;
+		private String qName;
+		private Attributes atts;
+		
+		public StartElementEvent(String uri, String localName, String qName,
+				Attributes atts) {
+			this.uri = uri;
+			this.localName = localName;
+			this.qName = qName;
+			this.atts = atts;
+		}
+
+		public String getURI() {
+			return uri;
+		}
+
+		public String getLocalName() {
+			return localName;
+		}
+
+		public String getQName() {
+			return qName;
+		}
+
+		public Attributes getAtts() {
+			return atts;
+		}
+	}
+
+	public static class EndElementEvent implements TestEvent {
+		private String uri;
+		private String localName;
+		private String qName;
+		
+		public EndElementEvent(String uri, String localName, String qName) {
+			this.uri = uri;
+			this.localName = localName;
+			this.qName = qName;
+		}
+
+		public String getURI() {
+			return uri;
+		}
+
+		public String getLocalName() {
+			return localName;
+		}
+
+		public String getQName() {
+			return qName;
+		}
+	}
+
+	
+	public static class CharacterEvent implements TestEvent {
+		private String characters;
+		
+		public CharacterEvent(char[] ch, int start, int length) {
+			char[] trimmed = new char[length];
+			System.arraycopy(ch, start, trimmed, 0, length);
+			this.characters = new String(trimmed);
+		}
+
+		public String getCharacters() {
+			return characters;
+		}
+	}
+	
+	public static class FatalErrorEvent implements TestEvent {
+		private Exception exception;
+
+		public FatalErrorEvent(Exception exception) {
+			this.exception = exception;
+		}
+
+		public Exception getException() {
+			return exception;
+		}
+	}
+
+	public static class ErrorEvent implements TestEvent {
+		private Exception exception;
+
+		public ErrorEvent(Exception exception) {
+			this.exception = exception;
+		}
+
+		public Exception getException() {
+			return exception;
+		}
+	}
+
+	public static class WarningEvent implements TestEvent {
+		private Exception exception;
+
+		public WarningEvent(Exception exception) {
+			this.exception = exception;
+		}
+
+		public Exception getException() {
+			return exception;
+		}
+	}
+
+	
+	private List<TestEvent> events = new ArrayList<TestEvent>();
+	
+	public List<TestEvent> getEvents() {
+		return events;
+	}
+	
+	public void characters(char[] ch, int start, int length)
+			throws SAXException {
+		events.add(new CharacterEvent(ch, start, length));
+		
+	}
+
+	public void endDocument() throws SAXException {
+		events.add(new EndDocumentEvent());
+	}
+
+	public void endElement(String uri, String localName, String qName)
+			throws SAXException {
+		events.add(new EndElementEvent(uri, localName, qName));
+		
+	}
+
+	public void endPrefixMapping(String prefix) throws SAXException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void ignorableWhitespace(char[] ch, int start, int length)
+			throws SAXException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void processingInstruction(String target, String data)
+			throws SAXException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void setDocumentLocator(Locator locator) {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void skippedEntity(String name) throws SAXException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void startDocument() throws SAXException {
+		events.add(new StartDocumentEvent());		
+	}
+
+	public void startElement(String uri, String localName, String qName,
+			Attributes atts) throws SAXException {
+		events.add(new StartElementEvent(uri, localName, qName, atts));
+		
+	}
+
+	public void startPrefixMapping(String prefix, String uri)
+			throws SAXException {
+		// TODO Auto-generated method stub
+		
+	}
+
+	public void error(SAXParseException exception) throws SAXException {
+		events.add(new ErrorEvent(exception));
+	}
+
+	public void fatalError(SAXParseException exception) throws SAXException {
+		events.add(new FatalErrorEvent(exception));		
+	}
+
+	public void warning(SAXParseException exception) throws SAXException {
+		events.add(new WarningEvent(exception));		
+	}
+
+
+}
\ No newline at end of file