Author: trustin
Date: Sun Jan 28 19:24:59 2007
New Revision: 500930

URL: http://svn.apache.org/viewvc?view=rev&rev=500930
Log:
Resolved issue: DIRMINA-343 (TextLineDecoder throws IllegalArgumentException)
* Added counter examples that shows the current TextLineDecoder implementation 
has a bug.
* Fixed the bug simplifying the implementation which doesn't use oldMatchCount 
anymore.


Modified:
    
mina/branches/1.0/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
    
mina/branches/1.0/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
    
mina/branches/1.1/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
    
mina/branches/1.1/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
    
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
    
mina/trunk/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java

Modified: 
mina/branches/1.0/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
URL: 
http://svn.apache.org/viewvc/mina/branches/1.0/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java?view=diff&rev=500930&r1=500929&r2=500930
==============================================================================
--- 
mina/branches/1.0/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
 (original)
+++ 
mina/branches/1.0/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
 Sun Jan 28 19:24:59 2007
@@ -165,7 +165,6 @@
     private int decodeAuto( ByteBuffer in, ByteBuffer buf, int matchCount, 
CharsetDecoder decoder, ProtocolDecoderOutput out ) throws 
CharacterCodingException
     {
         // Try to find a match
-        int oldMatchCount = matchCount;
         int oldPos = in.position();
         int oldLimit = in.limit();
         while( in.hasRemaining() )
@@ -192,7 +191,7 @@
             {
                 // Found a match.
                 int pos = in.position();
-                in.limit( pos - matchCount + oldMatchCount );
+                in.limit( pos );
                 in.position( oldPos );
                 
                 buf.put( in );
@@ -201,6 +200,7 @@
                     throw new BufferDataException( "Line is too long: " + 
buf.position() );
                 }
                 buf.flip();
+                buf.limit( buf.limit() - matchCount );
                 out.write( buf.getString( decoder ) );
                 buf.clear();
                 
@@ -213,7 +213,6 @@
         
         // Put remainder to buf.
         in.position( oldPos );
-        in.limit( in.limit() - matchCount + oldMatchCount );
         buf.put( in );
         
         return matchCount;
@@ -231,7 +230,6 @@
         }
         
         // Try to find a match
-        int oldMatchCount = matchCount;
         int oldPos = in.position();
         int oldLimit = in.limit();
         while( in.hasRemaining() )
@@ -244,7 +242,7 @@
                 {
                     // Found a match.
                     int pos = in.position();
-                    in.limit( pos - matchCount + oldMatchCount );
+                    in.limit( pos );
                     in.position( oldPos );
                     
                     buf.put( in );
@@ -253,6 +251,7 @@
                         throw new BufferDataException( "Line is too long: " + 
buf.position() );
                     }
                     buf.flip();
+                    buf.limit( buf.limit() - matchCount );
                     out.write( buf.getString( decoder ) );
                     buf.clear();
                     
@@ -270,7 +269,6 @@
         
         // Put remainder to buf.
         in.position( oldPos );
-        in.limit( in.limit() - matchCount + oldMatchCount );
         buf.put( in );
         
         return matchCount;

Modified: 
mina/branches/1.0/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
URL: 
http://svn.apache.org/viewvc/mina/branches/1.0/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java?view=diff&rev=500930&r1=500929&r2=500930
==============================================================================
--- 
mina/branches/1.0/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
 (original)
+++ 
mina/branches/1.0/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
 Sun Jan 28 19:24:59 2007
@@ -111,6 +111,50 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "PQR", out.getMessageQueue().pop() );
+        
+        // Test splitted long delimiter which produces two output
+        decoder = new TextLineDecoder(
+                Charset.forName( "UTF-8" ),
+                new LineDelimiter( "\n\n\n" ) );
+        in.clear();
+        in.putString( "PQR\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\nSTU\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().pop() );
+        Assert.assertEquals( "STU", out.getMessageQueue().pop() );
+        
+        // Test splitted long delimiter mixed with partial non-delimiter.
+        decoder = new TextLineDecoder(
+                Charset.forName( "UTF-8" ),
+                new LineDelimiter( "\n\n\n" ) );
+        in.clear();
+        in.putString( "PQR\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "X\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\n\nSTU\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR\nX", out.getMessageQueue().pop() );
+        Assert.assertEquals( "STU", out.getMessageQueue().pop() );
     }
     
     public void testAutoDecode() throws Exception
@@ -180,6 +224,44 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "PQR", out.getMessageQueue().pop() );
+
+        // Test splitted long delimiter (\r\r\n) which produces two output
+        in.clear();
+        in.putString( "PQR\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\nSTU\r\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().pop() );
+        Assert.assertEquals( "STU", out.getMessageQueue().pop() );
+
+        // Test splitted long delimiter mixed with partial non-delimiter.
+        in.clear();
+        in.putString( "PQR\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "X\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\r\nSTU\r\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR\rX", out.getMessageQueue().pop() );
+        Assert.assertEquals( "STU", out.getMessageQueue().pop() );
     }
     
     private static class DummySession extends BaseIoSession

Modified: 
mina/branches/1.1/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
URL: 
http://svn.apache.org/viewvc/mina/branches/1.1/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java?view=diff&rev=500930&r1=500929&r2=500930
==============================================================================
--- 
mina/branches/1.1/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
 (original)
+++ 
mina/branches/1.1/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
 Sun Jan 28 19:24:59 2007
@@ -37,273 +37,271 @@
  */
 public class TextLineDecoder implements ProtocolDecoder
 {
-       private static final String CONTEXT = TextLineDecoder.class.getName() + 
".context";
+    private static final String CONTEXT = TextLineDecoder.class.getName() + 
".context";
 
-       private final Charset charset;
-       private final LineDelimiter delimiter;
-       private ByteBuffer delimBuf;
-       private int maxLineLength = 1024;
-
-       /**
-        * Creates a new instance with the current default [EMAIL PROTECTED] 
Charset}
-        * and [EMAIL PROTECTED] LineDelimiter#AUTO} delimiter.
-        */
-       public TextLineDecoder()
-       {
-               this( Charset.defaultCharset(), LineDelimiter.AUTO );
-       }
-
-       /**
-        * Creates a new instance with the spcified <tt>charset</tt>
-        * and [EMAIL PROTECTED] LineDelimiter#AUTO} delimiter.
-        */
-       public TextLineDecoder( Charset charset )
-       {
-               this( charset, LineDelimiter.AUTO );
-       }
-
-       /**
-        * Creates a new instance with the specified <tt>charset</tt>
-        * and the specified <tt>delimiter</tt>.
-        */
-       public TextLineDecoder( Charset charset, LineDelimiter delimiter )
-       {
-               if( charset == null )
-               {
-                       throw new NullPointerException( "charset" );
-               }
-               if( delimiter == null )
-               {
-                       throw new NullPointerException( "delimiter" );
-               }
-
-               this.charset = charset;
-               this.delimiter = delimiter;
-       }
-
-       /**
-        * Returns the allowed maximum size of the line to be decoded.
-        * If the size of the line to be decoded exceeds this value, the
-        * decoder will throw a [EMAIL PROTECTED] BufferDataException}.  The 
default
-        * value is <tt>1024</tt> (1KB).
-        */
-       public int getMaxLineLength()
-       {
-               return maxLineLength;
-       }
-
-       /**
-        * Sets the allowed maximum size of the line to be decoded.
-        * If the size of the line to be decoded exceeds this value, the
-        * decoder will throw a [EMAIL PROTECTED] BufferDataException}.  The 
default
-        * value is <tt>1024</tt> (1KB).
-        */
-       public void setMaxLineLength( int maxLineLength )
-       {
-               if( maxLineLength <= 0 )
-               {
-                       throw new IllegalArgumentException( "maxLineLength: " + 
maxLineLength );
-               }
-
-               this.maxLineLength = maxLineLength;
-       }
-
-       public void decode( IoSession session, ByteBuffer in,
-                                               ProtocolDecoderOutput out )
-                       throws Exception
-       {
-               Context ctx = getContext(session);
-
-               if( LineDelimiter.AUTO.equals( delimiter ) )
-               {
-                       ctx.setMatchCount(
-                                       decodeAuto(
-                                                       in,
-                                                       ctx.getBuffer(),
-                                                       ctx.getMatchCount(),
-                                                       ctx.getDecoder(),
-                                                       out ) );
-               }
-               else
-               {
-                       ctx.setMatchCount(
-                                       decodeNormal(
-                                                       in,
-                                                       ctx.getBuffer(),
-                                                       ctx.getMatchCount(),
-                                                       ctx.getDecoder(),
-                                                       out ) );
-               }
-       }
-
-       private Context getContext(IoSession session) {
-               Context ctx = (Context) session.getAttribute( CONTEXT );
-               if( ctx == null )
-               {
-                       ctx = new Context();
-                       session.setAttribute( CONTEXT, ctx );
-               }
-               return ctx;
-       }
-
-       public void finishDecode( IoSession session, ProtocolDecoderOutput out 
) throws Exception
-       {
-       }
-
-       public void dispose( IoSession session ) throws Exception
-       {
-               Context ctx = ( Context ) session.getAttribute( CONTEXT );
-               if( ctx != null )
-               {
-                       ctx.getBuffer().release();
-                       session.removeAttribute( CONTEXT );
-               }
-       }
-
-       private int decodeAuto( ByteBuffer in, ByteBuffer buf, int matchCount, 
CharsetDecoder decoder, ProtocolDecoderOutput out ) throws 
CharacterCodingException
-       {
-               // Try to find a match
-               int oldMatchCount = matchCount;
-               int oldPos = in.position();
-               int oldLimit = in.limit();
-               while( in.hasRemaining() )
-               {
-                       byte b = in.get();
-                       boolean matched = false;
-                       switch( b )
-                       {
-                       case '\r':
-                               // Might be Mac, but we don't auto-detect Mac 
EOL
-                               // to avoid confusion.
-                               matchCount ++;
-                               break;
-                       case '\n':
-                               // UNIX
-                               matchCount ++;
-                               matched = true;
-                               break;
-                       default:
-                               matchCount = 0;
-                       }
-
-                       if( matched )
-                       {
-                               // Found a match.
-                               int pos = in.position();
-                               in.limit( pos - matchCount + oldMatchCount );
-                               in.position( oldPos );
-
-                               buf.put( in );
-                               if( buf.position() > maxLineLength )
-                               {
-                                       throw new BufferDataException( "Line is 
too long: " + buf.position() );
-                               }
-                               buf.flip();
-                               out.write( buf.getString( decoder ) );
-                               buf.clear();
-
-                               in.limit( oldLimit );
-                               in.position( pos );
-                               oldPos = pos;
-                               matchCount = 0;
-                       }
-               }
-
-               // Put remainder to buf.
-               in.position( oldPos );
-               in.limit( in.limit() - matchCount + oldMatchCount );
-               buf.put( in );
-
-               return matchCount;
-       }
-
-       private int decodeNormal( ByteBuffer in, ByteBuffer buf, int 
matchCount, CharsetDecoder decoder, ProtocolDecoderOutput out ) throws 
CharacterCodingException
-       {
-               // Convert delimiter to ByteBuffer if not done yet.
-               if( delimBuf == null )
-               {
-                       ByteBuffer tmp = ByteBuffer.allocate( 2 
).setAutoExpand( true );
-                       tmp.putString( delimiter.getValue(), 
charset.newEncoder() );
-                       tmp.flip();
-                       delimBuf = tmp;
-               }
-
-               // Try to find a match
-               int oldMatchCount = matchCount;
-               int oldPos = in.position();
-               int oldLimit = in.limit();
-               while( in.hasRemaining() )
-               {
-                       byte b = in.get();
-                       if( delimBuf.get( matchCount ) == b )
-                       {
-                               matchCount ++;
-                               if( matchCount == delimBuf.limit() )
-                               {
-                                       // Found a match.
-                                       int pos = in.position();
-                                       in.limit( pos - matchCount + 
oldMatchCount );
-                                       in.position( oldPos );
-
-                                       buf.put( in );
-                                       if( buf.position() > maxLineLength )
-                                       {
-                                               throw new BufferDataException( 
"Line is too long: " + buf.position() );
-                                       }
-                                       buf.flip();
-                                       out.write( buf.getString( decoder ) );
-                                       buf.clear();
-
-                                       in.limit( oldLimit );
-                                       in.position( pos );
-                                       oldPos = pos;
-                                       matchCount = 0;
-                               }
-                       }
-                       else
-                       {
-                               matchCount = 0;
-                       }
-               }
-
-               // Put remainder to buf.
-               in.position( oldPos );
-               in.limit( in.limit() - matchCount + oldMatchCount );
-               buf.put( in );
-
-               return matchCount;
-       }
-
-       private class Context
-       {
-               private final CharsetDecoder decoder;
-               private final ByteBuffer buf;
-               private int matchCount = 0;
-
-               private Context()
-               {
-                       decoder = charset.newDecoder();
-                       buf = ByteBuffer.allocate( 80 ).setAutoExpand( true );
-               }
-
-               public CharsetDecoder getDecoder()
-               {
-                       return decoder;
-               }
-
-               public ByteBuffer getBuffer()
-               {
-                       return buf;
-               }
-
-               public int getMatchCount()
-               {
-                       return matchCount;
-               }
-
-               public void setMatchCount( int matchCount )
-               {
-                       this.matchCount = matchCount;
-               }
-       }
+    private final Charset charset;
+    private final LineDelimiter delimiter;
+    private ByteBuffer delimBuf;
+    private int maxLineLength = 1024;
+
+    /**
+     * Creates a new instance with the current default [EMAIL PROTECTED] 
Charset}
+     * and [EMAIL PROTECTED] LineDelimiter#AUTO} delimiter.
+     */
+    public TextLineDecoder()
+    {
+        this( Charset.defaultCharset(), LineDelimiter.AUTO );
+    }
+
+    /**
+     * Creates a new instance with the spcified <tt>charset</tt>
+     * and [EMAIL PROTECTED] LineDelimiter#AUTO} delimiter.
+     */
+    public TextLineDecoder( Charset charset )
+    {
+        this( charset, LineDelimiter.AUTO );
+    }
+
+    /**
+     * Creates a new instance with the specified <tt>charset</tt>
+     * and the specified <tt>delimiter</tt>.
+     */
+    public TextLineDecoder( Charset charset, LineDelimiter delimiter )
+    {
+        if( charset == null )
+        {
+            throw new NullPointerException( "charset" );
+        }
+        if( delimiter == null )
+        {
+            throw new NullPointerException( "delimiter" );
+        }
+
+        this.charset = charset;
+        this.delimiter = delimiter;
+    }
+
+    /**
+     * Returns the allowed maximum size of the line to be decoded.
+     * If the size of the line to be decoded exceeds this value, the
+     * decoder will throw a [EMAIL PROTECTED] BufferDataException}.  The 
default
+     * value is <tt>1024</tt> (1KB).
+     */
+    public int getMaxLineLength()
+    {
+        return maxLineLength;
+    }
+
+    /**
+     * Sets the allowed maximum size of the line to be decoded.
+     * If the size of the line to be decoded exceeds this value, the
+     * decoder will throw a [EMAIL PROTECTED] BufferDataException}.  The 
default
+     * value is <tt>1024</tt> (1KB).
+     */
+    public void setMaxLineLength( int maxLineLength )
+    {
+        if( maxLineLength <= 0 )
+        {
+            throw new IllegalArgumentException( "maxLineLength: " + 
maxLineLength );
+        }
+
+        this.maxLineLength = maxLineLength;
+    }
+
+    public void decode( IoSession session, ByteBuffer in,
+                        ProtocolDecoderOutput out )
+            throws Exception
+    {
+        Context ctx = getContext(session);
+
+        if( LineDelimiter.AUTO.equals( delimiter ) )
+        {
+            ctx.setMatchCount(
+                    decodeAuto(
+                            in,
+                            ctx.getBuffer(),
+                            ctx.getMatchCount(),
+                            ctx.getDecoder(),
+                            out ) );
+        }
+        else
+        {
+            ctx.setMatchCount(
+                    decodeNormal(
+                            in,
+                            ctx.getBuffer(),
+                            ctx.getMatchCount(),
+                            ctx.getDecoder(),
+                            out ) );
+        }
+    }
+
+    private Context getContext(IoSession session) {
+        Context ctx = (Context) session.getAttribute( CONTEXT );
+        if( ctx == null )
+        {
+            ctx = new Context();
+            session.setAttribute( CONTEXT, ctx );
+        }
+        return ctx;
+    }
+
+    public void finishDecode( IoSession session, ProtocolDecoderOutput out ) 
throws Exception
+    {
+    }
+
+    public void dispose( IoSession session ) throws Exception
+    {
+        Context ctx = ( Context ) session.getAttribute( CONTEXT );
+        if( ctx != null )
+        {
+            ctx.getBuffer().release();
+            session.removeAttribute( CONTEXT );
+        }
+    }
+
+    private int decodeAuto( ByteBuffer in, ByteBuffer buf, int matchCount, 
CharsetDecoder decoder, ProtocolDecoderOutput out ) throws 
CharacterCodingException
+    {
+        // Try to find a match
+        int oldPos = in.position();
+        int oldLimit = in.limit();
+        while( in.hasRemaining() )
+        {
+            byte b = in.get();
+            boolean matched = false;
+            switch( b )
+            {
+            case '\r':
+                // Might be Mac, but we don't auto-detect Mac EOL
+                // to avoid confusion.
+                matchCount ++;
+                break;
+            case '\n':
+                // UNIX
+                matchCount ++;
+                matched = true;
+                break;
+            default:
+                matchCount = 0;
+            }
+
+            if( matched )
+            {
+                // Found a match.
+                int pos = in.position();
+                in.limit( pos );
+                in.position( oldPos );
+                
+                buf.put( in );
+                if( buf.position() > maxLineLength )
+                {
+                    throw new BufferDataException( "Line is too long: " + 
buf.position() );
+                }
+                buf.flip();
+                buf.limit( buf.limit() - matchCount );
+                out.write( buf.getString( decoder ) );
+                buf.clear();
+                
+                in.limit( oldLimit );
+                in.position( pos );
+                oldPos = pos;
+                matchCount = 0;
+            }
+        }
+        
+        // Put remainder to buf.
+        in.position( oldPos );
+        buf.put( in );
+        
+        return matchCount;
+    }
+
+    private int decodeNormal( ByteBuffer in, ByteBuffer buf, int matchCount, 
CharsetDecoder decoder, ProtocolDecoderOutput out ) throws 
CharacterCodingException
+    {
+        // Convert delimiter to ByteBuffer if not done yet.
+        if( delimBuf == null )
+        {
+            ByteBuffer tmp = ByteBuffer.allocate( 2 ).setAutoExpand( true );
+            tmp.putString( delimiter.getValue(), charset.newEncoder() );
+            tmp.flip();
+            delimBuf = tmp;
+        }
+        
+        // Try to find a match
+        int oldPos = in.position();
+        int oldLimit = in.limit();
+        while( in.hasRemaining() )
+        {
+            byte b = in.get();
+            if( delimBuf.get( matchCount ) == b )
+            {
+                matchCount ++;
+                if( matchCount == delimBuf.limit() )
+                {
+                    // Found a match.
+                    int pos = in.position();
+                    in.limit( pos );
+                    in.position( oldPos );
+                    
+                    buf.put( in );
+                    if( buf.position() > maxLineLength )
+                    {
+                        throw new BufferDataException( "Line is too long: " + 
buf.position() );
+                    }
+                    buf.flip();
+                    buf.limit( buf.limit() - matchCount );
+                    out.write( buf.getString( decoder ) );
+                    buf.clear();
+                    
+                    in.limit( oldLimit );
+                    in.position( pos );
+                    oldPos = pos;
+                    matchCount = 0;
+                }
+            }
+            else
+            {
+                matchCount = 0;
+            }
+        }
+        
+        // Put remainder to buf.
+        in.position( oldPos );
+        buf.put( in );
+        
+        return matchCount;
+    }
+
+    private class Context
+    {
+        private final CharsetDecoder decoder;
+        private final ByteBuffer buf;
+        private int matchCount = 0;
+
+        private Context()
+        {
+            decoder = charset.newDecoder();
+            buf = ByteBuffer.allocate( 80 ).setAutoExpand( true );
+        }
+
+        public CharsetDecoder getDecoder()
+        {
+            return decoder;
+        }
+
+        public ByteBuffer getBuffer()
+        {
+            return buf;
+        }
+
+        public int getMatchCount()
+        {
+            return matchCount;
+        }
+
+        public void setMatchCount( int matchCount )
+        {
+            this.matchCount = matchCount;
+        }
+    }
 }

Modified: 
mina/branches/1.1/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
URL: 
http://svn.apache.org/viewvc/mina/branches/1.1/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java?view=diff&rev=500930&r1=500929&r2=500930
==============================================================================
--- 
mina/branches/1.1/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
 (original)
+++ 
mina/branches/1.1/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
 Sun Jan 28 19:24:59 2007
@@ -56,19 +56,19 @@
         TextLineDecoder decoder =
             new TextLineDecoder(
                     Charset.forName( "UTF-8" ), LineDelimiter.WINDOWS );
-
+        
         CharsetEncoder encoder = Charset.forName( "UTF-8" ).newEncoder();
         IoSession session = new DummySession();
         TestDecoderOutput out = new TestDecoderOutput();
         ByteBuffer in = ByteBuffer.allocate( 16 );
-
+     
         // Test one decode and one output
         in.putString( "ABC\r\n", encoder );
         in.flip();
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "ABC", out.getMessageQueue().poll() );
-
+        
         // Test two decode and one output
         in.clear();
         in.putString( "DEF", encoder );
@@ -81,7 +81,7 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "DEFGHI", out.getMessageQueue().poll() );
-
+        
         // Test one decode and two output
         in.clear();
         in.putString( "JKL\r\nMNO\r\n", encoder );
@@ -90,7 +90,7 @@
         Assert.assertEquals( 2, out.getMessageQueue().size() );
         Assert.assertEquals( "JKL", out.getMessageQueue().poll() );
         Assert.assertEquals( "MNO", out.getMessageQueue().poll() );
-
+        
         // Test splitted long delimiter
         decoder = new TextLineDecoder(
                 Charset.forName( "UTF-8" ),
@@ -111,26 +111,70 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
-    }
 
+        // Test splitted long delimiter which produces two output
+        decoder = new TextLineDecoder(
+                Charset.forName( "UTF-8" ),
+                new LineDelimiter( "\n\n\n" ) );
+        in.clear();
+        in.putString( "PQR\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\nSTU\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );
+        
+        // Test splitted long delimiter mixed with partial non-delimiter.
+        decoder = new TextLineDecoder(
+                Charset.forName( "UTF-8" ),
+                new LineDelimiter( "\n\n\n" ) );
+        in.clear();
+        in.putString( "PQR\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "X\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\n\nSTU\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR\nX", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );
+    }
+    
     public void testAutoDecode() throws Exception
     {
         TextLineDecoder decoder =
             new TextLineDecoder(
                     Charset.forName( "UTF-8" ), LineDelimiter.AUTO );
-
+        
         CharsetEncoder encoder = Charset.forName( "UTF-8" ).newEncoder();
         IoSession session = new DummySession();
         TestDecoderOutput out = new TestDecoderOutput();
         ByteBuffer in = ByteBuffer.allocate( 16 );
-
+     
         // Test one decode and one output
         in.putString( "ABC\r\n", encoder );
         in.flip();
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "ABC", out.getMessageQueue().poll() );
-
+        
         // Test two decode and one output
         in.clear();
         in.putString( "DEF", encoder );
@@ -143,7 +187,7 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "DEFGHI", out.getMessageQueue().poll() );
-
+        
         // Test one decode and two output
         in.clear();
         in.putString( "JKL\r\nMNO\r\n", encoder );
@@ -152,7 +196,7 @@
         Assert.assertEquals( 2, out.getMessageQueue().size() );
         Assert.assertEquals( "JKL", out.getMessageQueue().poll() );
         Assert.assertEquals( "MNO", out.getMessageQueue().poll() );
-
+        
         // Test multiple '\n's
         in.clear();
         in.putString( "\n\n\n", encoder );
@@ -162,7 +206,7 @@
         Assert.assertEquals( "", out.getMessageQueue().poll() );
         Assert.assertEquals( "", out.getMessageQueue().poll() );
         Assert.assertEquals( "", out.getMessageQueue().poll() );
-
+        
         // Test splitted long delimiter (\r\r\n)
         in.clear();
         in.putString( "PQR\r", encoder );
@@ -180,8 +224,46 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
-    }
 
+        // Test splitted long delimiter (\r\r\n) which produces two output
+        in.clear();
+        in.putString( "PQR\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\nSTU\r\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );
+
+        // Test splitted long delimiter mixed with partial non-delimiter.
+        in.clear();
+        in.putString( "PQR\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "X\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\r\nSTU\r\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR\rX", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );    
+    }
+    
     private static class DummySession extends BaseIoSession
     {
         @Override

Modified: 
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
URL: 
http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java?view=diff&rev=500930&r1=500929&r2=500930
==============================================================================
--- 
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
 (original)
+++ 
mina/trunk/core/src/main/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
 Sun Jan 28 19:24:59 2007
@@ -164,7 +164,6 @@
     private int decodeAuto( ByteBuffer in, ByteBuffer buf, int matchCount, 
CharsetDecoder decoder, ProtocolDecoderOutput out ) throws 
CharacterCodingException
     {
         // Try to find a match
-        int oldMatchCount = matchCount;
         int oldPos = in.position();
         int oldLimit = in.limit();
         while( in.hasRemaining() )
@@ -191,7 +190,7 @@
             {
                 // Found a match.
                 int pos = in.position();
-                in.limit( pos - matchCount + oldMatchCount );
+                in.limit( pos );
                 in.position( oldPos );
                 
                 buf.put( in );
@@ -200,6 +199,7 @@
                     throw new BufferDataException( "Line is too long: " + 
buf.position() );
                 }
                 buf.flip();
+                buf.limit( buf.limit() - matchCount );
                 out.write( buf.getString( decoder ) );
                 buf.clear();
                 
@@ -212,7 +212,6 @@
         
         // Put remainder to buf.
         in.position( oldPos );
-        in.limit( in.limit() - matchCount + oldMatchCount );
         buf.put( in );
         
         return matchCount;
@@ -230,7 +229,6 @@
         }
         
         // Try to find a match
-        int oldMatchCount = matchCount;
         int oldPos = in.position();
         int oldLimit = in.limit();
         while( in.hasRemaining() )
@@ -243,7 +241,7 @@
                 {
                     // Found a match.
                     int pos = in.position();
-                    in.limit( pos - matchCount + oldMatchCount );
+                    in.limit( pos );
                     in.position( oldPos );
                     
                     buf.put( in );
@@ -252,6 +250,7 @@
                         throw new BufferDataException( "Line is too long: " + 
buf.position() );
                     }
                     buf.flip();
+                    buf.limit( buf.limit() - matchCount );
                     out.write( buf.getString( decoder ) );
                     buf.clear();
                     
@@ -269,7 +268,6 @@
         
         // Put remainder to buf.
         in.position( oldPos );
-        in.limit( in.limit() - matchCount + oldMatchCount );
         buf.put( in );
         
         return matchCount;

Modified: 
mina/trunk/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
URL: 
http://svn.apache.org/viewvc/mina/trunk/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java?view=diff&rev=500930&r1=500929&r2=500930
==============================================================================
--- 
mina/trunk/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
 (original)
+++ 
mina/trunk/core/src/test/java/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
 Sun Jan 28 19:24:59 2007
@@ -111,6 +111,50 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
+
+        // Test splitted long delimiter which produces two output
+        decoder = new TextLineDecoder(
+                Charset.forName( "UTF-8" ),
+                new LineDelimiter( "\n\n\n" ) );
+        in.clear();
+        in.putString( "PQR\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\nSTU\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );
+        
+        // Test splitted long delimiter mixed with partial non-delimiter.
+        decoder = new TextLineDecoder(
+                Charset.forName( "UTF-8" ),
+                new LineDelimiter( "\n\n\n" ) );
+        in.clear();
+        in.putString( "PQR\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "X\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\n\nSTU\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR\nX", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );
     }
     
     public void testAutoDecode() throws Exception
@@ -180,6 +224,44 @@
         decoder.decode( session, in, out );
         Assert.assertEquals( 1, out.getMessageQueue().size() );
         Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
+
+        // Test splitted long delimiter (\r\r\n) which produces two output
+        in.clear();
+        in.putString( "PQR\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\nSTU\r\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );
+
+        // Test splitted long delimiter mixed with partial non-delimiter.
+        in.clear();
+        in.putString( "PQR\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "X\r", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "\r\nSTU\r\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR\rX", out.getMessageQueue().poll() );
+        Assert.assertEquals( "STU", out.getMessageQueue().poll() );    
     }
     
     private static class DummySession extends BaseIoSession


Reply via email to