mina-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From Emmanuel Lécharny <elecha...@gmail.com>
Subject Re: git commit: Added text line coded and related unit tests
Date Mon, 08 Apr 2013 00:09:27 GMT
A small sugestion :

the DEFAUKT value can be initialized this way :

    public static final LineDelimiter DEFAULT = new LineDelimiter(
System.getProperty( "line.separator" ) );



Le 4/7/13 6:22 PM, jeffmaury@apache.org a écrit :
> Updated Branches:
>   refs/heads/trunk 2d51d12db -> 653d1a5ff
>
>
> Added text line coded and related unit tests
>
>
> Project: http://git-wip-us.apache.org/repos/asf/mina/repo
> Commit: http://git-wip-us.apache.org/repos/asf/mina/commit/653d1a5f
> Tree: http://git-wip-us.apache.org/repos/asf/mina/tree/653d1a5f
> Diff: http://git-wip-us.apache.org/repos/asf/mina/diff/653d1a5f
>
> Branch: refs/heads/trunk
> Commit: 653d1a5ff37904e4515bc375d24dcb301862dad4
> Parents: 2d51d12
> Author: Jeff MAURY <jeffmaury@apache.org>
> Authored: Sun Apr 7 18:21:47 2013 +0200
> Committer: Jeff MAURY <jeffmaury@apache.org>
> Committed: Sun Apr 7 18:21:47 2013 +0200
>
> ----------------------------------------------------------------------
>  .../apache/mina/codec/textline/LineDelimiter.java  |  149 ++++++
>  .../mina/codec/textline/TextLineDecoder.java       |  407 +++++++++++++++
>  .../mina/codec/textline/TextLineEncoder.java       |  147 ++++++
>  .../codec/textline/AutoTextLineDecoderTest.java    |  123 +++++
>  .../codec/textline/UnixTextLineDecoderTest.java    |  123 +++++
>  .../codec/textline/WindowsTextLineDecoderTest.java |  121 +++++
>  6 files changed, 1070 insertions(+), 0 deletions(-)
> ----------------------------------------------------------------------
>
>
> http://git-wip-us.apache.org/repos/asf/mina/blob/653d1a5f/codec/src/main/java/org/apache/mina/codec/textline/LineDelimiter.java
> ----------------------------------------------------------------------
> diff --git a/codec/src/main/java/org/apache/mina/codec/textline/LineDelimiter.java b/codec/src/main/java/org/apache/mina/codec/textline/LineDelimiter.java
> new file mode 100644
> index 0000000..c6f858a
> --- /dev/null
> +++ b/codec/src/main/java/org/apache/mina/codec/textline/LineDelimiter.java
> @@ -0,0 +1,149 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF licenses this file
> + *  to you under the Apache License, Version 2.0 (the
> + *  "License"); you may not use this file except in compliance
> + *  with the License.  You may obtain a copy of the License at
> + *
> + *    http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing,
> + *  software distributed under the License is distributed on an
> + *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + *  KIND, either express or implied.  See the License for the
> + *  specific language governing permissions and limitations
> + *  under the License.
> + *
> + */
> +package org.apache.mina.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>. This class defines default delimiters for various
> + * OS :
> + * <ul>
> + * <li><b>Unix/Linux</b> : LineDelimiter.UNIX ("\n")</li>
> + * <li><b>Windows</b> : LineDelimiter.WINDOWS ("\r\n")</li>
> + * <li><b>MAC</b> : LineDelimiter.MAC ("\r")</li>
> + * </ul>
> + *
> + * @author <a href="http://mina.apache.org">Apache MINA Project</a>
> + */
> +public class LineDelimiter {
> +    /** the line delimiter constant of the current O/S. */
> +    public static final LineDelimiter DEFAULT;
> +
> +    /** Compute the default delimiter on he current OS */
> +    static {
> +        ByteArrayOutputStream bout = new ByteArrayOutputStream();
> +        PrintWriter out = new PrintWriter(bout, true);
> +        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 CRLF line delimiter constant (<tt>"\r\n"</tt>)
> +     */
> +    public static final LineDelimiter CRLF = new LineDelimiter("\r\n");
> +
> +    /**
> +     * 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 = CRLF;
> +
> +    /**
> +     * The line delimiter constant of Mac OS (<tt>"\r"</tt>)
> +     */
> +    public static final LineDelimiter MAC = new LineDelimiter("\r");
> +
> +    /**
> +     * The line delimiter constant for NUL-terminated text protocols
> +     * such as Flash XML socket (<tt>"\0"</tt>)
> +     */
> +    public static final LineDelimiter NUL = new LineDelimiter("\0");
> +
> +    /** Stores the selected Line delimiter */
> +    private final String value;
> +
> +    /**
> +     * Creates a new line delimiter with the specified <tt>value</tt>.
> +     */
> +    public LineDelimiter(String value) {
> +        if (value == null) {
> +            throw new IllegalArgumentException("delimiter");
> +        }
> +
> +        this.value = value;
> +    }
> +
> +    /**
> +     * Return the delimiter string.
> +     */
> +    public String getValue() {
> +        return value;
> +    }
> +
> +    /**
> +     * {@inheritDoc}
> +     */
> +    @Override
> +    public int hashCode() {
> +        return value.hashCode();
> +    }
> +
> +    /**
> +     * {@inheritDoc}
> +     */
> +    @Override
> +    public boolean equals(Object o) {
> +        if (this == o) {
> +            return true;
> +        }
> +
> +        if (!(o instanceof LineDelimiter)) {
> +            return false;
> +        }
> +
> +        LineDelimiter that = (LineDelimiter) o;
> +
> +        return this.value.equals(that.value);
> +    }
> +
> +    /**
> +     * {@inheritDoc}
> +     */
> +    @Override
> +    public String toString() {
> +        if (value.length() == 0) {
> +            return "delimiter: auto";
> +        } else {
> +            StringBuilder buf = new StringBuilder();
> +            buf.append("delimiter:");
> +
> +            for (int i = 0; i < value.length(); i++) {
> +                buf.append(" 0x");
> +                buf.append(Integer.toHexString(value.charAt(i)));
> +            }
> +
> +            return buf.toString();
> +        }
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina/blob/653d1a5f/codec/src/main/java/org/apache/mina/codec/textline/TextLineDecoder.java
> ----------------------------------------------------------------------
> diff --git a/codec/src/main/java/org/apache/mina/codec/textline/TextLineDecoder.java
b/codec/src/main/java/org/apache/mina/codec/textline/TextLineDecoder.java
> new file mode 100644
> index 0000000..845ee24
> --- /dev/null
> +++ b/codec/src/main/java/org/apache/mina/codec/textline/TextLineDecoder.java
> @@ -0,0 +1,407 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF licenses this file
> + *  to you under the Apache License, Version 2.0 (the
> + *  "License"); you may not use this file except in compliance
> + *  with the License.  You may obtain a copy of the License at
> + *
> + *    http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing,
> + *  software distributed under the License is distributed on an
> + *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + *  KIND, either express or implied.  See the License for the
> + *  specific language governing permissions and limitations
> + *  under the License.
> + *
> + */
> +package org.apache.mina.codec.textline;
> +
> +import java.nio.ByteBuffer;
> +import java.nio.CharBuffer;
> +import java.nio.charset.CharacterCodingException;
> +import java.nio.charset.Charset;
> +import java.nio.charset.CharsetDecoder;
> +import java.util.ArrayList;
> +import java.util.List;
> +
> +import org.apache.mina.codec.ProtocolDecoder;
> +
> +/**
> + * A {@link ProtocolDecoder} which decodes a text line into a string.
> + *
> + * @author <a href="http://mina.apache.org">Apache MINA Project</a>
> + */
> +public class TextLineDecoder implements ProtocolDecoder<ByteBuffer, String, TextLineDecoder.Context>
{
> +    private final Charset charset;
> +
> +    /** The delimiter used to determinate when a line has been fully decoded */
> +    private final LineDelimiter delimiter;
> +
> +    /** An ByteBuffer containing the delimiter */
> +    private ByteBuffer delimBuf;
> +
> +    /** The default maximum Line length. Default to 1024. */
> +    private int maxLineLength = 1024;
> +
> +    /** The default maximum buffer length. Default to 128 chars. */
> +    private int bufferLength = 128;
> +
> +    /**
> +     * Creates a new instance with the current default {@link Charset}
> +     * and {@link LineDelimiter#AUTO} delimiter.
> +     */
> +    public TextLineDecoder() {
> +        this(LineDelimiter.AUTO);
> +    }
> +
> +    /**
> +     * Creates a new instance with the current default {@link Charset}
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineDecoder(String delimiter) {
> +        this(new LineDelimiter(delimiter));
> +    }
> +
> +    /**
> +     * Creates a new instance with the current default {@link Charset}
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineDecoder(LineDelimiter delimiter) {
> +        this(Charset.defaultCharset(), delimiter);
> +    }
> +
> +    /**
> +     * Creates a new instance with the spcified <tt>charset</tt>
> +     * and {@link LineDelimiter#AUTO} delimiter.
> +     */
> +    public TextLineDecoder(Charset charset) {
> +        this(charset, LineDelimiter.AUTO);
> +    }
> +
> +    /**
> +     * Creates a new instance with the spcified <tt>charset</tt>
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineDecoder(Charset charset, String delimiter) {
> +        this(charset, new LineDelimiter(delimiter));
> +    }
> +
> +    /**
> +     * 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 IllegalArgumentException("charset parameter shuld not be null");
> +        }
> +
> +        if (delimiter == null) {
> +            throw new IllegalArgumentException("delimiter parameter should not be null");
> +        }
> +
> +        this.charset = charset;
> +        this.delimiter = delimiter;
> +
> +        // Convert delimiter to ByteBuffer if not done yet.
> +        if (delimBuf == null) {
> +            ByteBuffer tmp = charset.encode(CharBuffer.wrap(delimiter.getValue()));
> +            tmp.rewind();
> +            delimBuf = tmp;
> +        }
> +    }
> +
> +    /**
> +     * 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 {@link 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 {@link BufferDataException}.  The default
> +     * value is <tt>1024</tt> (1KB).
> +     */
> +    public void setMaxLineLength(int maxLineLength) {
> +        if (maxLineLength <= 0) {
> +            throw new IllegalArgumentException("maxLineLength (" + maxLineLength + ")
should be a positive value");
> +        }
> +
> +        this.maxLineLength = maxLineLength;
> +    }
> +
> +    /**
> +     * Sets the default buffer size. This buffer is used in the Context
> +     * to store the decoded line.
> +     *
> +     * @param bufferLength The default bufer size
> +     */
> +    public void setBufferLength(int bufferLength) {
> +        if (bufferLength <= 0) {
> +            throw new IllegalArgumentException("bufferLength (" + maxLineLength + ")
should be a positive value");
> +
> +        }
> +
> +        this.bufferLength = bufferLength;
> +    }
> +
> +    /**
> +     * Returns the allowed buffer size used to store the decoded line
> +     * in the Context instance.
> +     */
> +    public int getBufferLength() {
> +        return bufferLength;
> +    }
> +
> +    @Override
> +    public Context createDecoderState() {
> +        return new Context(bufferLength);
> +    }
> +
> +    /**
> +     * {@inheritDoc}
> +     */
> +    public String[] decode(ByteBuffer in, Context ctx) {
> +        if (LineDelimiter.AUTO.equals(delimiter)) {
> +            return decodeAuto(ctx, in);
> +        } else {
> +            return decodeNormal(ctx, in);
> +        }
> +    }
> +
> +    /**
> +     * {@inheritDoc}
> +     */
> +    public void finishDecode(Context ctx) {
> +    }
> +
> +    /**
> +     * Decode a line using the default delimiter on the current system
> +     */
> +    private String[] decodeAuto(Context ctx, ByteBuffer in) {
> +        List<String> decoded = new ArrayList<String>();
> +        int matchCount = ctx.getMatchCount();
> +
> +        // 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);
> +
> +                ctx.append(in);
> +
> +                in.limit(oldLimit);
> +                in.position(pos);
> +
> +                try {
> +                    if (ctx.getOverflowLength() == 0) {
> +                        ByteBuffer buf = ctx.getBuffer();
> +                        buf.flip();
> +                        buf.limit(buf.limit() - matchCount);
> +
> +                        CharsetDecoder decoder = ctx.getDecoder();
> +                        CharBuffer buffer = decoder.decode(buf);
> +                        String str = new String(buffer.array());
> +                        decoded.add(str);
> +                    } else {
> +                        int overflowPosition = ctx.getOverflowLength();
> +                        throw new IllegalStateException("Line is too long: " + overflowPosition);
> +                    }
> +                } catch (CharacterCodingException cce) {
> +                    throw new RuntimeException(cce);
> +                } finally {
> +                    ctx.reset();
> +                }
> +                oldPos = pos;
> +                matchCount = 0;
> +            }
> +        }
> +
> +        // Put remainder to buf.
> +        in.position(oldPos);
> +        ctx.append(in);
> +
> +        ctx.setMatchCount(matchCount);
> +        return decoded.toArray(new String[decoded.size()]);
> +    }
> +
> +    /**
> +     * Decode a line using the delimiter defined by the caller
> +     * @return 
> +     */
> +    private String[] decodeNormal(Context ctx, ByteBuffer in) {
> +        List<String> decoded = new ArrayList<String>();
> +        int matchCount = ctx.getMatchCount();
> +
> +        // 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);
> +
> +                    ctx.append(in);
> +
> +                    in.limit(oldLimit);
> +                    in.position(pos);
> +
> +                    try {
> +                        if (ctx.getOverflowLength() == 0) {
> +                            ByteBuffer buf = ctx.getBuffer();
> +                            buf.flip();
> +                            buf.limit(buf.limit() - matchCount);
> +
> +                            CharsetDecoder decoder = ctx.getDecoder();
> +                            CharBuffer buffer = decoder.decode(buf);
> +                            String str = new String(buffer.array());
> +                            decoded.add(str);
> +                        } else {
> +                            int overflowLength = ctx.getOverflowLength();
> +                            throw new IllegalStateException("Line is too long: " + overflowLength);
> +                        }
> +                    } catch (CharacterCodingException cce) {
> +                        throw new RuntimeException(cce);
> +                    } finally {
> +                        ctx.reset();
> +                    }
> +                    
> +
> +                    oldPos = pos;
> +                    matchCount = 0;
> +                }
> +            } else {
> +                // fix for DIRMINA-506 & DIRMINA-536
> +                in.position(Math.max(0, in.position() - matchCount));
> +                matchCount = 0;
> +            }
> +        }
> +
> +        // Put remainder to buf.
> +        in.position(oldPos);
> +        ctx.append(in);
> +
> +        ctx.setMatchCount(matchCount);
> +        return decoded.toArray(new String[decoded.size()]);
> +    }
> +
> +    /**
> +     * A Context used during the decoding of a lin. It stores the decoder, 
> +     * the temporary buffer containing the decoded line, and other status flags.
> +     *
> +     * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
> +     * @version $Rev$, $Date$
> +     */
> +    public class Context {
> +        /** The decoder */
> +        private final CharsetDecoder decoder;
> +
> +        /** The temporary buffer containing the decoded line */
> +        private ByteBuffer buf;
> +
> +        /** The number of lines found so far */
> +        private int matchCount = 0;
> +        
> +        /**
> +         * Overflow length
> +         */
> +        private int overflowLength = 0;
> +
> +        /** Create a new Context object with a default buffer */
> +        private Context(int bufferLength) {
> +            decoder = charset.newDecoder();
> +            buf = ByteBuffer.allocate(bufferLength);
> +        }
> +
> +        public CharsetDecoder getDecoder() {
> +            return decoder;
> +        }
> +
> +        public ByteBuffer getBuffer() {
> +            return buf;
> +        }
> +
> +        public int getMatchCount() {
> +            return matchCount;
> +        }
> +
> +        public void setMatchCount(int matchCount) {
> +            this.matchCount = matchCount;
> +        }
> +        
> +        public int getOverflowLength() {
> +            return overflowLength;
> +        }
> +
> +        public void reset() {
> +            overflowLength = 0;
> +            matchCount = 0;
> +            decoder.reset();
> +            buf.clear();
> +        }
> +
> +        private void ensureSpace(int size) {
> +            if (buf.position() + size > buf.capacity()) {
> +                ByteBuffer b = ByteBuffer.allocate(buf.position() + size + bufferLength);
> +                buf.flip();
> +                b.put(buf);
> +                buf = b;
> +            }
> +        }
> +        public void append(ByteBuffer in) {
> +            if (buf.position() > maxLineLength - in.remaining()) {
> +                overflowLength = buf.position() + in.remaining();
> +                buf.clear();
> +                discard(in);
> +            } else {
> +                ensureSpace(in.remaining());
> +                getBuffer().put(in);
> +            }
> +        }
> +
> +        private void discard(ByteBuffer in) {
> +            in.position(in.limit());
> +        }
> +    }
> +
> +}
> \ No newline at end of file
>
> http://git-wip-us.apache.org/repos/asf/mina/blob/653d1a5f/codec/src/main/java/org/apache/mina/codec/textline/TextLineEncoder.java
> ----------------------------------------------------------------------
> diff --git a/codec/src/main/java/org/apache/mina/codec/textline/TextLineEncoder.java
b/codec/src/main/java/org/apache/mina/codec/textline/TextLineEncoder.java
> new file mode 100644
> index 0000000..6ce02c3
> --- /dev/null
> +++ b/codec/src/main/java/org/apache/mina/codec/textline/TextLineEncoder.java
> @@ -0,0 +1,147 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF licenses this file
> + *  to you under the Apache License, Version 2.0 (the
> + *  "License"); you may not use this file except in compliance
> + *  with the License.  You may obtain a copy of the License at
> + *
> + *    http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing,
> + *  software distributed under the License is distributed on an
> + *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + *  KIND, either express or implied.  See the License for the
> + *  specific language governing permissions and limitations
> + *  under the License.
> + *
> + */
> +package org.apache.mina.codec.textline;
> +
> +import java.nio.ByteBuffer;
> +import java.nio.CharBuffer;
> +import java.nio.charset.CharacterCodingException;
> +import java.nio.charset.Charset;
> +import java.nio.charset.CharsetEncoder;
> +
> +import org.apache.mina.codec.ProtocolEncoder;
> +import org.apache.mina.codec.StatelessProtocolEncoder;
> +
> +
> +/**
> + * A {@link ProtocolEncoder} which encodes a string into a text line
> + * which ends with the delimiter.
> + *
> + * @author <a href="http://mina.apache.org">Apache MINA Project</a>
> + */
> +public class TextLineEncoder implements StatelessProtocolEncoder<String, ByteBuffer>
{
> +    private final CharsetEncoder charsetEncoder;
> +
> +    private final LineDelimiter delimiter;
> +
> +    private int maxLineLength = Integer.MAX_VALUE;
> +
> +    /**
> +     * Creates a new instance with the current default {@link Charset}
> +     * and {@link LineDelimiter#UNIX} delimiter.
> +     */
> +    public TextLineEncoder() {
> +        this(Charset.defaultCharset(), LineDelimiter.UNIX);
> +    }
> +
> +    /**
> +     * Creates a new instance with the current default {@link Charset}
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineEncoder(String delimiter) {
> +        this(new LineDelimiter(delimiter));
> +    }
> +
> +    /**
> +     * Creates a new instance with the current default {@link Charset}
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineEncoder(LineDelimiter delimiter) {
> +        this(Charset.defaultCharset(), delimiter);
> +    }
> +
> +    /**
> +     * Creates a new instance with the spcified <tt>charset</tt>
> +     * and {@link LineDelimiter#UNIX} delimiter.
> +     */
> +    public TextLineEncoder(Charset charset) {
> +        this(charset, LineDelimiter.UNIX);
> +    }
> +
> +    /**
> +     * Creates a new instance with the spcified <tt>charset</tt>
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineEncoder(Charset charset, String delimiter) {
> +        this(charset, new LineDelimiter(delimiter));
> +    }
> +
> +    /**
> +     * Creates a new instance with the spcified <tt>charset</tt>
> +     * and the specified <tt>delimiter</tt>.
> +     */
> +    public TextLineEncoder(Charset charset, LineDelimiter delimiter) {
> +        if (charset == null) {
> +            throw new IllegalArgumentException("charset");
> +        }
> +        if (delimiter == null) {
> +            throw new IllegalArgumentException("delimiter");
> +        }
> +        if (LineDelimiter.AUTO.equals(delimiter)) {
> +            throw new IllegalArgumentException("AUTO delimiter is not allowed for encoder.");
> +        }
> +
> +        this.charsetEncoder = charset.newEncoder();
> +        this.delimiter = delimiter;
> +    }
> +
> +    /**
> +     * Returns the allowed maximum size of the encoded line.
> +     * If the size of the encoded line exceeds this value, the encoder
> +     * will throw a {@link IllegalArgumentException}.  The default value
> +     * is {@link Integer#MAX_VALUE}.
> +     */
> +    public int getMaxLineLength() {
> +        return maxLineLength;
> +    }
> +
> +    /**
> +     * Sets the allowed maximum size of the encoded line.
> +     * If the size of the encoded line exceeds this value, the encoder
> +     * will throw a {@link IllegalArgumentException}.  The default value
> +     * is {@link Integer#MAX_VALUE}.
> +     */
> +    public void setMaxLineLength(int maxLineLength) {
> +        if (maxLineLength <= 0) {
> +            throw new IllegalArgumentException("maxLineLength: " + maxLineLength);
> +        }
> +
> +        this.maxLineLength = maxLineLength;
> +    }
> +
> +    @Override
> +    public Void createEncoderState() {
> +        return null;
> +    }
> +
> +    @Override
> +    public ByteBuffer encode(String message, Void context) {
> +        try {
> +            String value = (message == null ? "" : message);
> +            
> +            if (value.length() > maxLineLength) {
> +                throw new IllegalArgumentException("Line length: " + message.length());
> +            }
> +            return charsetEncoder.encode(CharBuffer.wrap(value).append(CharBuffer.wrap(delimiter.getValue())));
> +        } catch (CharacterCodingException e) {
> +            throw new RuntimeException(e);
> +        }
> +    }
> +
> +}
> \ No newline at end of file
>
> http://git-wip-us.apache.org/repos/asf/mina/blob/653d1a5f/codec/src/test/java/org/apache/mina/codec/textline/AutoTextLineDecoderTest.java
> ----------------------------------------------------------------------
> diff --git a/codec/src/test/java/org/apache/mina/codec/textline/AutoTextLineDecoderTest.java
b/codec/src/test/java/org/apache/mina/codec/textline/AutoTextLineDecoderTest.java
> new file mode 100644
> index 0000000..ca087c4
> --- /dev/null
> +++ b/codec/src/test/java/org/apache/mina/codec/textline/AutoTextLineDecoderTest.java
> @@ -0,0 +1,123 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF licenses this file
> + *  to you under the Apache License, Version 2.0 (the
> + *  "License"); you may not use this file except in compliance
> + *  with the License.  You may obtain a copy of the License at
> + *
> + *    http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing,
> + *  software distributed under the License is distributed on an
> + *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + *  KIND, either express or implied.  See the License for the
> + *  specific language governing permissions and limitations
> + *  under the License.
> + *
> + */
> +package org.apache.mina.codec.textline;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertNotNull;
> +
> +import java.nio.ByteBuffer;
> +
> +import org.apache.mina.codec.textline.TextLineDecoder.Context;
> +import org.junit.Test;
> +
> +/**
> + * A {@link TextLineDecoder} test.
> + *
> + * @author <a href="http://mina.apache.org">Apache MINA Project</a>
> + */
> +public class AutoTextLineDecoderTest {
> +
> +    @Test
> +    public void testThatEmptyBufferReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.allocate(0), context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +    }
> +    
> +    @Test
> +    public void testThatNonLineTerminatedStringReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string".getBytes()), context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +        assertEquals(8, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatUnixLineTerminatedStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\n".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatWindowsLineTerminatedStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\r\n".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatContextIsMaintainedBetweenMessages() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\na".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(1, context.getBuffer().position());
> +        results = decoder.decode(ByteBuffer.wrap(" string\n".getBytes()), context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +
> +    @Test
> +    public void testThatUnixLineTerminatedLongStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        StringBuffer sb = new StringBuffer();
> +        for(int i=0; i < 100;++i) {
> +            sb.append("a string");
> +        }
> +        String[] results = decoder.decode(ByteBuffer.wrap((sb.toString() + "\n").getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals(sb.toString(), results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatWindowsLineTerminatedLongStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder();
> +        Context context = decoder.createDecoderState();
> +        StringBuffer sb = new StringBuffer();
> +        for(int i=0; i < 100;++i) {
> +            sb.append("a string");
> +        }
> +        String[] results = decoder.decode(ByteBuffer.wrap((sb.toString() + "\r\n").getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals(sb.toString(), results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina/blob/653d1a5f/codec/src/test/java/org/apache/mina/codec/textline/UnixTextLineDecoderTest.java
> ----------------------------------------------------------------------
> diff --git a/codec/src/test/java/org/apache/mina/codec/textline/UnixTextLineDecoderTest.java
b/codec/src/test/java/org/apache/mina/codec/textline/UnixTextLineDecoderTest.java
> new file mode 100644
> index 0000000..2023187
> --- /dev/null
> +++ b/codec/src/test/java/org/apache/mina/codec/textline/UnixTextLineDecoderTest.java
> @@ -0,0 +1,123 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF licenses this file
> + *  to you under the Apache License, Version 2.0 (the
> + *  "License"); you may not use this file except in compliance
> + *  with the License.  You may obtain a copy of the License at
> + *
> + *    http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing,
> + *  software distributed under the License is distributed on an
> + *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + *  KIND, either express or implied.  See the License for the
> + *  specific language governing permissions and limitations
> + *  under the License.
> + *
> + */
> +package org.apache.mina.codec.textline;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertNotNull;
> +
> +import java.nio.ByteBuffer;
> +
> +import org.apache.mina.codec.textline.TextLineDecoder.Context;
> +import org.junit.Test;
> +
> +/**
> + * A {@link TextLineDecoder} test.
> + *
> + * @author <a href="http://mina.apache.org">Apache MINA Project</a>
> + */
> +public class UnixTextLineDecoderTest {
> +
> +    @Test
> +    public void testThatEmptyBufferReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.allocate(0), context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +    }
> +    
> +    @Test
> +    public void testThatNonLineTerminatedStringReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string".getBytes()), context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +        assertEquals(8, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatUnixLineTerminatedStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\n".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatWindowsLineTerminatedStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\r\n".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string\r", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatContextIsMaintainedBetweenMessages() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\na".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(1, context.getBuffer().position());
> +        results = decoder.decode(ByteBuffer.wrap(" string\n".getBytes()), context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +
> +    @Test
> +    public void testThatUnixLineTerminatedLongStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        StringBuffer sb = new StringBuffer();
> +        for(int i=0; i < 100;++i) {
> +            sb.append("a string");
> +        }
> +        String[] results = decoder.decode(ByteBuffer.wrap((sb.toString() + "\n").getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals(sb.toString(), results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatWindowsLineTerminatedLongStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.UNIX);
> +        Context context = decoder.createDecoderState();
> +        StringBuffer sb = new StringBuffer();
> +        for(int i=0; i < 100;++i) {
> +            sb.append("a string");
> +        }
> +        String[] results = decoder.decode(ByteBuffer.wrap((sb.toString() + "\r\n").getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals(sb.toString() + "\r", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +}
>
> http://git-wip-us.apache.org/repos/asf/mina/blob/653d1a5f/codec/src/test/java/org/apache/mina/codec/textline/WindowsTextLineDecoderTest.java
> ----------------------------------------------------------------------
> diff --git a/codec/src/test/java/org/apache/mina/codec/textline/WindowsTextLineDecoderTest.java
b/codec/src/test/java/org/apache/mina/codec/textline/WindowsTextLineDecoderTest.java
> new file mode 100644
> index 0000000..727fd17
> --- /dev/null
> +++ b/codec/src/test/java/org/apache/mina/codec/textline/WindowsTextLineDecoderTest.java
> @@ -0,0 +1,121 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one
> + *  or more contributor license agreements.  See the NOTICE file
> + *  distributed with this work for additional information
> + *  regarding copyright ownership.  The ASF licenses this file
> + *  to you under the Apache License, Version 2.0 (the
> + *  "License"); you may not use this file except in compliance
> + *  with the License.  You may obtain a copy of the License at
> + *
> + *    http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing,
> + *  software distributed under the License is distributed on an
> + *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
> + *  KIND, either express or implied.  See the License for the
> + *  specific language governing permissions and limitations
> + *  under the License.
> + *
> + */
> +package org.apache.mina.codec.textline;
> +
> +import static org.junit.Assert.assertEquals;
> +import static org.junit.Assert.assertNotNull;
> +
> +import java.nio.ByteBuffer;
> +
> +import org.apache.mina.codec.textline.TextLineDecoder.Context;
> +import org.junit.Test;
> +
> +/**
> + * A {@link TextLineDecoder} test.
> + *
> + * @author <a href="http://mina.apache.org">Apache MINA Project</a>
> + */
> +public class WindowsTextLineDecoderTest {
> +
> +    @Test
> +    public void testThatEmptyBufferReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.allocate(0), context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +    }
> +    
> +    @Test
> +    public void testThatNonLineTerminatedStringReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string".getBytes()), context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +        assertEquals(8, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatUnixLineTerminatedStringReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\n".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +        assertEquals(9, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatWindowsLineTerminatedStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\r\n".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatContextIsMaintainedBetweenMessages() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        String[] results = decoder.decode(ByteBuffer.wrap("a string\r\na".getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(1, context.getBuffer().position());
> +        results = decoder.decode(ByteBuffer.wrap(" string\r\n".getBytes()), context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals("a string", results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +
> +    @Test
> +    public void testThatUnixLineTerminatedLongStringReturnsEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        StringBuffer sb = new StringBuffer();
> +        for(int i=0; i < 100;++i) {
> +            sb.append("a string");
> +        }
> +        String[] results = decoder.decode(ByteBuffer.wrap((sb.toString() + "\n").getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(0, results.length);
> +        assertEquals(801, context.getBuffer().position());
> +    }
> +    
> +    @Test
> +    public void testThatWindowsLineTerminatedLongStringReturnsNonEmptyResult() {
> +        TextLineDecoder decoder = new TextLineDecoder(LineDelimiter.WINDOWS);
> +        Context context = decoder.createDecoderState();
> +        StringBuffer sb = new StringBuffer();
> +        for(int i=0; i < 100;++i) {
> +            sb.append("a string");
> +        }
> +        String[] results = decoder.decode(ByteBuffer.wrap((sb.toString() + "\r\n").getBytes()),
context);
> +        assertNotNull(results);
> +        assertEquals(1, results.length);
> +        assertEquals(sb.toString(), results[0]);
> +        assertEquals(0, context.getBuffer().position());
> +    }
> +}
>


-- 
Regards,
Cordialement,
Emmanuel Lécharny
www.iktek.com 


Mime
View raw message