From ae3bb154fa51b2be12412c2f12ea0f9d4937d83f Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Fri, 11 Jan 2019 12:12:43 -0500 Subject: [PATCH] TcpCodecs factory improvement - add convenience factory methods to set the max message size while creating the codec * Polishing - PR comments; deprecate protected field; checkstyle fixes. --- .../AbstractByteArraySerializer.java | 15 ++- ...stractPooledBufferByteArraySerializer.java | 4 +- .../serializer/ByteArrayCrLfSerializer.java | 6 +- .../ByteArrayLengthHeaderSerializer.java | 6 +- .../serializer/ByteArrayRawSerializer.java | 6 +- .../ByteArraySingleTerminatorSerializer.java | 6 +- .../serializer/ByteArrayStxEtxSerializer.java | 6 +- .../ip/tcp/serializer/TcpCodecs.java | 119 +++++++++++++++++- .../ip/tcp/serializer/TcpCodecsTests.java | 35 +++++- 9 files changed, 181 insertions(+), 22 deletions(-) diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractByteArraySerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractByteArraySerializer.java index 2cb5527e3d..31755ce245 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractByteArraySerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractByteArraySerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 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. @@ -39,9 +39,16 @@ public abstract class AbstractByteArraySerializer implements Deserializer, ApplicationEventPublisherAware { - protected int maxMessageSize = 2048; + /** + * The default maximum message size when deserializing. + * @since 5.1.3 + */ + public static final int DEFAULT_MAX_MESSAGE_SIZE = 2048; - protected final Log logger = LogFactory.getLog(this.getClass()); + @Deprecated + protected int maxMessageSize = DEFAULT_MAX_MESSAGE_SIZE; // NOSONAR - TODO private in 5.2, use getter + + protected final Log logger = LogFactory.getLog(this.getClass()); // NOSONAR private ApplicationEventPublisher applicationEventPublisher; @@ -50,6 +57,7 @@ public abstract class AbstractByteArraySerializer implements * Default 2048. * @return The max message size. */ + @SuppressWarnings("deprecation") public int getMaxMessageSize() { return this.maxMessageSize; } @@ -59,6 +67,7 @@ public abstract class AbstractByteArraySerializer implements * Default 2048. * @param maxMessageSize The max message size. */ + @SuppressWarnings("deprecation") public void setMaxMessageSize(int maxMessageSize) { this.maxMessageSize = maxMessageSize; } diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractPooledBufferByteArraySerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractPooledBufferByteArraySerializer.java index d9b75fa399..ab7cd27329 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractPooledBufferByteArraySerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/AbstractPooledBufferByteArraySerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2019 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. @@ -77,7 +77,7 @@ public abstract class AbstractPooledBufferByteArraySerializer extends AbstractBy @Override public final byte[] deserialize(InputStream inputStream) throws IOException { - byte[] buffer = this.pool == null ? new byte[this.maxMessageSize] : this.pool.getItem(); + byte[] buffer = this.pool == null ? new byte[getMaxMessageSize()] : this.pool.getItem(); try { return doDeserialize(inputStream, buffer); } 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 cc16a10431..8c3caa5a17 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 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. @@ -66,8 +66,8 @@ public class ByteArrayCrLfSerializer extends AbstractPooledBufferByteArraySerial break; } buffer[n++] = (byte) bite; - if (n >= this.maxMessageSize) { - throw new IOException("CRLF not found before max message length: " + this.maxMessageSize); + if (n >= getMaxMessageSize()) { + throw new IOException("CRLF not found before max message length: " + getMaxMessageSize()); } } return n - 1; // trim \r diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLengthHeaderSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLengthHeaderSerializer.java index 6f0e082921..de51d786dd 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLengthHeaderSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArrayLengthHeaderSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 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. @@ -105,9 +105,9 @@ public class ByteArrayLengthHeaderSerializer extends AbstractByteArraySerializer } byte[] messagePart = null; try { - if (messageLength > this.maxMessageSize) { + if (messageLength > getMaxMessageSize()) { throw new IOException("Message length " + messageLength + - " exceeds max message length: " + this.maxMessageSize); + " exceeds max message length: " + getMaxMessageSize()); } messagePart = new byte[messageLength]; read(inputStream, messagePart, false); 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 bd5b448066..c36e98ee19 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 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. @@ -94,9 +94,9 @@ public class ByteArrayRawSerializer extends AbstractPooledBufferByteArraySeriali } break; } - if (n >= this.maxMessageSize) { + if (n >= getMaxMessageSize()) { throw new IOException("Socket was not closed before max message length: " - + this.maxMessageSize); + + getMaxMessageSize()); } buffer[n++] = (byte) bite; } diff --git a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArraySingleTerminatorSerializer.java b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArraySingleTerminatorSerializer.java index 6d17a8ec61..e725372048 100644 --- a/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArraySingleTerminatorSerializer.java +++ b/spring-integration-ip/src/main/java/org/springframework/integration/ip/tcp/serializer/ByteArraySingleTerminatorSerializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2016 the original author or authors. + * Copyright 2002-2019 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. @@ -60,10 +60,10 @@ public class ByteArraySingleTerminatorSerializer extends AbstractPooledBufferByt break; } buffer[n++] = (byte) bite; - if (n >= this.maxMessageSize) { + if (n >= getMaxMessageSize()) { throw new IOException("Terminator '0x" + Integer.toHexString(this.terminator & 0xff) + "' not found before max message length: " - + this.maxMessageSize); + + getMaxMessageSize()); } } return copyToSizedArray(buffer, n); 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 93fad3a272..9c9d3f482a 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2015 the original author or authors. + * Copyright 2002-2019 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. @@ -63,9 +63,9 @@ public class ByteArrayStxEtxSerializer extends AbstractPooledBufferByteArraySeri while ((bite = inputStream.read()) != ETX) { checkClosure(bite); buffer[n++] = (byte) bite; - if (n >= this.maxMessageSize) { + if (n >= getMaxMessageSize()) { throw new IOException("ETX not found before max message length: " - + this.maxMessageSize); + + getMaxMessageSize()); } } return copyToSizedArray(buffer, n); 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 index 72dd73f71d..7ff6e16c66 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2019 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. @@ -45,44 +45,57 @@ public final class TcpCodecs { } /** + * Return a serializer with the default max message size for deserialization. * @return a {@link ByteArrayCrLfSerializer}. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayCrLfSerializer crlf() { return ByteArrayCrLfSerializer.INSTANCE; } /** + * Return a serializer with the default max message size for deserialization. + * {@value AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE}. * @return a {@link ByteArrayLfSerializer}. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayLfSerializer lf() { return ByteArrayLfSerializer.INSTANCE; } /** + * Return a serializer with the default max message size for deserialization. * @return a {@link ByteArrayRawSerializer}. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayRawSerializer raw() { return ByteArrayRawSerializer.INSTANCE; } /** + * Return a serializer with the default max message size for deserialization. * @return a {@link ByteArrayStxEtxSerializer}. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayStxEtxSerializer stxetx() { return ByteArrayStxEtxSerializer.INSTANCE; } /** + * Return a serializer with the default max message size for deserialization. * @param terminator the terminator indicating message end. * @return a {@link ByteArraySingleTerminatorSerializer} using the supplied * terminator. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArraySingleTerminatorSerializer singleTerminator(byte terminator) { return new ByteArraySingleTerminatorSerializer(terminator); } /** + * Return a serializer with the default max message size for deserialization. * @return a {@link ByteArrayLengthHeaderSerializer} with a 1 byte header. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayLengthHeaderSerializer lengthHeader1() { if (oneByteLHS == null) { @@ -92,7 +105,9 @@ public final class TcpCodecs { } /** + * Return a serializer with the default max message size for deserialization. * @return a {@link ByteArrayLengthHeaderSerializer} with a 2 byte header. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayLengthHeaderSerializer lengthHeader2() { if (twoByteLHS == null) { @@ -102,7 +117,9 @@ public final class TcpCodecs { } /** + * Return a serializer with the default max message size for deserialization. * @return a {@link ByteArrayLengthHeaderSerializer} with a 4 byte header. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayLengthHeaderSerializer lengthHeader4() { if (fourByteLHS == null) { @@ -112,8 +129,10 @@ public final class TcpCodecs { } /** + * Return a serializer with the default max message size for deserialization. * @param bytes header length. * @return a {@link ByteArrayLengthHeaderSerializer} with a 1, 2 or 4 byte header. + * @see AbstractByteArraySerializer#DEFAULT_MAX_MESSAGE_SIZE */ public static ByteArrayLengthHeaderSerializer lengthHeader(int bytes) { switch (bytes) { @@ -128,4 +147,102 @@ public final class TcpCodecs { } } + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayCrLfSerializer}. + * @since 5.1.3 + */ + public static ByteArrayCrLfSerializer crlf(int maxMessageSize) { + ByteArrayCrLfSerializer codec = new ByteArrayCrLfSerializer(); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayLfSerializer}. + * @since 5.1.3 + */ + public static ByteArrayLfSerializer lf(int maxMessageSize) { + ByteArrayLfSerializer codec = new ByteArrayLfSerializer(); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayRawSerializer}. + * @since 5.1.3 + */ + public static ByteArrayRawSerializer raw(int maxMessageSize) { + ByteArrayRawSerializer codec = new ByteArrayRawSerializer(); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayStxEtxSerializer}. + * @since 5.1.3 + */ + public static ByteArrayStxEtxSerializer stxetx(int maxMessageSize) { + ByteArrayStxEtxSerializer codec = new ByteArrayStxEtxSerializer(); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param terminator the terminator indicating message end. + * @param maxMessageSize the max message size. + * @return a {@link ByteArraySingleTerminatorSerializer} using the supplied + * terminator. + * @since 5.1.3 + */ + public static ByteArraySingleTerminatorSerializer singleTerminator(byte terminator, int maxMessageSize) { + ByteArraySingleTerminatorSerializer codec = new ByteArraySingleTerminatorSerializer(terminator); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayLengthHeaderSerializer} with a 1 byte header. + * @since 5.1.3 + */ + public static ByteArrayLengthHeaderSerializer lengthHeader1(int maxMessageSize) { + ByteArrayLengthHeaderSerializer codec = new ByteArrayLengthHeaderSerializer(1); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayLengthHeaderSerializer} with a 2 byte header. + * @since 5.1.3 + */ + public static ByteArrayLengthHeaderSerializer lengthHeader2(int maxMessageSize) { + ByteArrayLengthHeaderSerializer codec = new ByteArrayLengthHeaderSerializer(2); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + + /** + * Return a serializer with the provided max message size for deserialization. + * @param maxMessageSize the max message size. + * @return a {@link ByteArrayLengthHeaderSerializer} with a 4 byte header. + * @since 5.1.3 + */ + public static ByteArrayLengthHeaderSerializer lengthHeader4(int maxMessageSize) { + ByteArrayLengthHeaderSerializer codec = new ByteArrayLengthHeaderSerializer(4); + codec.setMaxMessageSize(maxMessageSize); + return codec; + } + } 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 index c6497f6266..189d009412 100644 --- 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 @@ -1,5 +1,5 @@ /* - * Copyright 2016 the original author or authors. + * Copyright 2016-2019 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. @@ -16,6 +16,7 @@ package org.springframework.integration.ip.tcp.serializer; +import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.instanceOf; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertThat; @@ -64,4 +65,36 @@ public class TcpCodecsTests { assertEquals(4, TestUtils.getPropertyValue(codec, "headerSize")); } + @Test + public void testMaxLengths() { + AbstractByteArraySerializer codec = TcpCodecs.crlf(123); + assertThat(codec, instanceOf(ByteArrayCrLfSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + codec = TcpCodecs.lf(123); + assertThat(codec, instanceOf(ByteArrayLfSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + codec = TcpCodecs.raw(123); + assertThat(codec, instanceOf(ByteArrayRawSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + codec = TcpCodecs.stxetx(123); + assertThat(codec, instanceOf(ByteArrayStxEtxSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + codec = TcpCodecs.singleTerminator((byte) 23, 123); + assertThat(codec, instanceOf(ByteArraySingleTerminatorSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + assertEquals((byte) 23, TestUtils.getPropertyValue(codec, "terminator")); + codec = TcpCodecs.lengthHeader1(123); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + assertEquals(1, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader2(123); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + assertEquals(2, TestUtils.getPropertyValue(codec, "headerSize")); + codec = TcpCodecs.lengthHeader4(123); + assertThat(codec, instanceOf(ByteArrayLengthHeaderSerializer.class)); + assertThat(codec.getMaxMessageSize(), equalTo(123)); + assertEquals(4, TestUtils.getPropertyValue(codec, "headerSize")); + } + }