Updated Branches:
  refs/heads/trunk b9f507c1b -> 1c856929e

int serializations redesign and fixes


Project: http://git-wip-us.apache.org/repos/asf/mina/repo
Commit: http://git-wip-us.apache.org/repos/asf/mina/commit/ed496202
Tree: http://git-wip-us.apache.org/repos/asf/mina/tree/ed496202
Diff: http://git-wip-us.apache.org/repos/asf/mina/diff/ed496202

Branch: refs/heads/trunk
Commit: ed49620224d1224956e1c23b84b29ddc52c9efd2
Parents: b9f507c
Author: Raphaël P. Barazzutti <[email protected]>
Authored: Wed Jul 3 21:11:53 2013 +0200
Committer: Raphaël P. Barazzutti <[email protected]>
Committed: Thu Jul 4 00:39:46 2013 +0200

----------------------------------------------------------------------
 .../java/org/apache/mina/codec/IoBuffer.java    |  58 +++++++++-
 .../mina/codec/delimited/ByteBufferDecoder.java | 104 ------------------
 .../mina/codec/delimited/IoBufferDecoder.java   | 105 +++++++++++++++++++
 .../codec/delimited/SizePrefixedDecoder.java    |  15 ++-
 .../codec/delimited/ints/IntTranscoder.java     |  10 ++
 .../mina/codec/delimited/ints/RawInt32.java     | 105 ++++++++-----------
 .../mina/codec/delimited/ints/VarInt.java       | 104 ++++++++++++------
 .../serialization/JavaNativeMessageDecoder.java |  11 +-
 .../codec/delimited/ints/IntEncodingTest.java   |  35 ++++---
 .../ints/RawInt32BigEndianEncodingTest.java     |  10 +-
 .../ints/RawInt32LittleEndianEncodingTest.java  |  10 +-
 .../delimited/ints/VarIntEncodingTest.java      |   8 +-
 .../serialization/GenericSerializerTest.java    |  17 +--
 .../delimited/serialization/JavaNativeTest.java |   4 +-
 14 files changed, 341 insertions(+), 255 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/IoBuffer.java
----------------------------------------------------------------------
diff --git a/codec/src/main/java/org/apache/mina/codec/IoBuffer.java 
b/codec/src/main/java/org/apache/mina/codec/IoBuffer.java
index 605ca24..1be49a5 100644
--- a/codec/src/main/java/org/apache/mina/codec/IoBuffer.java
+++ b/codec/src/main/java/org/apache/mina/codec/IoBuffer.java
@@ -20,6 +20,7 @@ package org.apache.mina.codec;
 
 import java.io.IOException;
 import java.io.InputStream;
+import java.nio.BufferOverflowException;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
@@ -327,7 +328,7 @@ public final class IoBuffer {
      * @see ByteBuffer#get()
      */
     public byte get() {
-        if (position.getPosition() >= limit.getPosition()) {
+        if (!hasRemaining()) {
             throw new BufferUnderflowException();
         }
 
@@ -551,6 +552,13 @@ public final class IoBuffer {
     }
 
     /**
+     * @see ByteBuffer#isReadOnly()
+     */
+    public boolean isReadOnly() {
+        return readonly;
+    }
+
+    /**
      * @see ByteBuffer#limit()
      */
     public int limit() {
@@ -645,6 +653,48 @@ public final class IoBuffer {
     }
 
     /**
+     * @see ByteBuffer#put(ByteBuffer)
+     */
+    public IoBuffer put(ByteBuffer src) {
+
+        if (remaining() < src.remaining()) {
+            throw new BufferOverflowException();
+        }
+        if (isReadOnly()) {
+            throw new ReadOnlyBufferException();
+        }
+
+        while (src.hasRemaining()) {
+            put(src.get());
+        }
+
+        return this;
+    }
+    
+    
+    /**
+     * @see ByteBuffer#put(ByteBuffer)
+     */
+    public IoBuffer put(IoBuffer src) {
+        if(src==this){ // NOSONAR, checking the instance
+            throw new IllegalArgumentException();
+        }
+
+        if (remaining() < src.remaining()) {
+            throw new BufferOverflowException();
+        }
+        if (isReadOnly()) {
+            throw new ReadOnlyBufferException();
+        }
+
+        while (src.hasRemaining()) {
+            put(src.get());
+        }
+
+        return this;
+    }
+
+    /**
      * @see ByteBuffer#put(byte[], int, int)
      */
     public IoBuffer put(byte[] src, int offset, int length) {
@@ -996,10 +1046,10 @@ public final class IoBuffer {
         public String toString() {
             StringBuffer sb = new StringBuffer();
             sb.append(getClass().getName());
-            sb.append("[node=");
-            sb.append(getNode());
-            sb.append(", pos=");
+            sb.append("[pos=");
             sb.append(getPosition());
+            sb.append(", node=");
+            sb.append(getNode());
             sb.append("]");
             return sb.toString();
         }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/ByteBufferDecoder.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/ByteBufferDecoder.java 
b/codec/src/main/java/org/apache/mina/codec/delimited/ByteBufferDecoder.java
deleted file mode 100644
index 73b6bbf..0000000
--- a/codec/src/main/java/org/apache/mina/codec/delimited/ByteBufferDecoder.java
+++ /dev/null
@@ -1,104 +0,0 @@
-/*
- *  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.delimited;
-
-import java.nio.ByteBuffer;
-
-import org.apache.mina.codec.ProtocolDecoder;
-import org.apache.mina.codec.ProtocolDecoderException;
-import org.apache.mina.codec.StatelessProtocolDecoder;
-import org.apache.mina.codec.delimited.ints.RawInt32;
-import org.apache.mina.codec.delimited.ints.VarInt;
-
-/**
- * Abstract class providing both encoding and decoding methods between a given
- * type and ByteBuffers.
- * 
- * <p>
- * Transcoder is stateless class providing encoding and decoding facilities.
- * Additionally this abstract requires two methods which allows to determine 
the
- * size of a given message and to write it directly to a previously allocated
- * ByteBuffer.
- * </p>
- * 
- * @param <INPUT>
- *            the type of the messages which will be encoded in ByteBuffers and
- *            decoded from ByteBuffers.
- * 
- * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
- */
-public abstract class ByteBufferDecoder<INPUT> implements 
StatelessProtocolDecoder<ByteBuffer, INPUT> {
-    /**
-     * Being stateless, this method is left empty
-     * 
-     * @see ProtocolDecoder#createDecoderState()
-     */
-    @Override
-    public final Void createDecoderState() {
-        // stateless !
-        return null;
-    }
-
-    /**
-     * Decodes a message from a {@link ByteBuffer}
-     * 
-     * <p>
-     * When a truncated input is given to this method it <b>may</b> return 
null.
-     * Not all decoder will be able to detect this issue and report it that 
way.
-     * Thanks to prefixing of messages, decoder will only receive appropriately
-     * sized ByteBuffers.
-     * </p>
-     * 
-     * <p>
-     * n.b. The decoders used for the prefixing (i.e. {@link RawInt32} and
-     * {@link VarInt}) <b>have</b> to detect truncated ByteBuffers.
-     * </p>
-     * 
-     * @param input
-     *            data to be decoded as a TYPE message
-     * @return the decoded message on success, null otherwise
-     * 
-     * @throws ProtocolDecoderException
-     */
-    public abstract INPUT decode(ByteBuffer input);
-
-    /**
-     * Decodes a message from a {@link ByteBuffer}
-     * <p>
-     * The actual decoding needs to be implemented in the abstract method
-     * {@link ByteBufferDecoder#decode(ByteBuffer)}
-     * </p>
-     */
-    @Override
-    public final INPUT decode(ByteBuffer input, Void context) {
-        return decode(input);
-    }
-
-    /**
-     * Being stateless, this method is left empty
-     * 
-     * @see ProtocolDecoder#finishDecode(Object)
-     */
-    @Override
-    public final void finishDecode(Void context) {
-        // stateless !
-    }
-
-}

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/IoBufferDecoder.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/IoBufferDecoder.java 
b/codec/src/main/java/org/apache/mina/codec/delimited/IoBufferDecoder.java
new file mode 100644
index 0000000..416244a
--- /dev/null
+++ b/codec/src/main/java/org/apache/mina/codec/delimited/IoBufferDecoder.java
@@ -0,0 +1,105 @@
+/*
+ *  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.delimited;
+
+import java.nio.ByteBuffer;
+
+import org.apache.mina.codec.IoBuffer;
+import org.apache.mina.codec.ProtocolDecoder;
+import org.apache.mina.codec.ProtocolDecoderException;
+import org.apache.mina.codec.StatelessProtocolDecoder;
+import org.apache.mina.codec.delimited.ints.RawInt32;
+import org.apache.mina.codec.delimited.ints.VarInt;
+
+/**
+ * Abstract class providing both encoding and decoding methods between a given
+ * type and ByteBuffers.
+ * 
+ * <p>
+ * Transcoder is stateless class providing encoding and decoding facilities.
+ * Additionally this abstract requires two methods which allows to determine 
the
+ * size of a given message and to write it directly to a previously allocated
+ * ByteBuffer.
+ * </p>
+ * 
+ * @param <INPUT>
+ *            the type of the messages which will be encoded in ByteBuffers and
+ *            decoded from ByteBuffers.
+ * 
+ * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
+ */
+public abstract class IoBufferDecoder<INPUT> implements 
StatelessProtocolDecoder<IoBuffer, INPUT> {
+    /**
+     * Being stateless, this method is left empty
+     * 
+     * @see ProtocolDecoder#createDecoderState()
+     */
+    @Override
+    public final Void createDecoderState() {
+        // stateless !
+        return null;
+    }
+
+    /**
+     * Decodes a message from a {@link IoBuffer}
+     * 
+     * <p>
+     * When a truncated input is given to this method it <b>may</b> return 
null.
+     * Not all decoder will be able to detect this issue and report it that 
way.
+     * Thanks to prefixing of messages, decoder will only receive appropriately
+     * sized ByteBuffers.
+     * </p>
+     * 
+     * <p>
+     * n.b. The decoders used for the prefixing (i.e. {@link RawInt32} and
+     * {@link VarInt}) <b>have</b> to detect truncated ByteBuffers.
+     * </p>
+     * 
+     * @param input
+     *            data to be decoded as a TYPE message
+     * @return the decoded message on success, null otherwise
+     * 
+     * @throws ProtocolDecoderException
+     */
+    public abstract INPUT decode(IoBuffer input);
+
+    /**
+     * Decodes a message from a {@link ByteBuffer}
+     * <p>
+     * The actual decoding needs to be implemented in the abstract method
+     * {@link IoBufferDecoder#decode(ByteBuffer)}
+     * </p>
+     */
+    @Override
+    public final INPUT decode(IoBuffer input, Void context) {
+        return decode(input);
+    }
+
+    /**
+     * Being stateless, this method is left empty
+     * 
+     * @see ProtocolDecoder#finishDecode(Object)
+     */
+    @Override
+    public final void finishDecode(Void context) {
+        // stateless !
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/SizePrefixedDecoder.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/SizePrefixedDecoder.java 
b/codec/src/main/java/org/apache/mina/codec/delimited/SizePrefixedDecoder.java
index 73eccf2..ffd701a 100644
--- 
a/codec/src/main/java/org/apache/mina/codec/delimited/SizePrefixedDecoder.java
+++ 
b/codec/src/main/java/org/apache/mina/codec/delimited/SizePrefixedDecoder.java
@@ -19,15 +19,14 @@
  */
 package org.apache.mina.codec.delimited;
 
-import java.nio.ByteBuffer;
-
+import org.apache.mina.codec.IoBuffer;
 import org.apache.mina.codec.ProtocolDecoder;
 
 /**
  * 
  * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
  */
-public class SizePrefixedDecoder<OUT> implements ProtocolDecoder<ByteBuffer, 
OUT, SizePrefixedDecoder.MutableInt> {
+public class SizePrefixedDecoder<OUT> implements ProtocolDecoder<IoBuffer, 
OUT, SizePrefixedDecoder.MutableInt> {
 
     /**
      * A mutable {@link Integer} wrapper.
@@ -83,11 +82,11 @@ public class SizePrefixedDecoder<OUT> implements 
ProtocolDecoder<ByteBuffer, OUT
         }
     }
 
-    private final ByteBufferDecoder<Integer> sizeDecoder;
+    private final IoBufferDecoder<Integer> sizeDecoder;
 
-    private final ByteBufferDecoder<OUT> payloadDecoder;
+    private final IoBufferDecoder<OUT> payloadDecoder;
 
-    public SizePrefixedDecoder(ByteBufferDecoder<Integer> sizeDecoder, 
ByteBufferDecoder<OUT> payloadDecoder) {
+    public SizePrefixedDecoder(IoBufferDecoder<Integer> sizeDecoder, 
IoBufferDecoder<OUT> payloadDecoder) {
         super();
         this.sizeDecoder = sizeDecoder;
         this.payloadDecoder = payloadDecoder;
@@ -100,7 +99,7 @@ public class SizePrefixedDecoder<OUT> implements 
ProtocolDecoder<ByteBuffer, OUT
     }
 
     @Override
-    public OUT decode(ByteBuffer input, MutableInt nextBlockSize) {
+    public OUT decode(IoBuffer input, MutableInt nextBlockSize) {
         OUT output = null;
 
         if (nextBlockSize.getValue() == null) {
@@ -108,7 +107,7 @@ public class SizePrefixedDecoder<OUT> implements 
ProtocolDecoder<ByteBuffer, OUT
         }
 
         if (nextBlockSize.isDefined() && (input.remaining() >= 
nextBlockSize.getValue())) {
-            ByteBuffer buffer = input.slice();
+            IoBuffer buffer = input.slice();
             buffer.limit(buffer.position() + nextBlockSize.getValue());
 
             output = payloadDecoder.decode(buffer);

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/ints/IntTranscoder.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/ints/IntTranscoder.java 
b/codec/src/main/java/org/apache/mina/codec/delimited/ints/IntTranscoder.java
new file mode 100644
index 0000000..35a145c
--- /dev/null
+++ 
b/codec/src/main/java/org/apache/mina/codec/delimited/ints/IntTranscoder.java
@@ -0,0 +1,10 @@
+package org.apache.mina.codec.delimited.ints;
+
+import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
+
+public interface IntTranscoder {
+    IoBufferDecoder<Integer> getDecoder();
+
+    ByteBufferEncoder<Integer> getEncoder();
+}

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/ints/RawInt32.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/ints/RawInt32.java 
b/codec/src/main/java/org/apache/mina/codec/delimited/ints/RawInt32.java
index 6767a33..f650a58 100644
--- a/codec/src/main/java/org/apache/mina/codec/delimited/ints/RawInt32.java
+++ b/codec/src/main/java/org/apache/mina/codec/delimited/ints/RawInt32.java
@@ -19,11 +19,13 @@
  */
 package org.apache.mina.codec.delimited.ints;
 
+import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 
-import org.apache.mina.codec.ProtocolDecoderException;
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
+import org.apache.mina.codec.IoBuffer;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 
 /**
  * 
@@ -105,45 +107,55 @@ import org.apache.mina.codec.delimited.ByteBufferEncoder;
  * 
  * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
  */
-public class RawInt32 {
-    // this class should not be instanciated
-    private RawInt32() {
+/*
+ * About the suppression of warnings:
+ * This class contains a lot of bit-shifting, logical and/or operations order 
to handle
+ * VarInt conversions. The code contains a lot of hard-coded integer that 
tools like
+ * Sonar classify as "magic numbers". Using final static variables for all of 
them
+ * would have resulted in a code less readable.
+ * The "all" scope is too generic, but Sonar doesn't not handle properly 
others scopes 
+ * like "MagicNumber" (Sonar 3.6 - 03July2013)
+ */
+@SuppressWarnings("all")
+public final class RawInt32 implements IntTranscoder {
+    private final ByteOrder bo;
+
+    public RawInt32(ByteOrder bo) {
+        super();
+        this.bo = bo == null ? ByteOrder.BIG_ENDIAN : bo;
+    }
+
+    @Override
+    public IoBufferDecoder<Integer> getDecoder() {
+        return new Decoder();
+    }
+
+    @Override
+    public ByteBufferEncoder<Integer> getEncoder() {
+        return new Encoder();
     }
 
+    private static final int BYTE_MASK = 0xff;
+
     /**
      * Documentation available in the {@link RawInt32} enclosing class.
      * 
      * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
      * 
      */
-    public static class Decoder extends ByteBufferDecoder<Integer> {
-
-        private Endianness endianness;
-
-        public Decoder(Endianness endianness) {
-            super();
-            this.endianness = endianness;
-        }
+    private class Decoder extends IoBufferDecoder<Integer> {
 
         @Override
-        public Integer decode(ByteBuffer input) {
+        public Integer decode(IoBuffer input) {
             if (input.remaining() < 4) {
                 return null;
             }
 
-            if (endianness == Endianness.BIG) {
-                if ((input.get(0) & 0x80) != 0) {
-                    throw new ProtocolDecoderException("Not the big endian 
representation of a signed int32");
-                }
-                return ((input.get() & 0xff) << 24) | ((input.get() & 0xff) << 
16) | ((input.get() & 0xff) << 8)
-                        | ((input.get() & 0xff));
-            } else {
-                if ((input.get(3) & 0x80) != 0) {
-                    throw new ProtocolDecoderException("Not the small endian 
representation of a signed int32");
-                }
-                return ((input.get() & 0xff)) | ((input.get() & 0xff) << 8) | 
((input.get() & 0xff) << 16)
-                        | ((input.get() & 0xff) << 24);
+            int out = 0;
+            for (int i = 0; i < 32; i += 8) {
+                out |= (input.get() & 0xff) << (bo == ByteOrder.BIG_ENDIAN ? 
24 - i : i);
             }
+            return out;
         }
     }
 
@@ -153,33 +165,17 @@ public class RawInt32 {
      * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
      * 
      */
-    public static class Encoder extends ByteBufferEncoder<Integer> {
-
-        private final Endianness endianness;
-
-        public Encoder(Endianness endianness) {
-            super();
-            this.endianness = endianness;
-        }
+    private class Encoder extends ByteBufferEncoder<Integer> {
 
         @Override
         public void writeTo(Integer message, ByteBuffer buffer) {
-            // VarInts don't support negative values
-            if (message < 0) {
-                message = 0;
+
+            if (buffer.remaining() < 4) {
+                throw new BufferUnderflowException();
             }
-            if (endianness == Endianness.BIG) {
-                buffer.put((byte) (0xff & (message >> 24)));
-                buffer.put((byte) (0xff & (message >> 16)));
-                buffer.put((byte) (0xff & (message >> 8)));
-                buffer.put((byte) (0xff & (message)));
-            } else {
-                buffer.put((byte) (0xff & (message)));
-                buffer.put((byte) (0xff & (message >> 8)));
-                buffer.put((byte) (0xff & (message >> 16)));
-                buffer.put((byte) (0xff & (message >> 24)));
+            for (int i = 0; i < 32; i += 8) {
+                buffer.put((byte) (message >> (bo == ByteOrder.BIG_ENDIAN ? 24 
- i : i)));
             }
-
         }
 
         @Override
@@ -188,17 +184,4 @@ public class RawInt32 {
         }
 
     }
-
-    /**
-     * 
-     * This enumeration is used to select the endianness of the dncoder and the
-     * decoder class.
-     * 
-     * Documentation available in the {@link RawInt32} enclosing class.
-     * 
-     * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
-     */
-    public enum Endianness {
-        BIG, LITTLE
-    }
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/ints/VarInt.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/ints/VarInt.java 
b/codec/src/main/java/org/apache/mina/codec/delimited/ints/VarInt.java
index 625afeb..8102e6f 100644
--- a/codec/src/main/java/org/apache/mina/codec/delimited/ints/VarInt.java
+++ b/codec/src/main/java/org/apache/mina/codec/delimited/ints/VarInt.java
@@ -22,9 +22,10 @@ package org.apache.mina.codec.delimited.ints;
 import java.nio.BufferUnderflowException;
 import java.nio.ByteBuffer;
 
+import org.apache.mina.codec.IoBuffer;
 import org.apache.mina.codec.ProtocolDecoderException;
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 
 /**
  * Class providing a variable length representation of integers.
@@ -80,9 +81,26 @@ import org.apache.mina.codec.delimited.ByteBufferEncoder;
  * 
  * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
  */
-public class VarInt {
-    // this class should not be instanciated
-    private VarInt() {
+/*
+ * About the suppression of warnings:
+ * This class contains a lot of bit-shifting, logical and/or operations order 
to handle
+ * VarInt conversions. The code contains a lot of hard-coded integer that 
tools like
+ * Sonar classify as "magic numbers". Using final static variables for all of 
them
+ * would have resulted in a code less readable.
+ * The "all" scope is too generic, but Sonar doesn't not handle properly 
others scopes 
+ * like "MagicNumber" (Sonar 3.6 - 03July2013)
+ */
+@SuppressWarnings("all")
+public final class VarInt implements IntTranscoder {
+    
+    @Override
+    public IoBufferDecoder<Integer> getDecoder() {
+        return new Decoder();
+    }
+
+    @Override
+    public ByteBufferEncoder<Integer> getEncoder() {
+        return new Encoder();
     }
 
     /**
@@ -91,29 +109,45 @@ public class VarInt {
      * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
      * 
      */
-    public static class Decoder extends ByteBufferDecoder<Integer> {
+    private class Decoder extends IoBufferDecoder<Integer> {
 
         @Override
-        public Integer decode(ByteBuffer input) {
+        public Integer decode(IoBuffer input) {
             int origpos = input.position();
-            int size = 0;
 
             try {
-                for (int i = 0;; i += 7) {
-                    byte tmp = input.get();
-
-                    if ((tmp & 0x80) == 0 && (i != 4 * 7 || tmp < 1 << 3)) {
-                        return size | (tmp << i);
-                    } else if (i < 4 * 7) {
-                        size |= (tmp & 0x7f) << i;
+                byte tmp = input.get();
+                if (tmp >= 0) {
+                    return (int) tmp;
+                }
+                int result = tmp & 0x7f;
+                if ((tmp = input.get()) >= 0) {
+                    result |= tmp << 7;
+                } else {
+                    result |= (tmp & 0x7f) << 7;                    
+                    if ((tmp = input.get()) >= 0) {
+                        result |= tmp << 14;
                     } else {
-                        throw new ProtocolDecoderException("Not the varint 
representation of a signed int32");
+                        result |= (tmp & 0x7f) << 14;               
+                        if ((tmp = input.get()) >= 0) {
+                            result |= tmp << 21;
+                        } else {
+                            result |= (tmp & 0x7f) << 21;
+                            
+                            // check that there are at most 3 significant bits 
available
+                            if (((tmp = input.get()) & ~0x7) == 0) {
+                                result |= tmp << 28;
+                            } else {
+                                throw new ProtocolDecoderException("Not the 
varint representation of a signed int32");
+                            }
+                        }
                     }
                 }
+                return result;
+
             } catch (BufferUnderflowException bue) {
                 input.position(origpos);
             }
-
             return null;
         }
     }
@@ -124,33 +158,41 @@ public class VarInt {
      * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
      * 
      */
-    public static class Encoder extends ByteBufferEncoder<Integer> {
+    private class Encoder extends ByteBufferEncoder<Integer> {
 
         @Override
         public void writeTo(Integer message, ByteBuffer buffer) {
-            int value = message;
-
             // VarInts don't support negative values
-            if (value < 0) {
-                value = 0;
-            }
+            int value = Math.max(0,message);            
 
-            while (value > 0x7f) {
-                buffer.put((byte) ((value & 0x7f) | 0x80));
-                value >>= 7;
+            while (true) {
+                if ((value & ~0x7F) == 0) {
+                    buffer.put((byte) value);
+                    return;
+                } else {
+                    buffer.put((byte) ((value & 0x7F) | 0x80));
+                    value >>>= 7;
+                }
             }
 
-            buffer.put((byte) value);
         }
 
         @Override
-        public int getEncodedSize(Integer message) {
-            if (message < 1) {
+        public int getEncodedSize(Integer value) {
+            if ((value & (0xffffffff << 7)) == 0) {
                 return 1;
-            } else {
-                int log2 = 32 - Integer.numberOfLeadingZeros(message);
-                return (log2 + 6) / 7;
             }
+            if ((value & (0xffffffff << 14)) == 0) {
+                return 2;
+            }
+            if ((value & (0xffffffff << 21)) == 0) {
+                return 3;
+            }
+            if ((value & (0xffffffff << 28)) == 0) {
+                return 4;
+            }
+            return 5;
         }
+
     }
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/main/java/org/apache/mina/codec/delimited/serialization/JavaNativeMessageDecoder.java
----------------------------------------------------------------------
diff --git 
a/codec/src/main/java/org/apache/mina/codec/delimited/serialization/JavaNativeMessageDecoder.java
 
b/codec/src/main/java/org/apache/mina/codec/delimited/serialization/JavaNativeMessageDecoder.java
index d7cc44d..f05882d 100644
--- 
a/codec/src/main/java/org/apache/mina/codec/delimited/serialization/JavaNativeMessageDecoder.java
+++ 
b/codec/src/main/java/org/apache/mina/codec/delimited/serialization/JavaNativeMessageDecoder.java
@@ -21,24 +21,23 @@ package org.apache.mina.codec.delimited.serialization;
 
 import java.io.ObjectInputStream;
 import java.io.Serializable;
-import java.nio.ByteBuffer;
 
+import org.apache.mina.codec.IoBuffer;
 import org.apache.mina.codec.ProtocolDecoderException;
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
-import org.apache.mina.util.ByteBufferInputStream;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 
 /**
  * Decoder providing the built-in Java-deserialization.
  * 
  * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
  */
-public class JavaNativeMessageDecoder<IN extends Serializable> extends 
ByteBufferDecoder<IN> {
+public class JavaNativeMessageDecoder<IN extends Serializable> extends 
IoBufferDecoder<IN> {
 
     @SuppressWarnings("unchecked")
     @Override
-    public IN decode(final ByteBuffer input) {
+    public IN decode(final IoBuffer input) {
         try {
-            ObjectInputStream ois = new ObjectInputStream(new 
ByteBufferInputStream(input));
+            ObjectInputStream ois = new 
ObjectInputStream(input.asInputStream());
             IN s = (IN) ois.readObject();
             ois.close();
             return s;

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/test/java/org/apache/mina/codec/delimited/ints/IntEncodingTest.java
----------------------------------------------------------------------
diff --git 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/IntEncodingTest.java 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/IntEncodingTest.java
index f1c385c..019b44d 100644
--- 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/IntEncodingTest.java
+++ 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/IntEncodingTest.java
@@ -26,14 +26,15 @@ import static org.junit.Assert.fail;
 import java.nio.ByteBuffer;
 import java.util.Map;
 
+import org.apache.mina.codec.IoBuffer;
 import org.apache.mina.codec.ProtocolDecoderException;
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 import org.junit.Before;
 import org.junit.Test;
 
 /**
- * A generic test class for {@link ByteBufferEncoder} and {@link 
ByteBufferDecoder}
+ * A generic test class for {@link ByteBufferEncoder} and {@link 
IoBufferDecoder}
  * 
  * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
  */
@@ -41,9 +42,9 @@ public abstract class IntEncodingTest {
 
     protected ByteBufferEncoder<Integer> encoder;
 
-    protected ByteBufferDecoder<Integer> decoder;
+    protected IoBufferDecoder<Integer> decoder;
 
-    public abstract ByteBufferDecoder<Integer> newDecoderInstance();
+    public abstract IoBufferDecoder<Integer> newDecoderInstance();
 
     public abstract ByteBufferEncoder<Integer> newEncoderInstance();
 
@@ -61,10 +62,10 @@ public abstract class IntEncodingTest {
     public void testTruncatedValues() {
         for (int value : new int[] { 0, 1, 127, 128, 65536, 198649, 
Integer.MAX_VALUE }) {
 
-            ByteBuffer buffer = encoder.encode(value);
+            IoBuffer buffer = IoBuffer.wrap(encoder.encode(value));
 
             for (int i = 0; i < buffer.remaining(); i++) {
-                ByteBuffer partialBuffer = buffer.slice();
+                IoBuffer partialBuffer = buffer.slice();
                 partialBuffer.limit(partialBuffer.position() + i);
                 try {
                     assertNull(decoder.decode(partialBuffer));
@@ -81,7 +82,7 @@ public abstract class IntEncodingTest {
             ByteBuffer buffer = encoder.encode(value);
 
             try {
-                assertEquals(value, decoder.decode(buffer).intValue());
+                assertEquals(value, 
decoder.decode(IoBuffer.wrap(buffer)).intValue());
             } catch (ProtocolDecoderException e) {
                 fail("Should not throw exception");
             }
@@ -96,7 +97,7 @@ public abstract class IntEncodingTest {
 
             for (int i = 1; i < 5; i++) {
                 int size = buffer.remaining() + i;
-                ByteBuffer extendedBuffer = ByteBuffer.allocate(size);
+                IoBuffer extendedBuffer = 
IoBuffer.wrap(ByteBuffer.allocate(size));
                 int start = extendedBuffer.position();
                 extendedBuffer.put(buffer.slice());
                 extendedBuffer.position(start);
@@ -118,7 +119,7 @@ public abstract class IntEncodingTest {
         for (Integer val : samples.keySet()) {
             assertEquals(samples.get(val), encoder.encode(val));
             try {
-                assertEquals(val, decoder.decode(samples.get(val)));
+                assertEquals(val, 
decoder.decode(IoBuffer.wrap(samples.get(val))));
             } catch (ProtocolDecoderException e) {
                 fail("Should not throw exception");
             }
@@ -130,7 +131,7 @@ public abstract class IntEncodingTest {
 
         for (ByteBuffer buffer : getIllegalBuffers()) {
             try {
-                decoder.decode(buffer);
+                decoder.decode(IoBuffer.wrap(buffer));
                 fail("Should throw an overflow exception");
             } catch (ProtocolDecoderException e) {
                 // fine
@@ -138,11 +139,11 @@ public abstract class IntEncodingTest {
         }
     }
 
-    @Test
-    public void testNegativeValues() {
-        ByteBuffer zero = encoder.encode(0);
-        for (int i : new int[] { -1, -127, Integer.MIN_VALUE }) {
-            assertEquals(zero, encoder.encode(i));
-        }
-    }
+//    @Test
+//    public void testNegativeValues() {
+//        ByteBuffer zero = encoder.encode(0);
+//        for (int i : new int[] { -1, -127, Integer.MIN_VALUE }) {
+//            assertEquals(zero, encoder.encode(i));
+//        }
+//    }
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32BigEndianEncodingTest.java
----------------------------------------------------------------------
diff --git 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32BigEndianEncodingTest.java
 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32BigEndianEncodingTest.java
index 1f64ee1..858d17b 100644
--- 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32BigEndianEncodingTest.java
+++ 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32BigEndianEncodingTest.java
@@ -20,13 +20,14 @@
 package org.apache.mina.codec.delimited.ints;
 
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 
 /**
  * A {@link Int32Decoder} and {@link Int32Encoder} test in a big endian setup.
@@ -36,13 +37,13 @@ import org.apache.mina.codec.delimited.ByteBufferEncoder;
 public class RawInt32BigEndianEncodingTest extends IntEncodingTest {
 
     @Override
-    public ByteBufferDecoder<Integer> newDecoderInstance() {
-        return new RawInt32.Decoder(RawInt32.Endianness.BIG);
+    public IoBufferDecoder<Integer> newDecoderInstance() {
+        return new RawInt32(ByteOrder.BIG_ENDIAN).getDecoder();
     }
 
     @Override
     public ByteBufferEncoder<Integer> newEncoderInstance() {
-        return new RawInt32.Encoder(RawInt32.Endianness.BIG);
+        return new RawInt32(ByteOrder.BIG_ENDIAN).getEncoder();
     }
 
     @Override
@@ -57,7 +58,6 @@ public class RawInt32BigEndianEncodingTest extends 
IntEncodingTest {
     @Override
     public Iterable<ByteBuffer> getIllegalBuffers() {
         List<ByteBuffer> list = new LinkedList<ByteBuffer>();
-        list.add(ByteBuffer.wrap(new byte[] { (byte) 0x80, 0, 0, 0 }));
         return list;
     }
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32LittleEndianEncodingTest.java
----------------------------------------------------------------------
diff --git 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32LittleEndianEncodingTest.java
 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32LittleEndianEncodingTest.java
index fa2d07c..c486402 100644
--- 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32LittleEndianEncodingTest.java
+++ 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/RawInt32LittleEndianEncodingTest.java
@@ -20,13 +20,14 @@
 package org.apache.mina.codec.delimited.ints;
 
 import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
 import java.util.HashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 
 /**
  * A {@link RawInt32.Encoder} and {@link RawInt32.Decoder} test in a little 
endian setup.
@@ -36,13 +37,13 @@ import org.apache.mina.codec.delimited.ByteBufferEncoder;
 public class RawInt32LittleEndianEncodingTest extends IntEncodingTest {
 
     @Override
-    public ByteBufferDecoder<Integer> newDecoderInstance() {
-        return new RawInt32.Decoder(RawInt32.Endianness.LITTLE);
+    public IoBufferDecoder<Integer> newDecoderInstance() {
+        return new RawInt32(ByteOrder.LITTLE_ENDIAN).getDecoder();
     }
 
     @Override
     public ByteBufferEncoder<Integer> newEncoderInstance() {
-        return new RawInt32.Encoder(RawInt32.Endianness.LITTLE);
+        return new RawInt32(ByteOrder.LITTLE_ENDIAN).getEncoder();
     }
 
     @Override
@@ -57,7 +58,6 @@ public class RawInt32LittleEndianEncodingTest extends 
IntEncodingTest {
     @Override
     public Iterable<ByteBuffer> getIllegalBuffers() {
         List<ByteBuffer> list = new LinkedList<ByteBuffer>();
-        list.add(ByteBuffer.wrap(new byte[] { 0, 0, 0, (byte) 0x80 }));
         return list;
     }
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/test/java/org/apache/mina/codec/delimited/ints/VarIntEncodingTest.java
----------------------------------------------------------------------
diff --git 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/VarIntEncodingTest.java
 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/VarIntEncodingTest.java
index 694773a..e0cf6d8 100644
--- 
a/codec/src/test/java/org/apache/mina/codec/delimited/ints/VarIntEncodingTest.java
+++ 
b/codec/src/test/java/org/apache/mina/codec/delimited/ints/VarIntEncodingTest.java
@@ -25,7 +25,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
 
 /**
@@ -36,13 +36,13 @@ import org.apache.mina.codec.delimited.ByteBufferEncoder;
 public class VarIntEncodingTest extends IntEncodingTest {
 
     @Override
-    public ByteBufferDecoder<Integer> newDecoderInstance() {
-        return new VarInt.Decoder();
+    public IoBufferDecoder<Integer> newDecoderInstance() {
+        return new VarInt().getDecoder();
     }
 
     @Override
     public ByteBufferEncoder<Integer> newEncoderInstance() {
-        return new VarInt.Encoder();
+        return new VarInt().getEncoder();
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/test/java/org/apache/mina/codec/delimited/serialization/GenericSerializerTest.java
----------------------------------------------------------------------
diff --git 
a/codec/src/test/java/org/apache/mina/codec/delimited/serialization/GenericSerializerTest.java
 
b/codec/src/test/java/org/apache/mina/codec/delimited/serialization/GenericSerializerTest.java
index b2c4086..487c9bd 100644
--- 
a/codec/src/test/java/org/apache/mina/codec/delimited/serialization/GenericSerializerTest.java
+++ 
b/codec/src/test/java/org/apache/mina/codec/delimited/serialization/GenericSerializerTest.java
@@ -24,18 +24,19 @@ import static org.junit.Assert.assertEquals;
 import java.nio.ByteBuffer;
 import java.util.List;
 
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
+import org.apache.mina.codec.IoBuffer;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 import org.junit.Test;
 
 /**
- * A {@link ByteBufferEncoder} and {@link ByteBufferDecoder} test. 
+ * A {@link ByteBufferEncoder} and {@link IoBufferDecoder} test. 
  * 
  * @author <a href="http://mina.apache.org";>Apache MINA Project</a>
  */
 public abstract class GenericSerializerTest<T> {
 
-    public abstract ByteBufferDecoder<T> getDecoder() throws Exception;
+    public abstract IoBufferDecoder<T> getDecoder() throws Exception;
 
     public abstract ByteBufferEncoder<T> getEncoder() throws Exception;
 
@@ -43,24 +44,24 @@ public abstract class GenericSerializerTest<T> {
 
     @Test
     public void testSerialization() throws Exception {
-        ByteBufferDecoder<T> decoder = getDecoder();
+        IoBufferDecoder<T> decoder = getDecoder();
         ByteBufferEncoder<T> encoder = getEncoder();
         for (T object : getObjects()) {
-            assertEquals(object, decoder.decode(encoder.encode(object)));
+            assertEquals(object, 
decoder.decode(IoBuffer.wrap(encoder.encode(object))));
         }
     }
 
     @Test
     public void testEncodedSize() throws Exception {
-        ByteBufferDecoder<T> decoder = getDecoder();
+        IoBufferDecoder<T> decoder = getDecoder();
         ByteBufferEncoder<T> encoder = getEncoder();
         for (T object : getObjects()) {
             int size = encoder.getEncodedSize(object);
             ByteBuffer out = ByteBuffer.allocate(size);
-            encoder.writeTo(object, out);
+            encoder.writeTo(object, out);            
             assertEquals(size, out.position());
             out.position(0);
-            assertEquals(object, decoder.decode(out));
+            assertEquals(object, decoder.decode(IoBuffer.wrap(out)));
         }
     }
 }

http://git-wip-us.apache.org/repos/asf/mina/blob/ed496202/codec/src/test/java/org/apache/mina/codec/delimited/serialization/JavaNativeTest.java
----------------------------------------------------------------------
diff --git 
a/codec/src/test/java/org/apache/mina/codec/delimited/serialization/JavaNativeTest.java
 
b/codec/src/test/java/org/apache/mina/codec/delimited/serialization/JavaNativeTest.java
index 0e7257c..b2d8bed 100644
--- 
a/codec/src/test/java/org/apache/mina/codec/delimited/serialization/JavaNativeTest.java
+++ 
b/codec/src/test/java/org/apache/mina/codec/delimited/serialization/JavaNativeTest.java
@@ -23,7 +23,7 @@ import java.io.Serializable;
 import java.util.LinkedList;
 import java.util.List;
 
-import org.apache.mina.codec.delimited.ByteBufferDecoder;
+import org.apache.mina.codec.delimited.IoBufferDecoder;
 import org.apache.mina.codec.delimited.ByteBufferEncoder;
 
 /**
@@ -98,7 +98,7 @@ public class JavaNativeTest extends 
GenericSerializerTest<JavaNativeTest.TestBea
     }
 
     @Override
-    public ByteBufferDecoder<TestBean> getDecoder() throws Exception {
+    public IoBufferDecoder<TestBean> getDecoder() throws Exception {
         return new JavaNativeMessageDecoder<TestBean>();
     }
 

Reply via email to