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/07 17:59:17 UTC

svn commit: r888001 - in /mina/sandbox/vysper/trunk/nbxml/src: main/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoder.java test/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoderTestCase.java

Author: ngn
Date: Mon Dec  7 16:59:17 2009
New Revision: 888001

URL: http://svn.apache.org/viewvc?rev=888001&view=rev
Log:
Adding a simple statemachine when parsing XML as to handle some odd cases

Added:
    mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoderTestCase.java
Modified:
    mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoder.java

Modified: mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoder.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoder.java?rev=888001&r1=888000&r2=888001&view=diff
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoder.java (original)
+++ mina/sandbox/vysper/trunk/nbxml/src/main/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoder.java Mon Dec  7 16:59:17 2009
@@ -29,6 +29,19 @@
  * @author The Apache MINA Project (dev@mina.apache.org)
  */
 public class ParticleDecoder {
+	
+	private enum State { 
+		START, IN_TEXT, IN_TAG, IN_DOUBLE_ATTRIBUTE, IN_SINGLE_ATTRIBUTE, END, END_TEXT;
+		
+		public static boolean inAttribute(State state) {
+			return state == IN_DOUBLE_ATTRIBUTE || state == IN_SINGLE_ATTRIBUTE;
+		}
+
+		public static boolean atEnd(State state) {
+			return state == END || state == END_TEXT;
+		}
+}
+	
     /**
      * split in String, either in those parts enclosed by brackets or those who are not
      * @param byteBuffer
@@ -39,24 +52,42 @@
     public static XMLParticle decodeParticle(ByteBuffer byteBuffer, CharsetDecoder charsetDecoder) throws Exception {
         int startPosition = byteBuffer.position();
 
-        //String DEBUG_VORDERBAND = byteBuffer.duplicate().getString(charsetDecoder);
+        State state = State.START;
 
         if (!byteBuffer.hasRemaining()) return null;
 
         // count opening and closing braces
         char firstChar = (char)byteBuffer.get();
-        boolean plainText = firstChar != '<';
+        if(firstChar == '<') {
+        	state = State.IN_TAG;
+        } else {
+        	state = State.IN_TEXT;
+        }
 
-        boolean endReached = false;
         while (byteBuffer.remaining() > 0) {
             char aChar = (char)byteBuffer.get();
 
-            if (plainText && aChar == '<') endReached = true;
-            if (!plainText && aChar == '>') endReached = true;
-
-            if (endReached) {
+			if (state != State.IN_TEXT && state != State.IN_SINGLE_ATTRIBUTE && aChar == '"') {
+				if (state == State.IN_DOUBLE_ATTRIBUTE) {
+					state = State.IN_TAG;
+				} else {
+					state = State.IN_DOUBLE_ATTRIBUTE;
+				}
+			}
+			if (state != State.IN_TEXT && state != State.IN_DOUBLE_ATTRIBUTE && aChar == '\'') {
+				if (state == State.IN_SINGLE_ATTRIBUTE) {
+					state = State.IN_TAG;
+				} else {
+					state = State.IN_SINGLE_ATTRIBUTE;
+				}
+			}
+
+            if (state == State.IN_TEXT && aChar == '<') state = State.END_TEXT;
+            if (state != State.IN_TEXT && !State.inAttribute(state) && aChar == '>') state = State.END;
+            
+            if (State.atEnd(state)) {
                 int endPosition = byteBuffer.position();
-                if (plainText) endPosition--;
+                if (state == State.END_TEXT) endPosition--;
                 int limit = byteBuffer.limit();
                 ByteBuffer stanzaBuffer = null;
                 try {
@@ -69,8 +100,7 @@
                     byteBuffer.position(endPosition);
                     byteBuffer.limit(limit);
                 }
-                //String DEBUG_HINTERBAND = stanzaBuffer.duplicate().getString(charsetDecoder);
-                //String DEBUG_REMAINS = byteBuffer.duplicate().getString(charsetDecoder);
+
                 String content = stanzaBuffer.getString(charsetDecoder);
                 return new XMLParticle(content);
             }

Added: mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoderTestCase.java
URL: http://svn.apache.org/viewvc/mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoderTestCase.java?rev=888001&view=auto
==============================================================================
--- mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoderTestCase.java (added)
+++ mina/sandbox/vysper/trunk/nbxml/src/test/java/org/apache/vysper/xmpp/xmldecoder/ParticleDecoderTestCase.java Mon Dec  7 16:59:17 2009
@@ -0,0 +1,130 @@
+/*
+ *  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.xmpp.xmldecoder;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.vysper.charset.CharsetUtil;
+
+/**
+ */
+public class ParticleDecoderTestCase extends TestCase {
+
+	public void testSimple() throws Exception {
+		List<XMLParticle> particles = decodeAll("<root>text</root>");
+		XMLParticle opening = particles.get(0);
+		XMLParticle text = particles.get(1);
+		XMLParticle closing = particles.get(2);
+		
+		assertTrue(opening.isOpeningElement());
+		assertEquals("root", opening.getElementName());
+		
+		assertTrue(text.isText());
+		assertEquals("text", text.getContent());
+		
+		assertTrue(closing.isClosingElement());
+		assertEquals("root", closing.getElementName());
+	}
+
+	public void testParseDoubleQuoteAttributes() throws Exception {
+		String xml = "<root att=\"foo\">";
+		XMLParticle opening = decode(xml);
+		
+		assertTrue(opening.isOpeningElement());
+		assertEquals("root", opening.getElementName());
+		assertEquals(xml, opening.getContent());
+	}
+
+	public void testParseSingleQuoteAttributes() throws Exception {
+		String xml = "<root att='f\"oo'>";
+		XMLParticle opening = decode(xml);
+		
+		assertTrue(opening.isOpeningElement());
+		assertEquals("root", opening.getElementName());
+		assertEquals(xml, opening.getContent());
+	}
+
+	public void testParseAttributeWithLt() throws Exception {
+		// TODO This is not supported as per the XML spec, we might want to fail already in ParticleDecoder
+		String xml = "<root att='<'>";
+		XMLParticle opening = decode(xml);
+		
+		assertTrue(opening.isOpeningElement());
+		assertEquals("root", opening.getElementName());
+		assertEquals(xml, opening.getContent());
+	}
+
+	public void testParseAttributeWithGt() throws Exception {
+		String xml = "<root att='>'>";
+		XMLParticle opening = decode(xml);
+		assertTrue(opening.isOpeningElement());
+		assertEquals("root", opening.getElementName());
+		assertEquals(xml, opening.getContent());
+	}
+	
+	public void testParseComment() throws Exception {
+		XMLParticle opening = decode("<!-- comment -->");
+		
+		assertTrue(opening.isOpeningElement());
+		// TODO activate when XMLParticle supports comments
+		// assertNull(opening.getElementName());
+		assertEquals("<!-- comment -->", opening.getContent());
+	}
+
+	public void testParsePI() throws Exception {
+		String xml = "<?pi att=\"foo\" ?>";
+		XMLParticle opening = decode(xml);
+		
+		assertTrue(opening.isOpeningElement());
+		assertEquals("pi", opening.getElementName());
+		assertEquals(xml, opening.getContent());
+	}
+
+	
+	private ByteBuffer wrap(String xml) throws Exception {
+		return ByteBuffer.wrap(xml.getBytes("UTF-8"));
+	}
+	
+	private XMLParticle decode(String xml) throws Exception {
+		return decode(wrap(xml));
+	}
+
+	private XMLParticle decode(ByteBuffer bb) throws Exception {
+		return ParticleDecoder.decodeParticle(bb, CharsetUtil.UTF8_DECODER);
+	}
+
+	private List<XMLParticle> decodeAll(String xml) throws Exception {
+		ByteBuffer bb = wrap(xml);
+		List<XMLParticle> particles = new ArrayList<XMLParticle>();
+		
+		XMLParticle particle = decode(bb);
+		while(particle != null) {
+			particles.add(particle);
+			
+			particle = decode(bb);
+		}
+		return particles; 
+	}
+
+}