diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayCrLfSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayCrLfSerializer.java index 6b3f60939c..6258693272 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayCrLfSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayCrLfSerializer.java @@ -30,6 +30,11 @@ import java.io.OutputStream; */ public class ByteArrayCrLfSerializer extends AbstractPooledBufferByteArraySerializer { + /** + * A single reusable instance. + */ + public static final ByteArrayCrLfSerializer INSTANCE = new ByteArrayCrLfSerializer(); + private static final byte[] CRLF = "\r\n".getBytes(); /** diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLfSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLfSerializer.java index 982f8ec2ee..ee99e795d6 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLfSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLfSerializer.java @@ -23,6 +23,11 @@ package org.springframework.integration.ip.tcp.serializer; */ public class ByteArrayLfSerializer extends ByteArraySingleTerminatorSerializer { + /** + * A single reusable instance. + */ + public static final ByteArrayLfSerializer INSTANCE = new ByteArrayLfSerializer(); + public ByteArrayLfSerializer() { super((byte) 0x0a); } diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayRawSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayRawSerializer.java index 41bda136fd..bd5b448066 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayRawSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayRawSerializer.java @@ -43,6 +43,11 @@ import java.net.SocketTimeoutException; */ public class ByteArrayRawSerializer extends AbstractPooledBufferByteArraySerializer { + /** + * A single reusable instance that does not treat timeouts as end of message. + */ + public static final ByteArrayRawSerializer INSTANCE = new ByteArrayRawSerializer(); + private final boolean treatTimeoutAsEndOfMessage; public ByteArrayRawSerializer() { diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayStxEtxSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayStxEtxSerializer.java index b8f957cdef..93fad3a272 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayStxEtxSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayStxEtxSerializer.java @@ -32,6 +32,11 @@ import org.springframework.integration.mapping.MessageMappingException; */ public class ByteArrayStxEtxSerializer extends AbstractPooledBufferByteArraySerializer { + /** + * A single reusable instance. + */ + public static final ByteArrayStxEtxSerializer INSTANCE = new ByteArrayStxEtxSerializer(); + public static final int STX = 0x02; public static final int ETX = 0x03; diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/TcpCodecs.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/TcpCodecs.java new file mode 100644 index 0000000000..72dd73f71d --- /dev/null +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/TcpCodecs.java @@ -0,0 +1,131 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.ip.tcp.serializer; + +/** + * Factory class to create TCP Serializer/Deserializers used to + * encode/decode messages to/from a TCP stream. + * This is used to simplify configuration with Java, such as + * + *
+ * TcpNetServerConnectionFactory server = new TcpNetServerConnectionFactory(1234); + * server.setSerializer(TcpCodecs.lf()); + * server.setDserializer(TcpCodecs.lf()); + * ... + *+ * + * @author Gary Russell + * @since 5.0 + * + */ +public final class TcpCodecs { + + private static ByteArrayLengthHeaderSerializer oneByteLHS; + + private static ByteArrayLengthHeaderSerializer twoByteLHS; + + private static ByteArrayLengthHeaderSerializer fourByteLHS; + + private TcpCodecs() { + super(); + } + + /** + * @return a {@link ByteArrayCrLfSerializer}. + */ + public static ByteArrayCrLfSerializer crlf() { + return ByteArrayCrLfSerializer.INSTANCE; + } + + /** + * @return a {@link ByteArrayLfSerializer}. + */ + public static ByteArrayLfSerializer lf() { + return ByteArrayLfSerializer.INSTANCE; + } + + /** + * @return a {@link ByteArrayRawSerializer}. + */ + public static ByteArrayRawSerializer raw() { + return ByteArrayRawSerializer.INSTANCE; + } + + /** + * @return a {@link ByteArrayStxEtxSerializer}. + */ + public static ByteArrayStxEtxSerializer stxetx() { + return ByteArrayStxEtxSerializer.INSTANCE; + } + + /** + * @param terminator the terminator indicating message end. + * @return a {@link ByteArraySingleTerminatorSerializer} using the supplied + * terminator. + */ + public static ByteArraySingleTerminatorSerializer singleTerminator(byte terminator) { + return new ByteArraySingleTerminatorSerializer(terminator); + } + + /** + * @return a {@link ByteArrayLengthHeaderSerializer} with a 1 byte header. + */ + public static ByteArrayLengthHeaderSerializer lengthHeader1() { + if (oneByteLHS == null) { + oneByteLHS = new ByteArrayLengthHeaderSerializer(1); + } + return oneByteLHS; + } + + /** + * @return a {@link ByteArrayLengthHeaderSerializer} with a 2 byte header. + */ + public static ByteArrayLengthHeaderSerializer lengthHeader2() { + if (twoByteLHS == null) { + twoByteLHS = new ByteArrayLengthHeaderSerializer(2); + } + return twoByteLHS; + } + + /** + * @return a {@link ByteArrayLengthHeaderSerializer} with a 4 byte header. + */ + public static ByteArrayLengthHeaderSerializer lengthHeader4() { + if (fourByteLHS == null) { + fourByteLHS = new ByteArrayLengthHeaderSerializer(4); + } + return fourByteLHS; + } + + /** + * @param bytes header length. + * @return a {@link ByteArrayLengthHeaderSerializer} with a 1, 2 or 4 byte header. + */ + public static ByteArrayLengthHeaderSerializer lengthHeader(int bytes) { + switch (bytes) { + case 1: + return lengthHeader1(); + case 2: + return lengthHeader2(); + case 4: + return lengthHeader4(); + default: + throw new IllegalArgumentException("Only 1, 2 or 4 byte headers are supported"); + } + } + +} diff --git a/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/TcpCodecsTests.java b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/TcpCodecsTests.java new file mode 100644 index 0000000000..c6497f6266 --- /dev/null +++ b/spring-integration-ip/src/test/java/org/springframework/integration/ip/tcp/serializer/TcpCodecsTests.java @@ -0,0 +1,67 @@ +/* + * Copyright 2016 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.integration.ip.tcp.serializer; + +import static org.hamcrest.Matchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +import org.junit.Test; + +import org.springframework.integration.test.util.TestUtils; + +/** + * @author Gary Russell + * @since 5.0 + * + */ +public class TcpCodecsTests { + + @Test + public void testAll() { + AbstractByteArraySerializer codec = TcpCodecs.crlf(); + assertThat(codec, instanceOf(ByteArrayCrLfSerializer.class)); + codec = TcpCodecs.lf(); + assertThat(codec, instanceOf(ByteArrayLfSerializer.class)); + codec = TcpCodecs.raw(); + assertThat(codec, instanceOf(ByteArrayRawSerializer.class)); + codec = TcpCodecs.stxetx(); + assertThat(codec, instanceOf(ByteArrayStxEtxSerializer.class)); + codec = TcpCodecs.singleTerminator((byte) 23); + assertThat(codec, instanceOf(ByteArraySingleTerminatorSerializer.class)); + assertEquals((byte) 23, TestUtils.getPropertyValue(codec, "terminator")); + codec = TcpCodecs.lengthHeader1(); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertEquals(1, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader2(); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertEquals(2, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader4(); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertEquals(4, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader(1); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertEquals(1, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader(2); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertEquals(2, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader(4); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertEquals(4, TestUtils.getPropertyValue(codec, "headerSize")); + } + +}