You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@mina.apache.org by ma...@apache.org on 2007/12/05 23:02:13 UTC

svn commit: r601549 - in /mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring: ./ PrefixedStringCodecFactory.java PrefixedStringDecoder.java PrefixedStringEncoder.java

Author: maarten
Date: Wed Dec  5 14:02:12 2007
New Revision: 601549

URL: http://svn.apache.org/viewvc?rev=601549&view=rev
Log:
added a codec for Java String objects using a fixed-length length prefix (and no delimiter)

Added:
    mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/
    mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringCodecFactory.java
    mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringDecoder.java
    mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringEncoder.java

Added: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringCodecFactory.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringCodecFactory.java?rev=601549&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringCodecFactory.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringCodecFactory.java Wed Dec  5 14:02:12 2007
@@ -0,0 +1,134 @@
+package org.apache.mina.filter.codec.prefixedstring;
+
+import org.apache.mina.common.IoSession;
+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 java.nio.charset.Charset;
+
+/**
+ * A {@link ProtocolCodecFactory} that performs encoding and decoding
+ * of a Java String object using a fixed-length length prefix.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev: 596187 $, $Date: 2007-11-19 04:41:14 +0100 (ma, 19 nov 2007) $
+ */
+public class PrefixedStringCodecFactory implements ProtocolCodecFactory {
+
+    private final PrefixedStringEncoder encoder;
+
+    private final PrefixedStringDecoder decoder;
+
+    public PrefixedStringCodecFactory(Charset charset) {
+        encoder = new PrefixedStringEncoder(charset);
+        decoder = new PrefixedStringDecoder(charset);
+    }
+
+    public PrefixedStringCodecFactory() {
+        this(Charset.defaultCharset());
+    }
+
+    /**
+     * Returns the allowed maximum size of an encoded string.
+     * If the size of the encoded String exceeds this value, the encoder
+     * will throw a {@link IllegalArgumentException}.
+     * The default value is {@link PrefixedStringEncoder#DEFAULT_MAX_DATA_LENGTH}.
+     * <p/>
+     * This method does the same job as {@link PrefixedStringEncoder#setMaxDataLength(int)}.
+     *
+     * @return the allowed maximum size of an encoded string.
+     */
+    public int getEncoderMaxDataLength() {
+        return encoder.getMaxDataLength();
+    }
+
+    /**
+     * Sets the allowed maximum size of an encoded String.
+     * If the size of the encoded String exceeds this value, the encoder
+     * will throw a {@link IllegalArgumentException}.
+     * The default value is {@link PrefixedStringEncoder#DEFAULT_MAX_DATA_LENGTH}.
+     * <p/>
+     * This method does the same job as {@link PrefixedStringEncoder#getMaxDataLength()}.
+     *
+     * @param maxDataLength allowed maximum size of an encoded String.
+     */
+    public void setEncoderMaxDataLength(int maxDataLength) {
+        encoder.setMaxDataLength(maxDataLength);
+    }
+
+    /**
+     * Returns the allowed maximum size of a decoded string.
+     * <p>
+     * This method does the same job as {@link PrefixedStringEncoder#setMaxDataLength(int)}.
+     * </p>
+     *
+     * @return the allowed maximum size of an encoded string.
+     * @see #setDecoderMaxDataLength(int)
+     */
+    public int getDecoderMaxDataLength() {
+        return decoder.getMaxDataLength();
+    }
+
+    /**
+     * Sets the maximum allowed value specified as data length in the decoded data
+     * <p>
+     * Useful for preventing an OutOfMemory attack by the peer.
+     * The decoder will throw a {@link BufferDataException} when data length
+     * specified in the incoming data is greater than maxDataLength
+     * The default value is {@link PrefixedStringDecoder#DEFAULT_MAX_DATA_LENGTH}.
+     *
+     * This method does the same job as {@link PrefixedStringDecoder#setMaxDataLength(int)}.
+     * </p>
+     *
+     * @param maxDataLength maximum allowed value specified as data length in the incoming data
+     */
+    public void setDecoderMaxDataLength(int maxDataLength) {
+        decoder.setMaxDataLength(maxDataLength);
+    }
+
+    /**
+     * Sets the length of the prefix used by the decoder
+     *
+     * @param prefixLength the length of the length prefix (1, 2, or 4)
+     */
+    public void setDecoderPrefixLength(int prefixLength) {
+        decoder.setPrefixLength(prefixLength);
+    }
+
+    /**
+     * Gets the length of the length prefix (1, 2, or 4) used by the decoder
+     *
+     * @return length of the length prefix
+     */
+    public int getDecoderPrefixLength() {
+        return decoder.getPrefixLength();
+    }
+
+    /**
+     * Sets the length of the prefix used by the encoder
+     *
+     * @param prefixLength the length of the length prefix (1, 2, or 4)
+     */
+    public void setEncoderPrefixLength(int prefixLength) {
+        encoder.setPrefixLength(prefixLength);
+    }
+
+    /**
+     * Gets the length of the length prefix (1, 2, or 4) used by the encoder
+     *
+     * @return length of the length prefix
+     */
+    public int getEncoderPrefixLength() {
+        return encoder.getPrefixLength();
+    }
+
+    public ProtocolEncoder getEncoder(IoSession session) throws Exception {
+        return encoder;
+    }
+
+    public ProtocolDecoder getDecoder(IoSession session) throws Exception {
+        return decoder;
+    }
+}

Added: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringDecoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringDecoder.java?rev=601549&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringDecoder.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringDecoder.java Wed Dec  5 14:02:12 2007
@@ -0,0 +1,100 @@
+package org.apache.mina.filter.codec.prefixedstring;
+
+import org.apache.mina.common.IoBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.common.BufferDataException;
+import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoder;
+import org.apache.mina.filter.codec.ProtocolDecoderOutput;
+
+import java.nio.charset.Charset;
+
+/**
+ * A {@link ProtocolDecoder} which decodes a String using a fixed-length length prefix.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev: 591182 $, $Date: 2007-11-02 01:59:27 +0100 (vr, 02 nov 2007) $,
+ */
+public class PrefixedStringDecoder extends CumulativeProtocolDecoder {
+
+    public final static int DEFAULT_PREFIX_LENGTH = 4;
+
+    public final static int DEFAULT_MAX_DATA_LENGTH = 2048;
+
+    private final Charset charset;
+
+    private int prefixLength = DEFAULT_PREFIX_LENGTH;
+
+    private int maxDataLength = DEFAULT_MAX_DATA_LENGTH;
+
+    /**
+     * @param charset       the charset to use for encoding
+     * @param prefixLength  the length of the prefix
+     * @param maxDataLength maximum number of bytes allowed for a single String
+     */
+    public PrefixedStringDecoder(Charset charset, int prefixLength, int maxDataLength) {
+        this.charset = charset;
+        this.prefixLength = prefixLength;
+        this.maxDataLength = maxDataLength;
+    }
+
+    public PrefixedStringDecoder(Charset charset, int prefixLength) {
+        this(charset, prefixLength, DEFAULT_MAX_DATA_LENGTH);
+    }
+
+    public PrefixedStringDecoder(Charset charset) {
+        this(charset, DEFAULT_PREFIX_LENGTH);
+    }
+
+    /**
+     * Sets the number of bytes used by the length prefix
+     *
+     * @param prefixLength the length of the length prefix (1, 2, or 4)
+     */
+    public void setPrefixLength(int prefixLength) {
+        this.prefixLength = prefixLength;
+    }
+
+    /**
+     * Gets the length of the length prefix (1, 2, or 4)
+     *
+     * @return length of the length prefix
+     */
+    public int getPrefixLength() {
+        return prefixLength;
+    }
+
+    /**
+     * Sets the maximum allowed value specified as data length in the incoming data
+     * <p>
+     * Useful for preventing an OutOfMemory attack by the peer.
+     * The decoder will throw a {@link BufferDataException} when data length
+     * specified in the incoming data is greater than maxDataLength
+     * The default value is {@link PrefixedStringDecoder#DEFAULT_MAX_DATA_LENGTH}.
+     * </p>
+     *
+     * @param maxDataLength maximum allowed value specified as data length in the incoming data
+     */
+    public void setMaxDataLength(int maxDataLength) {
+        this.maxDataLength = maxDataLength;
+    }
+
+    /**
+     * Gets the maximum number of bytes allowed for a single String
+     *
+     * @return maximum number of bytes allowed for a single String
+     */
+    public int getMaxDataLength() {
+        return maxDataLength;
+    }
+
+    protected boolean doDecode(IoSession session, IoBuffer in, ProtocolDecoderOutput out) throws Exception {
+        if (in.prefixedDataAvailable(prefixLength, maxDataLength)) {
+            String msg = in.getPrefixedString(prefixLength, charset.newDecoder());
+            out.write(msg);
+            return true;
+        } else {
+            return false;
+        }
+    }
+}

Added: mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringEncoder.java
URL: http://svn.apache.org/viewvc/mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringEncoder.java?rev=601549&view=auto
==============================================================================
--- mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringEncoder.java (added)
+++ mina/trunk/core/src/main/java/org/apache/mina/filter/codec/prefixedstring/PrefixedStringEncoder.java Wed Dec  5 14:02:12 2007
@@ -0,0 +1,104 @@
+package org.apache.mina.filter.codec.prefixedstring;
+
+import org.apache.mina.common.IoBuffer;
+import org.apache.mina.common.IoSession;
+import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
+import org.apache.mina.filter.codec.ProtocolEncoderOutput;
+import org.apache.mina.filter.codec.ProtocolEncoder;
+
+import java.nio.charset.Charset;
+
+/**
+ * A {@link ProtocolEncoder} which encodes a string
+ * using a fixed-length length prefix.
+ *
+ * @author The Apache MINA Project (dev@mina.apache.org)
+ * @version $Rev: 591182 $, $Date: 2007-11-02 01:59:27 +0100 (vr, 02 nov 2007) $,
+ */
+public class PrefixedStringEncoder extends ProtocolEncoderAdapter {
+
+    public final static int DEFAULT_PREFIX_LENGTH = 4;
+
+    public final static int DEFAULT_MAX_DATA_LENGTH = 2048;
+
+    private final Charset charset;
+
+    private int prefixLength = DEFAULT_PREFIX_LENGTH;
+
+    private int maxDataLength = DEFAULT_MAX_DATA_LENGTH;
+
+    public PrefixedStringEncoder(Charset charset, int prefixLength, int maxDataLength) {
+        this.charset = charset;
+        this.prefixLength = prefixLength;
+        this.maxDataLength = maxDataLength;
+    }
+
+    public PrefixedStringEncoder(Charset charset, int prefixLength) {
+        this(charset, prefixLength, DEFAULT_MAX_DATA_LENGTH);
+    }
+
+    public PrefixedStringEncoder(Charset charset) {
+        this(charset, DEFAULT_PREFIX_LENGTH);
+    }
+
+    public PrefixedStringEncoder() {
+        this(Charset.defaultCharset());
+    }
+
+    /**
+     * Sets the number of bytes used by the length prefix
+     *
+     * @param prefixLength the length of the length prefix (1, 2, or 4)
+     */
+    public void setPrefixLength(int prefixLength) {
+        if (prefixLength != 1 && prefixLength != 2 && prefixLength != 4) {
+            throw new IllegalArgumentException("prefixLength: " + prefixLength);
+        }
+        this.prefixLength = prefixLength;
+    }
+
+    /**
+     * Gets the length of the length prefix (1, 2, or 4)
+     *
+     * @return length of the length prefix
+     */
+    public int getPrefixLength() {
+        return prefixLength;
+    }
+
+    /**
+     * Sets the maximum number of bytes allowed for encoding a single String
+     * (including the prefix)
+     * <p>
+     * The encoder will throw a {@link IllegalArgumentException} when more bytes
+     * are needed to encode a String value.
+     * The default value is {@link PrefixedStringEncoder#DEFAULT_MAX_DATA_LENGTH}.
+     * </p>
+     *
+     * @param maxDataLength maximum number of bytes allowed for encoding a single String
+     */
+    public void setMaxDataLength(int maxDataLength) {
+        this.maxDataLength = maxDataLength;
+    }
+
+    /**
+     * Gets the maximum number of bytes allowed for encoding a single String     *
+     *
+     * @return maximum number of bytes allowed for encoding a single String (prefix included)
+     */
+    public int getMaxDataLength() {
+        return maxDataLength;
+    }
+
+
+    public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
+        String value = (String) message;
+        IoBuffer buffer = IoBuffer.allocate(value.length()).setAutoExpand(true);
+        buffer.putPrefixedString(value, prefixLength, charset.newEncoder());
+        if (buffer.position() > maxDataLength) {
+            throw new IllegalArgumentException("Data length: " + buffer.position());
+        }
+        buffer.flip();
+        out.write(buffer);
+    }
+}