CAMEL-6302: Mina udp codec should use byte[] instead of String. Thanks to Thomas Termin for the patches.

git-svn-id: https://svn.apache.org/repos/asf/camel/branches/camel-2.11.x@1476114 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaComponent.java b/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaComponent.java
index c197e66..68375d5 100644
--- a/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaComponent.java
+++ b/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaComponent.java
@@ -330,12 +330,10 @@
     protected void configureDataGramCodecFactory(final String type, final IoServiceConfig config, final MinaConfiguration configuration) {
         ProtocolCodecFactory codecFactory = configuration.getCodec();
         if (codecFactory == null) {
-            final Charset charset = getEncodingParameter(type, configuration);
-            
-            codecFactory = new MinaUdpProtocolCodecFactory(getCamelContext(), charset);
+            codecFactory = new MinaUdpProtocolCodecFactory(getCamelContext());
 
             if (LOG.isDebugEnabled()) {
-                LOG.debug("{}: Using CodecFactory: {} using encoding: {}", new Object[]{type, codecFactory, charset});
+                LOG.debug("{}: Using CodecFactory: {}", new Object[]{type, codecFactory});
             }
         }
 
diff --git a/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaUdpProtocolCodecFactory.java b/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaUdpProtocolCodecFactory.java
index f15275d..9465930 100644
--- a/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaUdpProtocolCodecFactory.java
+++ b/components/camel-mina/src/main/java/org/apache/camel/component/mina/MinaUdpProtocolCodecFactory.java
@@ -17,8 +17,6 @@
 package org.apache.camel.component.mina;
 
 import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.NoTypeConversionAvailableException;
@@ -31,27 +29,21 @@
 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
 
 /**
- * @version 
+ * @version
  */
 public class MinaUdpProtocolCodecFactory implements ProtocolCodecFactory {
 
-    private final Charset charset;
     private final CamelContext context;
 
-    public MinaUdpProtocolCodecFactory(CamelContext context, Charset charset) {
+    public MinaUdpProtocolCodecFactory(CamelContext context) {
         this.context = context;
-        this.charset = charset;
     }
 
     public ProtocolEncoder getEncoder() throws Exception {
         return new ProtocolEncoder() {
-            private CharsetEncoder encoder;
 
             public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
-                if (encoder == null) {
-                    encoder = charset.newEncoder();
-                }
-                ByteBuffer buf = toByteBuffer(message, encoder);
+                ByteBuffer buf = toByteBuffer(message);
                 buf.flip();
                 out.write(buf);
             }
@@ -64,10 +56,11 @@
 
     public ProtocolDecoder getDecoder() throws Exception {
         return new ProtocolDecoder() {
-            public void decode(IoSession session, ByteBuffer in, ProtocolDecoderOutput out) throws Exception {
-                // convert to bytes to write, we can not pass in the byte buffer as it could be sent to
-                // multiple mina sessions so we must convert it to bytes
-                byte[] bytes = context.getTypeConverter().convertTo(byte[].class, in);
+            public void decode(IoSession session, ByteBuffer in,
+                               ProtocolDecoderOutput out) throws Exception {
+                // convert to bytes to write, we can not pass in the byte buffer
+                // as it could be sent to multiple mina sessions so we must convert it to bytes
+                byte[] bytes = context.getTypeConverter().mandatoryConvertTo(byte[].class, in);
                 out.write(bytes);
             }
 
@@ -81,17 +74,15 @@
         };
     }
 
-    private ByteBuffer toByteBuffer(Object message, CharsetEncoder encoder)
-        throws CharacterCodingException, NoTypeConversionAvailableException {
-        String value = context.getTypeConverter().convertTo(String.class, message);
+    private ByteBuffer toByteBuffer(Object message) throws CharacterCodingException, NoTypeConversionAvailableException {
+        // try to convert it to a byte array
+        byte[] value = context.getTypeConverter().tryConvertTo(byte[].class, message);
         if (value != null) {
-            ByteBuffer answer = ByteBuffer.allocate(value.length()).setAutoExpand(false);
-            answer.putString(value, encoder);
+            ByteBuffer answer = ByteBuffer.allocate(value.length).setAutoExpand(false);
+            answer.put(value);
             return answer;
         }
-
-        // failback to use a byte buffer converter
+        // fallback to use a byte buffer converter
         return context.getTypeConverter().mandatoryConvertTo(ByteBuffer.class, message);
     }
-
 }
diff --git a/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaUdpUsingTemplateTest.java b/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaUdpUsingTemplateTest.java
index cb6643b..83d40d0c 100644
--- a/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaUdpUsingTemplateTest.java
+++ b/components/camel-mina/src/test/java/org/apache/camel/component/mina/MinaUdpUsingTemplateTest.java
@@ -24,7 +24,7 @@
 import org.junit.Test;
 
 /**
- * @version 
+ * @version
  */
 public class MinaUdpUsingTemplateTest extends BaseMinaTest {
 
@@ -37,8 +37,6 @@
         endpoint.expectedBodiesReceived("Hello Message: 0", "Hello Message: 1", "Hello Message: 2");
 
         sendUdpMessages();
-        // sleeping for while to let the mock endpoint get all the message
-        Thread.sleep(2000);
 
         assertMockEndpointsSatisfied();
     }
@@ -57,9 +55,6 @@
         byte[] in = "Hello from bytes".getBytes();
         template.sendBody("mina:udp://127.0.0.1:{{port}}?sync=false", in);
 
-        // sleeping for while to let the mock endpoint get all the message
-        Thread.sleep(2000);
-
         assertMockEndpointsSatisfied();
         List<Exchange> list = endpoint.getReceivedExchanges();
         byte[] out = list.get(0).getIn().getBody(byte[].class);
@@ -69,10 +64,49 @@
         }
     }
 
+    @Test
+    public void testSendingRawByteMessage() throws Exception {
+        MockEndpoint endpoint = getMockEndpoint("mock:result");
+        endpoint.expectedMessageCount(1);
+
+        String toSend = "ef3e00559f5faf0262f5ff0962d9008daa91001cd46b0fa9330ef0f3030fff250e46f72444d1cc501678c351e04b8004c"
+                + "4000002080000fe850bbe011030000008031b031bfe9251305441593830354720020800050440ff";
+        byte[] in = fromHexString(toSend);
+        template.sendBody("mina:udp://127.0.0.1:{{port}}?sync=false", in);
+
+        assertMockEndpointsSatisfied();
+        List<Exchange> list = endpoint.getReceivedExchanges();
+        byte[] out = list.get(0).getIn().getBody(byte[].class);
+
+        for (int i = 0; i < in.length; i++) {
+            assertEquals("The bytes should be the same", in[i], out[i]);
+        }
+        assertEquals("The strings should be the same", toSend, byteArrayToHex(out));
+    }
+
+    private String byteArrayToHex(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
+    private byte[] fromHexString(String hexstr) {
+        byte data[] = new byte[hexstr.length() / 2];
+        int i = 0;
+        for (int n = hexstr.length(); i < n; i += 2) {
+            data[i / 2] = (Integer.decode("0x" + hexstr.charAt(i)
+                    + hexstr.charAt(i + 1))).byteValue();
+        }
+        return data;
+    }
+
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
             public void configure() {
-                from("mina:udp://127.0.0.1:{{port}}?sync=false&minaLogger=true").to("mock:result");
+                from("mina:udp://127.0.0.1:{{port}}?sync=false&minaLogger=true")
+                        .to("mock:result");
             }
         };
     }
diff --git a/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Consumer.java b/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Consumer.java
index d175eb6..31267b2 100644
--- a/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Consumer.java
+++ b/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Consumer.java
@@ -224,12 +224,10 @@
     protected void configureDataGramCodecFactory(final String type, final IoService service, final Mina2Configuration configuration) {
         ProtocolCodecFactory codecFactory = configuration.getCodec();
         if (codecFactory == null) {
-            final Charset charset = getEncodingParameter(type, configuration);
-
-            codecFactory = new Mina2UdpProtocolCodecFactory(this.getEndpoint().getCamelContext(), charset);
+            codecFactory = new Mina2UdpProtocolCodecFactory(this.getEndpoint().getCamelContext());
 
             if (LOG.isDebugEnabled()) {
-                LOG.debug("{}: Using CodecFactory: {} using encoding: {}", new Object[]{type, codecFactory, charset});
+                LOG.debug("{}: Using CodecFactory: {}", new Object[]{type, codecFactory});
             }
         }
 
diff --git a/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Producer.java b/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Producer.java
index c13f824..139e3a8 100644
--- a/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Producer.java
+++ b/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2Producer.java
@@ -388,12 +388,10 @@
     protected void configureDataGramCodecFactory(final String type, final IoService service, final Mina2Configuration configuration) {
         ProtocolCodecFactory codecFactory = configuration.getCodec();
         if (codecFactory == null) {
-            final Charset charset = getEncodingParameter(type, configuration);
-
-            codecFactory = new Mina2UdpProtocolCodecFactory(this.getEndpoint().getCamelContext(), charset);
+            codecFactory = new Mina2UdpProtocolCodecFactory(this.getEndpoint().getCamelContext());
 
             if (LOG.isDebugEnabled()) {
-                LOG.debug("{}: Using CodecFactory: {} using encoding: {}", new Object[]{type, codecFactory, charset});
+                LOG.debug("{}: Using CodecFactory: {}", new Object[]{type, codecFactory});
             }
         }
 
diff --git a/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2UdpProtocolCodecFactory.java b/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2UdpProtocolCodecFactory.java
index 2a5fde4..1b2a27d 100644
--- a/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2UdpProtocolCodecFactory.java
+++ b/components/camel-mina2/src/main/java/org/apache/camel/component/mina2/Mina2UdpProtocolCodecFactory.java
@@ -17,8 +17,6 @@
 package org.apache.camel.component.mina2;
 
 import java.nio.charset.CharacterCodingException;
-import java.nio.charset.Charset;
-import java.nio.charset.CharsetEncoder;
 
 import org.apache.camel.CamelContext;
 import org.apache.camel.NoTypeConversionAvailableException;
@@ -31,28 +29,21 @@
 import org.apache.mina.filter.codec.ProtocolEncoderOutput;
 
 /**
- * @version 
+ * @version
  */
 public class Mina2UdpProtocolCodecFactory implements ProtocolCodecFactory {
 
-    private final Charset charset;
     private final CamelContext context;
 
-    public Mina2UdpProtocolCodecFactory(CamelContext context, Charset charset) {
+    public Mina2UdpProtocolCodecFactory(CamelContext context) {
         this.context = context;
-        this.charset = charset;
     }
 
     public ProtocolEncoder getEncoder(IoSession session) throws Exception {
         return new ProtocolEncoder() {
 
-            private CharsetEncoder encoder;
-
             public void encode(IoSession session, Object message, ProtocolEncoderOutput out) throws Exception {
-                if (encoder == null) {
-                    encoder = charset.newEncoder();
-                }
-                IoBuffer buf = toIoBuffer(message, encoder);
+                IoBuffer buf = toIoBuffer(message);
                 buf.flip();
                 out.write(buf);
             }
@@ -83,16 +74,16 @@
         };
     }
 
-    private IoBuffer toIoBuffer(Object message, CharsetEncoder encoder)
-        throws CharacterCodingException, NoTypeConversionAvailableException {
-        String value = context.getTypeConverter().convertTo(String.class, message);
+    private IoBuffer toIoBuffer(Object message) throws CharacterCodingException, NoTypeConversionAvailableException {
+        //try to convert it to a byte array
+        byte[] value = context.getTypeConverter().tryConvertTo(byte[].class, message);
         if (value != null) {
-            IoBuffer answer = IoBuffer.allocate(value.length()).setAutoExpand(true);
-            answer.putString(value, encoder);
+            IoBuffer answer = IoBuffer.allocate(value.length).setAutoExpand(true);
+            answer.put(value);
             return answer;
         }
 
-        // failback to use a byte buffer converter
+        // fallback to use a byte buffer converter
         return context.getTypeConverter().mandatoryConvertTo(IoBuffer.class, message);
     }
 }
diff --git a/components/camel-mina2/src/test/java/org/apache/camel/component/mina2/Mina2UdpUsingTemplateTest.java b/components/camel-mina2/src/test/java/org/apache/camel/component/mina2/Mina2UdpUsingTemplateTest.java
index 1d66b4b..e67b2c9 100644
--- a/components/camel-mina2/src/test/java/org/apache/camel/component/mina2/Mina2UdpUsingTemplateTest.java
+++ b/components/camel-mina2/src/test/java/org/apache/camel/component/mina2/Mina2UdpUsingTemplateTest.java
@@ -24,7 +24,7 @@
 import org.junit.Test;
 
 /**
- * @version 
+ * @version
  */
 public class Mina2UdpUsingTemplateTest extends BaseMina2Test {
 
@@ -37,8 +37,6 @@
         endpoint.expectedBodiesReceived("Hello Message: 0", "Hello Message: 1", "Hello Message: 2");
 
         sendUdpMessages();
-        // sleeping for while to let the mock endpoint get all the message
-        Thread.sleep(2000);
 
         assertMockEndpointsSatisfied();
     }
@@ -57,9 +55,6 @@
         byte[] in = "Hello from bytes".getBytes();
         template.sendBody(String.format("mina2:udp://127.0.0.1:%1$s?sync=false", getPort()), in);
 
-        // sleeping for while to let the mock endpoint get all the message
-        Thread.sleep(2000);
-
         assertMockEndpointsSatisfied();
         List<Exchange> list = endpoint.getReceivedExchanges();
         byte[] out = list.get(0).getIn().getBody(byte[].class);
@@ -69,6 +64,44 @@
         }
     }
 
+    @Test
+    public void testSendingRawByteMessage() throws Exception {
+        MockEndpoint endpoint = getMockEndpoint("mock:result");
+        endpoint.expectedMessageCount(1);
+
+        String toSend = "ef3e00559f5faf0262f5ff0962d9008daa91001cd46b0fa9330ef0f3030fff250e46f72444d1cc501678c351e04b8004c"
+                + "4000002080000fe850bbe011030000008031b031bfe9251305441593830354720020800050440ff";
+        byte[] in = fromHexString(toSend);
+        template.sendBody(String.format("mina2:udp://127.0.0.1:%1$s?sync=false", getPort()), in);
+
+        assertMockEndpointsSatisfied();
+        List<Exchange> list = endpoint.getReceivedExchanges();
+        byte[] out = list.get(0).getIn().getBody(byte[].class);
+
+        for (int i = 0; i < in.length; i++) {
+            assertEquals("The bytes should be the same", in[i], out[i]);
+        }
+        assertEquals("The strings should be the same", toSend, byteArrayToHex(out));
+    }
+
+    private String byteArrayToHex(byte[] bytes) {
+        StringBuilder sb = new StringBuilder();
+        for (byte b : bytes) {
+            sb.append(String.format("%02x", b & 0xff));
+        }
+        return sb.toString();
+    }
+
+    private byte[] fromHexString(String hexstr) {
+        byte data[] = new byte[hexstr.length() / 2];
+        int i = 0;
+        for (int n = hexstr.length(); i < n; i += 2) {
+            data[i / 2] = (Integer.decode("0x" + hexstr.charAt(i)
+                    + hexstr.charAt(i + 1))).byteValue();
+        }
+        return data;
+    }
+
     protected RouteBuilder createRouteBuilder() {
         return new RouteBuilder() {
             public void configure() {