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