directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From trus...@apache.org
Subject svn commit: r354780 - in /directory/network: branches/0.8/src/java/org/apache/mina/common/ trunk/src/examples/org/apache/mina/examples/reverser/ trunk/src/java/org/apache/mina/common/ trunk/src/java/org/apache/mina/filter/codec/textline/ trunk/src/test...
Date Wed, 07 Dec 2005 15:49:24 GMT
Author: trustin
Date: Wed Dec  7 07:49:02 2005
New Revision: 354780

URL: http://svn.apache.org/viewcvs?rev=354780&view=rev
Log:
Resolved issue: DIRMINA-141 (Infinite loop in ByteBuffer.get/putString())
* Added 1 to expectedLength variable

Resovled issue: DIRMINA-142 (Codec for text protocols)
* Added TextLineDecoder
* Added TextLineEncoder
* Added TextLineCodecFactory


Added:
    directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/
    directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
  (with props)
    directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.java
  (with props)
    directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
  (with props)
    directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineEncoder.java
  (with props)
    directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/
    directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
  (with props)
    directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineEncoderTest.java
  (with props)
Removed:
    directory/network/trunk/src/examples/org/apache/mina/examples/reverser/TextLineDecoder.java
    directory/network/trunk/src/examples/org/apache/mina/examples/reverser/TextLineEncoder.java
Modified:
    directory/network/branches/0.8/src/java/org/apache/mina/common/ByteBuffer.java
    directory/network/trunk/src/examples/org/apache/mina/examples/reverser/ReverseProtocolHandler.java
    directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java

Modified: directory/network/branches/0.8/src/java/org/apache/mina/common/ByteBuffer.java
URL: http://svn.apache.org/viewcvs/directory/network/branches/0.8/src/java/org/apache/mina/common/ByteBuffer.java?rev=354780&r1=354779&r2=354780&view=diff
==============================================================================
--- directory/network/branches/0.8/src/java/org/apache/mina/common/ByteBuffer.java (original)
+++ directory/network/branches/0.8/src/java/org/apache/mina/common/ByteBuffer.java Wed Dec
 7 07:49:02 2005
@@ -1092,7 +1092,7 @@
             }
             decoder.reset();
 
-            int expectedLength = (int) ( buf.remaining() * decoder.averageCharsPerByte()
);
+            int expectedLength = (int) ( buf.remaining() * decoder.averageCharsPerByte()
) + 1;
             CharBuffer out = CharBuffer.allocate( expectedLength );
             for( ;; )
             {
@@ -1207,7 +1207,7 @@
             }
             decoder.reset();
 
-            int expectedLength = (int) ( buf.remaining() * decoder.averageCharsPerByte()
);
+            int expectedLength = (int) ( buf.remaining() * decoder.averageCharsPerByte()
) + 1;
             CharBuffer out = CharBuffer.allocate( expectedLength );
             for( ;; )
             {
@@ -1333,7 +1333,7 @@
             }
             
             CharBuffer in = CharBuffer.wrap( val ); 
-            int expectedLength = (int) (in.remaining() * encoder.averageBytesPerChar());
+            int expectedLength = (int) (in.remaining() * encoder.averageBytesPerChar()) +
1;
 
             encoder.reset();
 

Modified: directory/network/trunk/src/examples/org/apache/mina/examples/reverser/ReverseProtocolHandler.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/examples/org/apache/mina/examples/reverser/ReverseProtocolHandler.java?rev=354780&r1=354779&r2=354780&view=diff
==============================================================================
--- directory/network/trunk/src/examples/org/apache/mina/examples/reverser/ReverseProtocolHandler.java
(original)
+++ directory/network/trunk/src/examples/org/apache/mina/examples/reverser/ReverseProtocolHandler.java
Wed Dec  7 07:49:02 2005
@@ -23,10 +23,8 @@
 import org.apache.mina.common.IoHandlerAdapter;
 import org.apache.mina.common.IoSession;
 import org.apache.mina.filter.LoggingFilter;
-import org.apache.mina.filter.codec.ProtocolCodecFactory;
 import org.apache.mina.filter.codec.ProtocolCodecFilter;
-import org.apache.mina.filter.codec.ProtocolDecoder;
-import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.textline.TextLineCodecFactory;
 
 /**
  * {@link IoHandler} implementation of reverser server protocol.
@@ -37,28 +35,13 @@
 public class ReverseProtocolHandler extends IoHandlerAdapter
 {
     private static IoFilter LOGGING_FILTER = new LoggingFilter();
-    
-    private static ProtocolCodecFactory CODEC_FACTORY = new ProtocolCodecFactory()
-    {
-        public ProtocolEncoder getEncoder()
-        {
-            // Create a new encoder.
-            return new TextLineEncoder();
-        }
-
-        public ProtocolDecoder getDecoder()
-        {
-            // Create a new decoder.
-            return new TextLineDecoder();
-        }
-    };
-
-    private static IoFilter CODEC_FILTER = new ProtocolCodecFilter( CODEC_FACTORY );
+    private static IoFilter CODEC_FILTER =
+        new ProtocolCodecFilter( new TextLineCodecFactory() );
 
     public void sessionCreated( IoSession session ) throws Exception
     {
-        session.getFilterChain().addLast( "codec", CODEC_FILTER );
         session.getFilterChain().addLast( "logger", LOGGING_FILTER );
+        session.getFilterChain().addLast( "codec", CODEC_FILTER );
     }
 
     public void exceptionCaught( IoSession session, Throwable cause )

Modified: directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java?rev=354780&r1=354779&r2=354780&view=diff
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java (original)
+++ directory/network/trunk/src/java/org/apache/mina/common/ByteBuffer.java Wed Dec  7 07:49:02
2005
@@ -972,7 +972,7 @@
         }
         decoder.reset();
 
-        int expectedLength = (int) ( remaining() * decoder.averageCharsPerByte() );
+        int expectedLength = (int) ( remaining() * decoder.averageCharsPerByte() ) + 1;
         CharBuffer out = CharBuffer.allocate( expectedLength );
         for( ;; )
         {
@@ -1093,7 +1093,7 @@
         }
         decoder.reset();
 
-        int expectedLength = (int) ( remaining() * decoder.averageCharsPerByte() );
+        int expectedLength = (int) ( remaining() * decoder.averageCharsPerByte() ) + 1;
         CharBuffer out = CharBuffer.allocate( expectedLength );
         for( ;; )
         {
@@ -1145,7 +1145,7 @@
         }
         
         CharBuffer in = CharBuffer.wrap( val ); 
-        int expectedLength = (int) (in.remaining() * encoder.averageBytesPerChar());
+        int expectedLength = (int) (in.remaining() * encoder.averageBytesPerChar()) + 1;
 
         encoder.reset();
 
@@ -1330,7 +1330,7 @@
         limit( end );
         decoder.reset();
 
-        int expectedLength = (int) ( remaining() * decoder.averageCharsPerByte() );
+        int expectedLength = (int) ( remaining() * decoder.averageCharsPerByte() ) + 1;
         CharBuffer out = CharBuffer.allocate( expectedLength );
         for( ;; )
         {
@@ -1478,7 +1478,7 @@
         }
 
         CharBuffer in = CharBuffer.wrap( val ); 
-        int expectedLength = (int) (in.remaining() * encoder.averageBytesPerChar());
+        int expectedLength = (int) (in.remaining() * encoder.averageBytesPerChar()) + 1;
 
         skip( prefixLength ); // make a room for the length field
         int oldPos = position();

Added: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/LineDelimiter.java?rev=354780&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
(added)
+++ directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
Wed Dec  7 07:49:02 2005
@@ -0,0 +1,125 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.mina.filter.codec.textline;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintWriter;
+
+/**
+ * A delimiter which is appended to the end of a text line, such as
+ * <tt>CR/LF</tt>.
+ *
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class LineDelimiter
+{
+    /**
+     * the line delimiter constant of the current O/S.
+     */
+    public static final LineDelimiter DEFAULT;
+    
+    static
+    {
+        ByteArrayOutputStream bout = new ByteArrayOutputStream();
+        PrintWriter out = new PrintWriter( bout );
+        out.println();
+        DEFAULT = new LineDelimiter( new String( bout.toByteArray() ) );
+    }
+    
+    /**
+     * A special line delimiter which is used for auto-detection of
+     * EOL in {@link TextLineDecoder}.  If this delimiter is used,
+     * {@link TextLineDecoder} will consider both  <tt>'\r'</tt> and
+     * <tt>'\n'</tt> as a delimiter. 
+     */
+    public static final LineDelimiter AUTO = new LineDelimiter( "" );
+    
+    /**
+     * The line delimiter constant of UNIX (<tt>"\n"</tt>)
+     */
+    public static final LineDelimiter UNIX = new LineDelimiter( "\n" );
+
+    /**
+     * The line delimiter constant of MS Windows/DOS (<tt>"\r\n"</tt>)
+     */
+    public static final LineDelimiter WINDOWS = new LineDelimiter( "\r\n" );
+    
+    /**
+     * The line delimiter constant of Mac OS (<tt>"\r"</tt>)
+     */
+    public static final LineDelimiter MAC = new LineDelimiter( "\r" );
+    
+    private final String value;
+
+    /**
+     * Creates a new line delimiter with the specified <tt>value</tt>.
+     */
+    public LineDelimiter( String value )
+    {
+        if( value == null )
+        {
+            throw new NullPointerException( "delimiter" );
+        }
+        this.value = value;
+    }
+
+    /**
+     * Return the delimiter string.
+     */
+    public String getValue()
+    {
+        return value;
+    }
+    
+    public int hashCode()
+    {
+        return value.hashCode();
+    }
+    
+    public boolean equals( Object o )
+    {
+        if( !( o instanceof LineDelimiter ) )
+        {
+            return false;
+        }
+        
+        LineDelimiter that = ( LineDelimiter ) o;
+        return this.value.equals( that.value );
+    }
+    
+    public String toString()
+    {
+        StringBuffer buf = new StringBuffer();
+        buf.append( "delimiter:" );
+        if( value.length() == 0 )
+        {
+            buf.append( " auto" );
+        }
+        else
+        {
+            for( int i = 0; i < value.length(); i ++ )
+            {
+                buf.append( " 0x" );
+                buf.append( Integer.toHexString( value.charAt( i ) ) );
+            }
+        }
+        return buf.toString();
+    }
+}

Propchange: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/LineDelimiter.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.java?rev=354780&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.java
(added)
+++ directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.java
Wed Dec  7 07:49:02 2005
@@ -0,0 +1,121 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.mina.filter.codec.textline;
+
+import java.nio.charset.Charset;
+
+import org.apache.mina.common.BufferDataException;
+import org.apache.mina.filter.codec.ProtocolCodecFactory;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+import org.apache.mina.filter.codec.serialization.ObjectSerializationDecoder;
+import org.apache.mina.filter.codec.serialization.ObjectSerializationEncoder;
+
+/**
+ * A {@link ProtocolCodecFactory} that serializes and deserializes Java objects.
+ * This codec is very useful when you have to prototype your application rapidly
+ * without any specific codec.
+ *
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$
+ */
+public class TextLineCodecFactory implements ProtocolCodecFactory
+{
+    private final TextLineEncoder encoder;
+    private final TextLineDecoder decoder;
+    
+    /**
+     * Creates a new instance with the current default {@link Charset}.
+     */
+    public TextLineCodecFactory()
+    {
+        this( Charset.defaultCharset() );
+    }
+    
+    /**
+     * Creates a new instance with the specified {@link Charset}.
+     */
+    public TextLineCodecFactory( Charset charset )
+    {
+        encoder = new TextLineEncoder( charset, LineDelimiter.WINDOWS );
+        decoder = new TextLineDecoder( charset, LineDelimiter.WINDOWS );
+    }
+
+    public ProtocolEncoder getEncoder()
+    {
+        return encoder;
+    }
+
+    public ProtocolDecoder getDecoder()
+    {
+        return decoder;
+    }
+    
+    /**
+     * Returns the allowed maximum size of the encoded object.
+     * If the size of the encoded object exceeds this value, the encoder
+     * will throw a {@link IllegalArgumentException}.  The default value
+     * is {@link Integer#MAX_VALUE}.
+     * <p>
+     * This method does the same job with {@link ObjectSerializationEncoder#setMaxObjectSize(int)}.
+     */
+    public int gerEncoderMaxLineLength()
+    {
+        return encoder.getMaxLineLength();
+    }
+    
+    /**
+     * Sets the allowed maximum size of the encoded object.
+     * If the size of the encoded object exceeds this value, the encoder
+     * will throw a {@link IllegalArgumentException}.  The default value
+     * is {@link Integer#MAX_VALUE}.
+     * <p>
+     * This method does the same job with {@link ObjectSerializationEncoder#setMaxObjectSize(int)}.
+     */
+    public void setEncoderMaxLineLength( int maxLineLength )
+    {
+        encoder.setMaxLineLength( maxLineLength );
+    }
+    
+    /**
+     * Returns the allowed maximum size of the object to be decoded.
+     * If the size of the object to be decoded exceeds this value, the
+     * decoder will throw a {@link BufferDataException}.  The default
+     * value is <tt>1048576</tt> (1MB).
+     * <p>
+     * This method does the same job with {@link ObjectSerializationDecoder#getMaxObjectSize()}.
+     */
+    public int gerDecoderMaxLineLength()
+    {
+        return decoder.getMaxLineLength();
+    }
+    
+    /**
+     * Sets the allowed maximum size of the object to be decoded.
+     * If the size of the object to be decoded exceeds this value, the
+     * decoder will throw a {@link BufferDataException}.  The default
+     * value is <tt>1048576</tt> (1MB).
+     * <p>
+     * This method does the same job with {@link ObjectSerializationDecoder#setMaxObjectSize(int)}.
+     */
+    public void setDecoderMaxLineLength( int maxLineLength )
+    {
+        decoder.setMaxLineLength( maxLineLength );
+    }
+}

Propchange: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineCodecFactory.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java?rev=354780&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
(added)
+++ directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
Wed Dec  7 07:49:02 2005
@@ -0,0 +1,277 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.mina.filter.codec.textline;
+
+import java.nio.charset.CharacterCodingException;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
+
+import org.apache.mina.common.BufferDataException;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolDecoderAdapter;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+/**
+ * Decodes a text line into a string.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$,
+ */
+public class TextLineDecoder extends ProtocolDecoderAdapter
+{
+    private static final String CONTEXT = TextLineDecoder.class.getName() + ".context";
+
+    private final Charset charset;
+    private final LineDelimiter delimiter;
+    private ByteBuffer delimBuf;
+    private int maxLineLength = 1024;
+    
+    public TextLineDecoder()
+    {
+        this( Charset.defaultCharset(), LineDelimiter.AUTO );
+    }
+    
+    public TextLineDecoder( Charset charset )
+    {
+        this( charset, LineDelimiter.AUTO );
+    }
+    
+    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 encoded.
+     * If the length of the line to be encoded exceeds this value, this
+     * decoder will throw a {@link BufferDataException}.  The default
+     * value is <tt>1024</tt> (1KB).
+     */
+    public int getMaxLineLength()
+    {
+        return maxLineLength;
+    }
+    
+    /**
+     * Sets the allowed maximum size of the object to be decoded.
+     * If the size of the object to be decoded exceeds this value, this
+     * decoder will throw a {@link 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 = ( Context ) session.getAttribute( CONTEXT );
+        if( ctx == null )
+        {
+            ctx = new Context();
+            session.setAttribute( CONTEXT, ctx );
+        }
+        
+        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 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;
+        }
+    }
+}
\ No newline at end of file

Propchange: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineDecoder.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineEncoder.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineEncoder.java?rev=354780&view=auto
==============================================================================
--- directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineEncoder.java
(added)
+++ directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineEncoder.java
Wed Dec  7 07:49:02 2005
@@ -0,0 +1,132 @@
+/*
+ *   @(#) $Id$
+ *
+ *   Copyright 2004 The Apache Software Foundation
+ *
+ *   Licensed 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.mina.filter.codec.textline;
+
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+
+import org.apache.mina.common.BufferDataException;
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+
+/**
+ * Encodes a string into a text line which ends with <code>"\r\n"</code>.
+ * 
+ * @author The Apache Directory Project (dev@directory.apache.org)
+ * @version $Rev$, $Date$,
+ */
+public class TextLineEncoder extends ProtocolEncoderAdapter
+{
+    private static final String ENCODER = TextLineEncoder.class.getName() + ".encoder";
+
+    private final Charset charset;
+    private final LineDelimiter delimiter;
+    private int maxLineLength = 1024;
+
+    public TextLineEncoder()
+    {
+        this( Charset.defaultCharset(), LineDelimiter.UNIX );
+    }
+    
+    public TextLineEncoder( LineDelimiter delimiter )
+    {
+        this( Charset.defaultCharset(), delimiter );
+    }
+    
+    public TextLineEncoder( Charset charset )
+    {
+        this( charset, LineDelimiter.UNIX );
+    }
+    
+    public TextLineEncoder( Charset charset, LineDelimiter delimiter )
+    {
+        if( charset == null )
+        {
+            throw new NullPointerException( "charset" );
+        }
+        if( delimiter == null )
+        {
+            throw new NullPointerException( "delimiter" );
+        }
+        if( LineDelimiter.AUTO.equals( delimiter ) )
+        {
+            throw new IllegalArgumentException( "AUTO delimiter is not allowed for encoder."
);
+        }
+        
+        
+        this.charset = charset;
+        this.delimiter = delimiter;
+    }
+    
+    /**
+     * Returns the allowed maximum size of the line to be encoded.
+     * If the length of the line to be encoded exceeds this value, this
+     * decoder will throw a {@link BufferDataException}.  The default
+     * value is <tt>1024</tt> (1KB).
+     */
+    public int getMaxLineLength()
+    {
+        return maxLineLength;
+    }
+    
+    /**
+     * Sets the allowed maximum size of the object to be decoded.
+     * If the size of the object to be decoded exceeds this value, this
+     * decoder will throw a {@link 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 encode( IoSession session, Object message,
+                        ProtocolEncoderOutput out )
+            throws Exception
+    {
+        CharsetEncoder encoder = ( CharsetEncoder ) session.getAttribute( ENCODER );
+        if( encoder == null )
+        {
+            encoder = charset.newEncoder();
+            session.setAttribute( ENCODER, encoder );
+        }
+        
+        String value = message.toString();
+        ByteBuffer buf = ByteBuffer.allocate( value.length() ).setAutoExpand( true );
+        buf.putString( value, encoder );
+        if( buf.position() > maxLineLength )
+        {
+            throw new IllegalArgumentException( "Line length: " + buf.position() );
+        }
+        buf.putString( delimiter.getValue(), encoder );
+        buf.flip();
+        out.write( buf );
+    }
+
+    public void dispose() throws Exception
+    {
+    }
+}
\ No newline at end of file

Propchange: directory/network/trunk/src/java/org/apache/mina/filter/codec/textline/TextLineEncoder.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java?rev=354780&view=auto
==============================================================================
--- directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
(added)
+++ directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
Wed Dec  7 07:49:02 2005
@@ -0,0 +1,198 @@
+package org.apache.mina.filter.codec.textline;
+
+import java.net.SocketAddress;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetEncoder;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoSessionManager;
+import org.apache.mina.common.TransportType;
+import org.apache.mina.common.support.BaseIoSession;
+import org.apache.mina.filter.codec.support.SimpleProtocolDecoderOutput;
+
+public class TextLineDecoderTest extends TestCase
+{
+    public static void main( String[] args )
+    {
+        junit.textui.TestRunner.run( TextLineDecoderTest.class );
+    }
+
+    public void testNormalDecode() throws Exception
+    {
+        TextLineDecoder decoder =
+            new TextLineDecoder(
+                    Charset.forName( "UTF-8" ), LineDelimiter.WINDOWS );
+        
+        CharsetEncoder encoder = Charset.forName( "UTF-8" ).newEncoder();
+        IoSession session = new DummySession();
+        SimpleProtocolDecoderOutput out = new SimpleProtocolDecoderOutput();
+        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().pop() );
+        
+        // Test two decode and one output
+        in.clear();
+        in.putString( "DEF", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "GHI\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 1, out.getMessageQueue().size() );
+        Assert.assertEquals( "DEFGHI", out.getMessageQueue().pop() );
+        
+        // Test one decode and two output
+        in.clear();
+        in.putString( "JKL\r\nMNO\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "JKL", out.getMessageQueue().pop() );
+        Assert.assertEquals( "MNO", out.getMessageQueue().pop() );
+        
+        // Test splitted long 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( "\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( 1, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().pop() );
+    }
+    
+    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();
+        SimpleProtocolDecoderOutput out = new SimpleProtocolDecoderOutput();
+        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().pop() );
+        
+        // Test two decode and one output
+        in.clear();
+        in.putString( "DEF", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 0, out.getMessageQueue().size() );
+        in.clear();
+        in.putString( "GHI\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 1, out.getMessageQueue().size() );
+        Assert.assertEquals( "DEFGHI", out.getMessageQueue().pop() );
+        
+        // Test one decode and two output
+        in.clear();
+        in.putString( "JKL\r\nMNO\r\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 2, out.getMessageQueue().size() );
+        Assert.assertEquals( "JKL", out.getMessageQueue().pop() );
+        Assert.assertEquals( "MNO", out.getMessageQueue().pop() );
+        
+        // Test multiple '\n's
+        in.clear();
+        in.putString( "\n\n\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 3, out.getMessageQueue().size() );
+        Assert.assertEquals( "", out.getMessageQueue().pop() );
+        Assert.assertEquals( "", out.getMessageQueue().pop() );
+        Assert.assertEquals( "", out.getMessageQueue().pop() );
+        
+        // Test splitted long delimiter (\r\r\n)
+        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( "\n", encoder );
+        in.flip();
+        decoder.decode( session, in, out );
+        Assert.assertEquals( 1, out.getMessageQueue().size() );
+        Assert.assertEquals( "PQR", out.getMessageQueue().pop() );
+    }
+    
+    private static class DummySession extends BaseIoSession
+    {
+        protected void updateTrafficMask()
+        {
+        }
+
+        public IoSessionManager getManager()
+        {
+            return null;
+        }
+
+        public IoHandler getHandler()
+        {
+            return null;
+        }
+
+        public IoFilterChain getFilterChain()
+        {
+            return null;
+        }
+
+        public TransportType getTransportType()
+        {
+            return null;
+        }
+
+        public SocketAddress getRemoteAddress()
+        {
+            return null;
+        }
+
+        public SocketAddress getLocalAddress()
+        {
+            return null;
+        }
+
+        public int getScheduledWriteRequests()
+        {
+            return 0;
+        }
+    }
+}

Propchange: directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineDecoderTest.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineEncoderTest.java
URL: http://svn.apache.org/viewcvs/directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineEncoderTest.java?rev=354780&view=auto
==============================================================================
--- directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineEncoderTest.java
(added)
+++ directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineEncoderTest.java
Wed Dec  7 07:49:02 2005
@@ -0,0 +1,92 @@
+package org.apache.mina.filter.codec.textline;
+
+import java.net.SocketAddress;
+import java.nio.charset.Charset;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+import org.apache.mina.common.ByteBuffer;
+import org.apache.mina.common.IoFilterChain;
+import org.apache.mina.common.IoHandler;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.IoSessionManager;
+import org.apache.mina.common.TransportType;
+import org.apache.mina.common.WriteFuture;
+import org.apache.mina.common.support.BaseIoSession;
+import org.apache.mina.filter.codec.support.SimpleProtocolEncoderOutput;
+
+public class TextLineEncoderTest extends TestCase
+{
+    public static void main( String[] args )
+    {
+        junit.textui.TestRunner.run( TextLineEncoderTest.class );
+    }
+
+    public void testEncode() throws Exception
+    {
+        TextLineEncoder encoder = new TextLineEncoder(
+                Charset.forName( "UTF-8" ), LineDelimiter.WINDOWS );
+        IoSession session = new DummySession();
+        SimpleProtocolEncoderOutput out =
+            new SimpleProtocolEncoderOutput()
+            {
+                protected WriteFuture doFlush( ByteBuffer buf )
+                {
+                    return null;
+                }
+            };
+        
+        encoder.encode( session, "ABC", out );
+        Assert.assertEquals( 1, out.getBufferQueue().size() );
+        ByteBuffer buf = ( ByteBuffer ) out.getBufferQueue().pop();
+        Assert.assertEquals( 5, buf.remaining() );
+        Assert.assertEquals( 'A', buf.get() );
+        Assert.assertEquals( 'B', buf.get() );
+        Assert.assertEquals( 'C', buf.get() );
+        Assert.assertEquals( '\r', buf.get() );
+        Assert.assertEquals( '\n', buf.get() );
+    }
+
+    private static class DummySession extends BaseIoSession
+    {
+        protected void updateTrafficMask()
+        {
+        }
+
+        public IoSessionManager getManager()
+        {
+            return null;
+        }
+
+        public IoHandler getHandler()
+        {
+            return null;
+        }
+
+        public IoFilterChain getFilterChain()
+        {
+            return null;
+        }
+
+        public TransportType getTransportType()
+        {
+            return null;
+        }
+
+        public SocketAddress getRemoteAddress()
+        {
+            return null;
+        }
+
+        public SocketAddress getLocalAddress()
+        {
+            return null;
+        }
+
+        public int getScheduledWriteRequests()
+        {
+            return 0;
+        }
+    }
+}

Propchange: directory/network/trunk/src/test/org/apache/mina/filter/codec/textline/TextLineEncoderTest.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision



Mime
View raw message