From 87d994cd6d2965c3d16379c9d7c9b70b41f30646 Mon Sep 17 00:00:00 2001 From: Gary Russell Date: Thu, 15 Apr 2010 22:25:58 +0000 Subject: [PATCH] INT-1008 Simple TCP Inbound Gateway - Initial Commit --- .../integration/ip/IpHeaders.java | 14 +- .../ip/config/IpAdapterParserUtils.java | 12 +- .../ip/config/IpInboundGatewayParser.java | 61 +++++ .../ip/config/IpNamespaceHandler.java | 1 + .../integration/ip/tcp/NetSocketReader.java | 7 + .../integration/ip/tcp/NioSocketReader.java | 8 + .../ip/tcp/SimpleTcpNetInboundGateway.java | 244 ++++++++++++++++++ .../ip/tcp/SocketMessageMapper.java | 1 + .../integration/ip/tcp/SocketReader.java | 6 + .../ip/tcp/TcpNetReceivingChannelAdapter.java | 23 +- .../ip/config/spring-integration-ip-2.0.xsd | 120 +++++++-- .../ip/tcp/NetSocketReaderTests.java | 1 - ...impleTcpNetInboundGatewayTests-context.xml | 36 +++ .../tcp/SimpleTcpNetInboundGatewayTests.java | 58 +++++ .../ip/tcp/SocketMessageMapperTests.java | 10 + .../integration/ip/tcp/TestService.java | 29 +++ 16 files changed, 593 insertions(+), 38 deletions(-) create mode 100644 org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpInboundGatewayParser.java create mode 100644 org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGateway.java create mode 100644 org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests-context.xml create mode 100644 org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests.java create mode 100644 org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/TestService.java diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/IpHeaders.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/IpHeaders.java index e21143037e..f6890177ed 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/IpHeaders.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/IpHeaders.java @@ -29,16 +29,18 @@ public abstract class IpHeaders { private static final String PREFIX = MessageHeaders.PREFIX; - private static final String IP = "ip_"; + private static final String IP = PREFIX + "ip_"; - private static final String TCP = "tcp_"; + private static final String TCP = IP + "tcp_"; - private static final String UDP = "udp_"; + private static final String UDP = IP + "udp_"; - public static final String HOSTNAME = PREFIX + IP + "hostname"; + public static final String HOSTNAME = IP + "hostname"; - public static final String IP_ADDRESS = PREFIX + IP + "address"; + public static final String IP_ADDRESS = IP + "address"; - public static final String ACK_ADDRESS = PREFIX + "ackTo"; + public static final String ACK_ADDRESS = IP + "ackTo"; + + public static final String REMOTE_PORT = TCP + "remote_port"; } diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java index 340fa71f6a..c821439a0f 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpAdapterParserUtils.java @@ -174,20 +174,20 @@ public abstract class IpAdapterParserUtils { * @return The value of the attribute or false. */ static Integer getMessageFormat(Element element) { - String useNio = element.getAttribute(IpAdapterParserUtils.MESSAGE_FORMAT); - if (!StringUtils.hasText(useNio)) { + String messageFormat = element.getAttribute(IpAdapterParserUtils.MESSAGE_FORMAT); + if (!StringUtils.hasText(messageFormat)) { return MessageFormats.FORMAT_LENGTH_HEADER; } - if (useNio.equals("length-header")) { + if (messageFormat.equals("length-header")) { return MessageFormats.FORMAT_LENGTH_HEADER; } - if (useNio.equals("stx-etx")) { + if (messageFormat.equals("stx-etx")) { return MessageFormats.FORMAT_STX_ETX; } - if (useNio.equals("crlf")) { + if (messageFormat.equals("crlf")) { return MessageFormats.FORMAT_CRLF; } - if (useNio.equals("custom")) { + if (messageFormat.equals("custom")) { return MessageFormats.FORMAT_CUSTOM; } return MessageFormats.FORMAT_LENGTH_HEADER; diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpInboundGatewayParser.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpInboundGatewayParser.java new file mode 100644 index 0000000000..56771156cc --- /dev/null +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpInboundGatewayParser.java @@ -0,0 +1,61 @@ +/* + * Copyright 2002-2010 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.config; + +import org.springframework.beans.factory.support.BeanDefinitionBuilder; +import org.springframework.core.Conventions; +import org.springframework.integration.adapter.config.AbstractRemotingGatewayParser; +import org.springframework.integration.ip.tcp.SimpleTcpNetInboundGateway; +import org.w3c.dom.Element; + +import sun.print.IPPPrintService; + +/** + * @author Gary Russell + * + */ +public class IpInboundGatewayParser extends AbstractRemotingGatewayParser { + + + /* (non-Javadoc) + * @see org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser#getBeanClass(org.w3c.dom.Element) + */ + @Override + protected Class getBeanClass(Element element) { + return SimpleTcpNetInboundGateway.class; + } + + /* (non-Javadoc) + * @see org.springframework.integration.adapter.config.AbstractRemotingGatewayParser#isEligibleAttribute(java.lang.String) + */ + @Override + protected boolean isEligibleAttribute(String attributeName) { + return !attributeName.equals(IpAdapterParserUtils.MESSAGE_FORMAT) + && super.isEligibleAttribute(attributeName); + } + + /* (non-Javadoc) + * @see org.springframework.integration.adapter.config.AbstractRemotingGatewayParser#doPostProcess(org.springframework.beans.factory.support.BeanDefinitionBuilder, org.w3c.dom.Element) + */ + @Override + protected void doPostProcess(BeanDefinitionBuilder builder, Element element) { + builder.addPropertyValue( + Conventions.attributeNameToPropertyName(IpAdapterParserUtils.MESSAGE_FORMAT), + IpAdapterParserUtils.getMessageFormat(element)); + } + + +} diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpNamespaceHandler.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpNamespaceHandler.java index 2647a39e00..f8173f546c 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpNamespaceHandler.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/config/IpNamespaceHandler.java @@ -29,6 +29,7 @@ public class IpNamespaceHandler extends AbstractIntegrationNamespaceHandler { public void init() { this.registerBeanDefinitionParser("inbound-channel-adapter", new IpInboundChannelAdapterParser()); this.registerBeanDefinitionParser("outbound-channel-adapter", new IpOutboundChannelAdapterParser()); + this.registerBeanDefinitionParser("inbound-gateway", new IpInboundGatewayParser()); } } diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NetSocketReader.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NetSocketReader.java index 63fa123164..481c2f01d9 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NetSocketReader.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NetSocketReader.java @@ -181,4 +181,11 @@ public class NetSocketReader extends AbstractSocketReader { return this.socket.getInetAddress(); } + /* (non-Javadoc) + * @see org.springframework.integration.ip.tcp.SocketReader#getSocket() + */ + public Socket getSocket() { + return socket; + } + } diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NioSocketReader.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NioSocketReader.java index 8e33c251bf..f37c819e0d 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NioSocketReader.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/NioSocketReader.java @@ -17,6 +17,7 @@ package org.springframework.integration.ip.tcp; import java.io.IOException; import java.net.InetAddress; +import java.net.Socket; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; @@ -331,4 +332,11 @@ public class NioSocketReader extends AbstractSocketReader { this.usingDirectBuffers = usingDirectBuffers; } + /* (non-Javadoc) + * @see org.springframework.integration.ip.tcp.SocketReader#getSocket() + */ + public Socket getSocket() { + return channel.socket(); + } + } diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGateway.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGateway.java new file mode 100644 index 0000000000..f8e8663b49 --- /dev/null +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGateway.java @@ -0,0 +1,244 @@ +/* + * Copyright 2002-2010 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; + +import java.net.Socket; +import java.net.SocketException; + +import org.springframework.integration.adapter.MessageMappingException; +import org.springframework.integration.core.Message; +import org.springframework.integration.gateway.AbstractMessagingGateway; + +/** + * Simple implementation of a TCP/IP inbound gateway; uses {@link java.net.Socket} + * and socket reader thread hangs on receive for response; therefore no multiplexing + * of incoming messages is supported. Delegates most of its work to a private + * subclass of {@link TcpNetReceivingChannelAdapter}, overriding the + * processMessage() method. + * + * Consequently, the pool size needs to be large enough to support the maximum + * number of concurrent connections expected. + * + * @author Gary Russell + * + */ +public class SimpleTcpNetInboundGateway extends AbstractMessagingGateway { + + private SocketMessageMapper mapper = new SocketMessageMapper(); + + private WriteCapableTcpNetReceivingChannelAdapter delegate; + + private int port; + + private int messageFormat = MessageFormats.FORMAT_LENGTH_HEADER; + + private int poolSize = 2; + + private int receiveBufferSize = 2048; + + private boolean soKeepAlive; + + private int soReceiveBufferSize = -1; + + private int soSendBufferSize = -1; + + private int soTimeout = 0; + + private String customSocketReaderClassName; + + private String customSocketWriterClassName; + + + /* (non-Javadoc) + * @see org.springframework.integration.gateway.AbstractMessagingGateway#doStart() + */ + @Override + protected void doStart() { + super.doStart(); + delegate.start(); + } + + /* (non-Javadoc) + * @see org.springframework.integration.gateway.AbstractMessagingGateway#doStop() + */ + @Override + protected void doStop() { + super.doStop(); + delegate.stop(); + } + + /* (non-Javadoc) + * @see org.springframework.integration.gateway.AbstractMessagingGateway#onInit() + */ + @Override + protected void onInit() throws Exception { + delegate = new WriteCapableTcpNetReceivingChannelAdapter(port); + delegate.setMessageFormat(messageFormat); + delegate.setPoolSize(poolSize); + delegate.setReceiveBufferSize(receiveBufferSize); + delegate.setSoKeepAlive(soKeepAlive); + delegate.setSoReceiveBufferSize(soReceiveBufferSize); + delegate.setSoSendBufferSize(soSendBufferSize); + delegate.setSoTimeout(soTimeout); + delegate.setTaskScheduler(getTaskScheduler()); + delegate.setCustomSocketReaderClassName(customSocketReaderClassName); + super.onInit(); + } + + /* (non-Javadoc) + * @see org.springframework.integration.gateway.AbstractMessagingGateway#fromMessage(org.springframework.integration.core.Message) + */ + @Override + protected Object fromMessage(Message message) { + throw new MessageMappingException("Cannot map a message to an object in this gateway"); + } + + /* (non-Javadoc) + * @see org.springframework.integration.gateway.AbstractMessagingGateway#toMessage(java.lang.Object) + */ + @Override + protected Message toMessage(Object object) { + try { + return mapper.toMessage((SocketReader) object); + } catch (Exception e) { + throw new MessageMappingException("Failed to map message", e); + } + } + + + /** + * @param port the port to set + */ + public void setPort(int port) { + this.port = port; + } + + /** + * @param messageFormat the messageFormat to set + */ + public void setMessageFormat(int messageFormat) { + this.messageFormat = messageFormat; + } + + /** + * @param poolSize the poolSize to set + */ + public void setPoolSize(int poolSize) { + this.poolSize = poolSize; + } + + /** + * @param receiveBufferSize the receiveBufferSize to set + */ + public void setReceiveBufferSize(int receiveBufferSize) { + this.receiveBufferSize = receiveBufferSize; + } + + /** + * @param soKeepAlive the soKeepAlive to set + */ + public void setSoKeepAlive(boolean soKeepAlive) { + this.soKeepAlive = soKeepAlive; + } + + /** + * @return the port + */ + public int getPort() { + return port; + } + + /** + * @param soReceiveBufferSize the soReceiveBufferSize to set + */ + public void setSoReceiveBufferSize(int soReceiveBufferSize) { + this.soReceiveBufferSize = soReceiveBufferSize; + } + + /** + * @param soSendBufferSize the soSendBufferSize to set + */ + public void setSoSendBufferSize(int soSendBufferSize) { + this.soSendBufferSize = soSendBufferSize; + } + + /** + * @param soTimeout the soTimeout to set + */ + public void setSoTimeout(int soTimeout) { + this.soTimeout = soTimeout; + } + + /** + * @param customSocketReaderClassName the customSocketReaderClassName to set + */ + public void setCustomSocketReaderClassName(String customSocketReaderClassName) { + this.customSocketReaderClassName = customSocketReaderClassName; + } + + /** + * @param customSocketWriterClassName the customSocketWriterClassName to set + */ + public void setCustomSocketWriterClassName(String customSocketWriterClassName) { + this.customSocketWriterClassName = customSocketWriterClassName; + } + + private class WriteCapableTcpNetReceivingChannelAdapter extends TcpNetReceivingChannelAdapter { + + /** + * @param port + */ + public WriteCapableTcpNetReceivingChannelAdapter(int port) { + super(port); + } + + /* (non-Javadoc) + * @see org.springframework.integration.ip.tcp.TcpNetReceivingChannelAdapter#processMessage(org.springframework.integration.core.Message) + */ + @Override + protected void processMessage(NetSocketReader reader) { + Socket socket = reader.getSocket(); + NetSocketWriter writer = new NetSocketWriter(socket); + writer.setMessageFormat(messageFormat); + Message message = sendAndReceiveMessage(reader); + try { + writer.write(mapper.fromMessage(message)); + } catch (Exception e) { + throw new MessageMappingException("Failed to map and send response", e); + } + } + + /* (non-Javadoc) + * @see org.springframework.integration.ip.AbstractInternetProtocolReceivingChannelAdapter#doStart() + */ + @Override + protected void doStart() { +; super.doStart(); + } + + /* (non-Javadoc) + * @see org.springframework.integration.ip.tcp.AbstractTcpReceivingChannelAdapter#setSocketOptions(java.net.Socket) + */ + @Override + protected void setSocketOptions(Socket socket) throws SocketException { + super.setSocketOptions(socket); + if (soSendBufferSize > 0) { + socket.setSendBufferSize(soSendBufferSize); + } + } + + } +} diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketMessageMapper.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketMessageMapper.java index f1964c99a6..1a2335ee53 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketMessageMapper.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketMessageMapper.java @@ -60,6 +60,7 @@ public class SocketMessageMapper implements message = MessageBuilder.withPayload(payload) .setHeader(IpHeaders.HOSTNAME, socketReader.getAddress().getHostName()) .setHeader(IpHeaders.IP_ADDRESS, socketReader.getAddress().getHostAddress()) + .setHeader(IpHeaders.REMOTE_PORT, socketReader.getSocket().getPort()) .build(); } return message; diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketReader.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketReader.java index 5375cb7e71..640f6787d9 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketReader.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/SocketReader.java @@ -17,6 +17,7 @@ package org.springframework.integration.ip.tcp; import java.io.IOException; import java.net.InetAddress; +import java.net.Socket; /** * General interface for assembling message data from a TCP/IP Socket. @@ -49,4 +50,9 @@ public interface SocketReader { * @return The InetAddress. */ public InetAddress getAddress(); + + /** + * @return the Socket + */ + public Socket getSocket(); } diff --git a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/TcpNetReceivingChannelAdapter.java b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/TcpNetReceivingChannelAdapter.java index 7dc733b5b2..2f5d01bca6 100644 --- a/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/TcpNetReceivingChannelAdapter.java +++ b/org.springframework.integration.ip/src/main/java/org/springframework/integration/ip/tcp/TcpNetReceivingChannelAdapter.java @@ -111,16 +111,27 @@ public class TcpNetReceivingChannelAdapter extends while (true) { try { if (reader.assembleData()) { - Message message = mapper.toMessage(reader); - if (message != null) { - sendMessage(message); - } + processMessage(reader); } } catch (Exception e) { + logger.error("processMessage failed", e); return; } } } + + /** + * @param reader + * @return + * @throws Exception + */ + protected void processMessage(NetSocketReader reader) + throws Exception { + Message message = mapper.toMessage(reader); + if (message != null) { + sendMessage(message); + } + } @Override protected void doStop() { @@ -140,8 +151,10 @@ public class TcpNetReceivingChannelAdapter extends @SuppressWarnings("unchecked") public void setCustomSocketReaderClassName( String customSocketReaderClassName) throws ClassNotFoundException { - this.customSocketReader = (Class) Class + if (customSocketReaderClassName != null) { + this.customSocketReader = (Class) Class .forName(customSocketReaderClassName); + } } } diff --git a/org.springframework.integration.ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.0.xsd b/org.springframework.integration.ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.0.xsd index be0f6f51b0..9824a6da69 100644 --- a/org.springframework.integration.ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.0.xsd +++ b/org.springframework.integration.ip/src/main/resources/org/springframework/integration/ip/config/spring-integration-ip-2.0.xsd @@ -28,13 +28,6 @@ - - - - - - - @@ -67,7 +60,14 @@ the custom message format. See java docs for TcpNetReceivingChannelAdapter and T - + + + +If message-format = 'custom' you must provide a sub class of the appropriate type to implement +the custom message format. See java docs for TcpNetSendingChannelAdapter and TcpNioSendingChannelAdapter. + + + @@ -76,28 +76,109 @@ the custom message format. See java docs for TcpNetReceivingChannelAdapter and T + + + + Defines an inbound Gateway for receiving and replying to incoming IP packets. + + + + + + + + + + +If message-format = 'custom' you must provide a sub class of the appropriate type to implement +the custom message format. See java docs for TcpNetReceivingChannelAdapter and TcpNioReceivingChannelAdapter. + + + + + + +If message-format = 'custom' you must provide a sub class of the appropriate type to implement +the custom message format. See java docs for TcpNetSendingChannelAdapter and TcpNioSendingChannelAdapter. + + + + + + + + Common configuration for IP-based adapters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines common configuration for gateway adapters. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - @@ -111,7 +192,6 @@ the custom message format. See java docs for TcpNetReceivingChannelAdapter and T - \ No newline at end of file diff --git a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/NetSocketReaderTests.java b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/NetSocketReaderTests.java index 5aabc4f6d9..9181292695 100644 --- a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/NetSocketReaderTests.java +++ b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/NetSocketReaderTests.java @@ -16,7 +16,6 @@ package org.springframework.integration.ip.tcp; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.IOException; diff --git a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests-context.xml b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests-context.xml new file mode 100644 index 0000000000..e0256be8be --- /dev/null +++ b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests-context.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + diff --git a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests.java b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests.java new file mode 100644 index 0000000000..6c23943255 --- /dev/null +++ b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SimpleTcpNetInboundGatewayTests.java @@ -0,0 +1,58 @@ +/* + * Copyright 2002-2010 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; + +import static org.junit.Assert.assertEquals; + +import java.net.Socket; + +import javax.net.SocketFactory; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; + +/** + * @author Gary Russell + * + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class SimpleTcpNetInboundGatewayTests { + + @Autowired + SimpleTcpNetInboundGateway gateway; + + @Test + public void test1() throws Exception { + Thread.sleep(2000); + Socket socket = SocketFactory.getDefault().createSocket("localhost", gateway.getPort()); + String greetings = "Hello World!"; + socket.getOutputStream().write((greetings + "\r\n").getBytes()); + StringBuilder sb = new StringBuilder(); + int c; + while (true) { + c = socket.getInputStream().read(); + sb.append((char) c); + if (c == '\n') { + break; + } + } + assertEquals("echo:" + greetings + "\r\n", sb.toString()); + } +} diff --git a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SocketMessageMapperTests.java b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SocketMessageMapperTests.java index fcd0b03da0..798d3e0d8c 100644 --- a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SocketMessageMapperTests.java +++ b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/SocketMessageMapperTests.java @@ -19,6 +19,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.fail; import java.net.InetAddress; +import java.net.Socket; import java.net.UnknownHostException; import org.junit.Test; @@ -50,6 +51,8 @@ public class SocketMessageMapperTests { .getHeaders().get(IpHeaders.HOSTNAME)); assertEquals(InetAddress.getLocalHost().getHostAddress(), message .getHeaders().get(IpHeaders.IP_ADDRESS)); + assertEquals(0, message + .getHeaders().get(IpHeaders.REMOTE_PORT)); } /** @@ -92,6 +95,13 @@ public class SocketMessageMapperTests { return false; } + /* (non-Javadoc) + * @see org.springframework.integration.ip.tcp.SocketReader#getSocket() + */ + public Socket getSocket() { + return new Socket(); + } + } diff --git a/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/TestService.java b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/TestService.java new file mode 100644 index 0000000000..fa6514ff77 --- /dev/null +++ b/org.springframework.integration.ip/src/test/java/org/springframework/integration/ip/tcp/TestService.java @@ -0,0 +1,29 @@ +/* + * Copyright 2002-2010 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; + +/** + * Simple echo service. + * + * @author Gary Russell + * + */ +public class TestService { + + public String test(byte[] bytes) { + return "echo:" + new String(bytes); + } +}