INT-1279 Namespace Updates For New Gateways; Remove Old Gateways/Adapters; Migrate All Tests to New Gateways/Adapters
This commit is contained in:
@@ -19,9 +19,7 @@ package org.springframework.integration.ip.config;
|
||||
import org.springframework.beans.factory.BeanCreationException;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ip.tcp.MessageFormats;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
@@ -33,8 +31,6 @@ import org.w3c.dom.Element;
|
||||
*/
|
||||
public abstract class IpAdapterParserUtils {
|
||||
|
||||
static final String IP_PROTOCOL_ATTRIBUTE = "protocol";
|
||||
|
||||
static final String UDP_MULTICAST = "multicast";
|
||||
|
||||
static final String MULTICAST_ADDRESS = "multicast-address";
|
||||
@@ -87,8 +83,6 @@ public abstract class IpAdapterParserUtils {
|
||||
|
||||
static final String SO_TRAFFIC_CLASS = "so-traffic-class";
|
||||
|
||||
static final String CLOSE = "close";
|
||||
|
||||
static final String LOCAL_ADDRESS = "local-address";
|
||||
|
||||
static final String TASK_EXECUTOR = "task-executor";
|
||||
@@ -104,6 +98,13 @@ public abstract class IpAdapterParserUtils {
|
||||
static final String TCP_CONNECTION_FACTORY = "connection-factory";
|
||||
|
||||
public static final String INTERCEPTOR_FACTORY_CHAIN = "interceptor-factory-chain";
|
||||
|
||||
public static final String REQUEST_TIMEOUT = "request-timeout";
|
||||
|
||||
public static final String REPLY_TIMEOUT = "reply-timeout";
|
||||
|
||||
public static final String REPLY_CHANNEL = "reply-channel";
|
||||
|
||||
|
||||
/**
|
||||
* Adds a constructor-arg to the provided bean definition builder
|
||||
@@ -151,26 +152,6 @@ public abstract class IpAdapterParserUtils {
|
||||
builder.addConstructorArgValue(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a protocol attribute (udp or tcp) is supplied,
|
||||
* @param element
|
||||
* @param parserContext
|
||||
* @return The value of the attribute.
|
||||
* @throws BeanCreationException if attribute not provided or invalid.
|
||||
*/
|
||||
static String getProtocol(Element element, ParserContext parserContext) {
|
||||
String protocol = element.getAttribute(IpAdapterParserUtils.IP_PROTOCOL_ATTRIBUTE);
|
||||
if (!StringUtils.hasText(protocol)) {
|
||||
parserContext.getReaderContext().error(IpAdapterParserUtils.IP_PROTOCOL_ATTRIBUTE +
|
||||
" is required for an IP channel adapter", element);
|
||||
}
|
||||
if (!protocol.equals("tcp") && !protocol.equals("udp")) {
|
||||
parserContext.getReaderContext().error(IpAdapterParserUtils.IP_PROTOCOL_ATTRIBUTE +
|
||||
" must be 'tcp' or 'udp' for an IP channel adapter", element);
|
||||
}
|
||||
return protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Asserts that a port attribute is supplied.
|
||||
* @param element
|
||||
@@ -200,22 +181,6 @@ public abstract class IpAdapterParserUtils {
|
||||
return multicast;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the close attribute, if present.
|
||||
* @param element
|
||||
*/
|
||||
static void setClose(Element element, BeanDefinitionBuilder builder) {
|
||||
String close = element.getAttribute(IpAdapterParserUtils.CLOSE);
|
||||
if (!StringUtils.hasText(close)) {
|
||||
close = "false";
|
||||
}
|
||||
if (close.equals("true")) {
|
||||
builder.addPropertyValue(
|
||||
Conventions.attributeNameToPropertyName(IpAdapterParserUtils.CLOSE),
|
||||
close);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the use-nio attribute, if present; if not returns 'false'.
|
||||
* @param element
|
||||
@@ -229,58 +194,6 @@ public abstract class IpAdapterParserUtils {
|
||||
return useNio;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the message-format attribute, if present; if not returns
|
||||
* {@link MessageFormats#FORMAT_LENGTH_HEADER}.
|
||||
* @param element
|
||||
* @return The value of the attribute or false.
|
||||
*/
|
||||
static Integer getMessageFormat(Element element) {
|
||||
String messageFormat = element.getAttribute(IpAdapterParserUtils.MESSAGE_FORMAT);
|
||||
if (!StringUtils.hasText(messageFormat)) {
|
||||
return MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
}
|
||||
if (messageFormat.equals("length-header")) {
|
||||
return MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
}
|
||||
if (messageFormat.equals("stx-etx")) {
|
||||
return MessageFormats.FORMAT_STX_ETX;
|
||||
}
|
||||
if (messageFormat.equals("crlf")) {
|
||||
return MessageFormats.FORMAT_CRLF;
|
||||
}
|
||||
if (messageFormat.equals("serialized")) {
|
||||
return MessageFormats.FORMAT_JAVA_SERIALIZED;
|
||||
}
|
||||
if (messageFormat.equals("custom")) {
|
||||
return MessageFormats.FORMAT_CUSTOM;
|
||||
}
|
||||
return MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @param builder
|
||||
*/
|
||||
public static void addOutboundTcpAttributes(Element element,
|
||||
BeanDefinitionBuilder builder) {
|
||||
builder.addPropertyValue(
|
||||
Conventions.attributeNameToPropertyName(IpAdapterParserUtils.MESSAGE_FORMAT),
|
||||
IpAdapterParserUtils.getMessageFormat(element));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.CUSTOM_SOCKET_WRITER_CLASS_NAME);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.USING_DIRECT_BUFFERS);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_KEEP_ALIVE);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_LINGER);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_TCP_NODELAY);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_TRAFFIC_CLASS);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the common port attributes on the bean being built (timeout, receive buffer size,
|
||||
* send buffer size).
|
||||
|
||||
@@ -27,10 +27,10 @@ import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHa
|
||||
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());
|
||||
this.registerBeanDefinitionParser("outbound-gateway", new IpOutboundGatewayParser());
|
||||
this.registerBeanDefinitionParser("udp-inbound-channel-adapter", new UdpInboundChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("udp-outbound-channel-adapter", new UdpOutboundChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("tcp-inbound-gateway", new TcpInboundGatewayParser());
|
||||
this.registerBeanDefinitionParser("tcp-outbound-gateway", new TcpOutboundGatewayParser());
|
||||
this.registerBeanDefinitionParser("tcp-connection-factory", new TcpConnectionParser());
|
||||
this.registerBeanDefinitionParser("tcp-inbound-channel-adapter", new TcpInboundChannelAdapterParser());
|
||||
this.registerBeanDefinitionParser("tcp-outbound-channel-adapter", new TcpOutboundChannelAdapterParser());
|
||||
|
||||
@@ -67,7 +67,7 @@ public class TcpConnectionParser extends AbstractBeanDefinitionParser {
|
||||
}
|
||||
} else {
|
||||
parserContext.getReaderContext().error(IpAdapterParserUtils.TCP_CONNECTION_TYPE +
|
||||
" must be 'client' or 'server' for an IP channel adapter", element);
|
||||
" must be 'client' or 'server' for a TCP Connection Factory", element);
|
||||
}
|
||||
IpAdapterParserUtils.addCommonSocketOptions(builder, element);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
|
||||
@@ -16,40 +16,32 @@
|
||||
|
||||
package org.springframework.integration.ip.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.integration.config.xml.AbstractInboundGatewayParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ip.tcp.SimpleTcpNetInboundGateway;
|
||||
import org.springframework.integration.ip.tcp.TcpInboundGateway;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class IpInboundGatewayParser extends AbstractInboundGatewayParser {
|
||||
public class TcpInboundGatewayParser extends AbstractInboundGatewayParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return SimpleTcpNetInboundGateway.class;
|
||||
return TcpInboundGateway.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isEligibleAttribute(String attributeName) {
|
||||
return !attributeName.equals(IpAdapterParserUtils.MESSAGE_FORMAT)
|
||||
&& !attributeName.equals(IpAdapterParserUtils.TASK_EXECUTOR)
|
||||
return !attributeName.equals(IpAdapterParserUtils.TCP_CONNECTION_FACTORY)
|
||||
&& super.isEligibleAttribute(attributeName);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doPostProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
builder.addPropertyValue(
|
||||
Conventions.attributeNameToPropertyName(IpAdapterParserUtils.MESSAGE_FORMAT),
|
||||
IpAdapterParserUtils.getMessageFormat(element));
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.TASK_EXECUTOR);
|
||||
}
|
||||
IpAdapterParserUtils.TCP_CONNECTION_FACTORY); }
|
||||
|
||||
}
|
||||
@@ -28,7 +28,7 @@ import org.w3c.dom.Element;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class IpOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
public class TcpOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
|
||||
@Override
|
||||
protected String getInputChannelAttributeName() {
|
||||
@@ -38,14 +38,15 @@ public class IpOutboundGatewayParser extends AbstractConsumerEndpointParser {
|
||||
@Override
|
||||
protected BeanDefinitionBuilder parseHandler(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
"org.springframework.integration.ip.tcp.SimpleTcpNetOutboundGateway");
|
||||
IpAdapterParserUtils.addHostAndPortToConstructor(element, builder, parserContext);
|
||||
IpAdapterParserUtils.addCommonSocketOptions(builder, element);
|
||||
IpAdapterParserUtils.addOutboundTcpAttributes(element, builder);
|
||||
"org.springframework.integration.ip.tcp.TcpOutboundGateway");
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.TCP_CONNECTION_FACTORY);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.REPLY_CHANNEL);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.CUSTOM_SOCKET_READER_CLASS_NAME);
|
||||
IntegrationNamespaceUtils.setReferenceIfAttributeDefined(builder, element, "reply-channel");
|
||||
IpAdapterParserUtils.setClose(element, builder);
|
||||
IpAdapterParserUtils.REQUEST_TIMEOUT);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.REPLY_TIMEOUT);
|
||||
return builder;
|
||||
}
|
||||
|
||||
@@ -16,19 +16,15 @@
|
||||
|
||||
package org.springframework.integration.ip.config;
|
||||
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.support.AbstractBeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.core.Conventions;
|
||||
import org.springframework.integration.config.xml.AbstractChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ip.tcp.TcpNetReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.TcpNioReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.udp.MulticastReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.udp.UnicastReceivingChannelAdapter;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* Channel Adapter that receives UDP datagram packets and maps them to Messages.
|
||||
@@ -36,16 +32,10 @@ import org.springframework.util.StringUtils;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class IpInboundChannelAdapterParser extends AbstractChannelAdapterParser {
|
||||
public class UdpInboundChannelAdapterParser extends AbstractChannelAdapterParser {
|
||||
|
||||
protected AbstractBeanDefinition doParse(Element element, ParserContext parserContext, String channelName) {
|
||||
String protocol = IpAdapterParserUtils.getProtocol(element, parserContext);
|
||||
BeanDefinitionBuilder builder = null;
|
||||
if (protocol.equals("tcp")) {
|
||||
builder = parseTcp(element, parserContext);
|
||||
} else if (protocol.equals("udp")) {
|
||||
builder = parseUdp(element, parserContext);
|
||||
}
|
||||
BeanDefinitionBuilder builder = parseUdp(element, parserContext);
|
||||
IpAdapterParserUtils.addCommonSocketOptions(builder, element);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.RECEIVE_BUFFER_SIZE);
|
||||
@@ -100,34 +90,4 @@ public class IpInboundChannelAdapterParser extends AbstractChannelAdapterParser
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @param parserContext
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinitionBuilder parseTcp(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder;
|
||||
String useNio = IpAdapterParserUtils.getUseNio(element);
|
||||
if (useNio.equals("false")) {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TcpNetReceivingChannelAdapter.class);
|
||||
}
|
||||
else {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TcpNioReceivingChannelAdapter.class);
|
||||
}
|
||||
addPortToConstructor(element, builder, parserContext);
|
||||
builder.addPropertyValue(
|
||||
Conventions.attributeNameToPropertyName(IpAdapterParserUtils.MESSAGE_FORMAT),
|
||||
IpAdapterParserUtils.getMessageFormat(element));
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.CUSTOM_SOCKET_READER_CLASS_NAME);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.USING_DIRECT_BUFFERS);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element,
|
||||
IpAdapterParserUtils.SO_KEEP_ALIVE);
|
||||
IpAdapterParserUtils.setClose(element, builder);
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler;
|
||||
import org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler;
|
||||
import org.springframework.integration.ip.udp.MulticastSendingMessageHandler;
|
||||
import org.springframework.integration.ip.udp.UnicastSendingMessageHandler;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -32,17 +30,10 @@ import org.w3c.dom.Element;
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class IpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
|
||||
public class UdpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
|
||||
|
||||
protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) {
|
||||
String protocol = IpAdapterParserUtils.getProtocol(element, parserContext);
|
||||
BeanDefinitionBuilder builder = null;
|
||||
if (protocol.equals("tcp")) {
|
||||
builder = parseTcp(element, parserContext);
|
||||
}
|
||||
else if (protocol.equals("udp")) {
|
||||
builder = parseUdp(element, parserContext);
|
||||
}
|
||||
BeanDefinitionBuilder builder = parseUdp(element, parserContext);
|
||||
IpAdapterParserUtils.addCommonSocketOptions(builder, element);
|
||||
return builder.getBeanDefinition();
|
||||
}
|
||||
@@ -103,25 +94,4 @@ public class IpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapt
|
||||
return builder;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param element
|
||||
* @param parserContext
|
||||
* @return
|
||||
*/
|
||||
private BeanDefinitionBuilder parseTcp(Element element, ParserContext parserContext) {
|
||||
BeanDefinitionBuilder builder;
|
||||
String useNio = IpAdapterParserUtils.getUseNio(element);
|
||||
if (useNio.equals("false")) {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TcpNetSendingMessageHandler.class);
|
||||
}
|
||||
else {
|
||||
builder = BeanDefinitionBuilder
|
||||
.genericBeanDefinition(TcpNioSendingMessageHandler.class);
|
||||
}
|
||||
IpAdapterParserUtils.addHostAndPortToConstructor(element, builder, parserContext);
|
||||
IpAdapterParserUtils.addOutboundTcpAttributes(element, builder);
|
||||
return builder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
|
||||
/**
|
||||
* Abstract SocketReader that handles data in 3 standard, and one custom
|
||||
* format. The default format is {@link MessageFormats#FORMAT_LENGTH_HEADER} in which
|
||||
* the message consists of a 4 byte integer (in network byte order) containing
|
||||
* the length of data that follows. {@link MessageFormats#FORMAT_STX_ETX}
|
||||
* indicates a message where the data begins with STX (0x02) and ends with
|
||||
* ETX (0x03); the STX and ETX are not part of the data. {@link MessageFormats#FORMAT_CRLF}
|
||||
* indicates a message followed by carriage return and line feed '\r\n'.
|
||||
* FORMAT_LENGTH_HEADER can be used for {@link java.net.Socket} and
|
||||
* {@link java.nio.channels.SocketChannel} implementations are provided for
|
||||
* the standard formats. Users requiring other formats should subclass the
|
||||
* appropriate implementation, and provide an implementation for
|
||||
* {@link #assembleDataCustomFormat()} which is invoked by {@link #assembleData()}
|
||||
* when the format is {@link MessageFormats#FORMAT_CUSTOM}.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractSocketReader implements SocketReader, MessageFormats {
|
||||
|
||||
protected int messageFormat = FORMAT_LENGTH_HEADER;
|
||||
|
||||
/**
|
||||
* The assembled data; must contain a reference when assembleData()
|
||||
* returns true; will be set to null when getAssembledData() is called.
|
||||
*/
|
||||
protected Object assembledData;
|
||||
|
||||
protected int maxMessageSize = 1024 * 60;
|
||||
|
||||
/**
|
||||
* Assembles data in format {@link #FORMAT_LENGTH_HEADER}.
|
||||
* @return SocketReader.MESSAGE_COMPLETE when message is assembled, otherwise SocketReader.MESSAGE_IMCOMPLETE, or
|
||||
* < 0 if socket closed before any data for a message is received.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract int assembleDataLengthFormat() throws IOException;
|
||||
|
||||
/**
|
||||
* Assembles data in format {@link #FORMAT_STX_ETX}.
|
||||
* @return SocketReader.MESSAGE_COMPLETE when message is assembled, otherwise SocketReader.MESSAGE_IMCOMPLETE, or
|
||||
* < 0 if socket closed before any data for a message is received.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract int assembleDataStxEtxFormat() throws IOException;
|
||||
|
||||
/**
|
||||
* Assembles data in format {@link #FORMAT_CRLF}.
|
||||
* @return SocketReader.MESSAGE_COMPLETE when message is assembled, otherwise SocketReader.MESSAGE_IMCOMPLETE, or
|
||||
* < 0 if socket closed before any data for a message is received.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract int assembleDataCrLfFormat() throws IOException;
|
||||
|
||||
/**
|
||||
* Assembles data in format {@link #FORMAT_JAVA_SERIALIZED}
|
||||
* @return SocketReader.MESSAGE_COMPLETE when message is assembled, otherwise SocketReader.MESSAGE_IMCOMPLETE, or
|
||||
* < 0 if socket closed before any data for a message is received.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract int assembleDataSerializedFormat() throws IOException;
|
||||
|
||||
/**
|
||||
* Assembles data in format {@link #FORMAT_CUSTOM}. Implementations must
|
||||
* return false until the message is completely assembled, at which time
|
||||
* the implementation must update assembledData to reference the assembled
|
||||
* message.
|
||||
* @return True when a message is completely assembled.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract int assembleDataCustomFormat() throws IOException;
|
||||
|
||||
public int assembleData() throws IOException {
|
||||
int result;
|
||||
try {
|
||||
switch (this.messageFormat) {
|
||||
case FORMAT_LENGTH_HEADER:
|
||||
result = assembleDataLengthFormat();
|
||||
break;
|
||||
case FORMAT_STX_ETX:
|
||||
result = assembleDataStxEtxFormat();
|
||||
break;
|
||||
case FORMAT_CRLF:
|
||||
result = assembleDataCrLfFormat();
|
||||
break;
|
||||
case FORMAT_JAVA_SERIALIZED:
|
||||
result = assembleDataSerializedFormat();
|
||||
break;
|
||||
case FORMAT_CUSTOM:
|
||||
result = assembleDataCustomFormat();
|
||||
break;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported message format: " + messageFormat);
|
||||
}
|
||||
if (result < 0) {
|
||||
doClose();
|
||||
}
|
||||
return result;
|
||||
} catch (IOException e) {
|
||||
doClose();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getAssembledData()
|
||||
*/
|
||||
public Object getAssembledData() {
|
||||
Object assembledData = this.assembledData;
|
||||
this.assembledData = null;
|
||||
if (assembledData instanceof byte[] &&
|
||||
((byte[]) assembledData).length == 0) {
|
||||
return null;
|
||||
}
|
||||
return assembledData;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called after an exception; close the transport.
|
||||
*/
|
||||
protected abstract void doClose();
|
||||
|
||||
/**
|
||||
* @param messageFormat the messageFormat to set,
|
||||
*/
|
||||
public void setMessageFormat(int messageFormat) {
|
||||
this.messageFormat = messageFormat;
|
||||
}
|
||||
|
||||
public void setMaxMessageSize(int maxMessageSize) {
|
||||
this.maxMessageSize = maxMessageSize;
|
||||
}
|
||||
}
|
||||
@@ -1,123 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
/**
|
||||
* Abstract SocketWriter that handles data in 3 standard, and one custom
|
||||
* format. The default format is {@link MessageFormats#FORMAT_LENGTH_HEADER} in which
|
||||
* the message consists of a 4 byte integer (in network byte order) containing
|
||||
* the length of data that follows. {@link MessageFormats#FORMAT_STX_ETX}
|
||||
* indicates a message where the data begins with STX (0x02) and ends with
|
||||
* ETX (0x03); the STX and ETX are not part of the data. {@link MessageFormats#FORMAT_CRLF}
|
||||
* indicates a message followed by carriage return and line feed '\r\n'.
|
||||
* FORMAT_LENGTH_HEADER can be used for {@link java.net.Socket} and
|
||||
* {@link java.nio.channels.SocketChannel} implementations are provided for
|
||||
* the standard formats. Users requiring other formats should subclass the
|
||||
* appropriate implementation, and provide an implementation for
|
||||
* {@link #writeCustomFormat(Object)} which is invoked by {@link #write(Object)}
|
||||
* when the format is {@link MessageFormats#FORMAT_CUSTOM}.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractSocketWriter implements SocketWriter, MessageFormats {
|
||||
|
||||
protected int messageFormat = FORMAT_LENGTH_HEADER;
|
||||
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
/*
|
||||
* @see org.springframework.integration.ip.tcp.SocketWriter#write(Object)
|
||||
*/
|
||||
public synchronized void write(Object object) throws IOException {
|
||||
try {
|
||||
switch (this.messageFormat) {
|
||||
case FORMAT_LENGTH_HEADER:
|
||||
writeLengthFormat((byte[]) object);
|
||||
return;
|
||||
case FORMAT_STX_ETX:
|
||||
writeStxEtxFormat((byte[]) object);
|
||||
return;
|
||||
case FORMAT_CRLF:
|
||||
writeCrLfFormat((byte[]) object);
|
||||
return;
|
||||
case FORMAT_JAVA_SERIALIZED:
|
||||
writeSerializedFormat(object);
|
||||
return;
|
||||
case FORMAT_CUSTOM:
|
||||
writeCustomFormat(object);
|
||||
return;
|
||||
default:
|
||||
throw new UnsupportedOperationException(
|
||||
"Unsupported message format: " + messageFormat);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
doClose();
|
||||
throw e;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when an IO error
|
||||
*/
|
||||
protected abstract void doClose();
|
||||
|
||||
|
||||
/**
|
||||
* Write the length of the data in a 4 byte integer (in network byte
|
||||
* order) before the data itself.
|
||||
* @param bytes The bytes to write.
|
||||
* @throws IOException
|
||||
*/
|
||||
protected abstract void writeLengthFormat(byte[] bytes) throws IOException;
|
||||
|
||||
/**
|
||||
* Write an STX (0x02) followed by the data, followed by ETX (0x03).
|
||||
* @param bytes The bytes to write.
|
||||
*/
|
||||
protected abstract void writeStxEtxFormat(byte[] bytes) throws IOException;
|
||||
|
||||
/**
|
||||
* Write the data, followed by carriage return, line feed ('\r\n').
|
||||
*/
|
||||
protected abstract void writeCrLfFormat(byte[] bytes) throws IOException;
|
||||
|
||||
/**
|
||||
* Write the data, followed by carriage return, line feed ('\r\n').
|
||||
*/
|
||||
protected abstract void writeSerializedFormat(Object object) throws IOException;
|
||||
|
||||
/**
|
||||
* Write the data using some custom protocol.
|
||||
*/
|
||||
protected abstract void writeCustomFormat(Object object) throws IOException;
|
||||
|
||||
/**
|
||||
* @param messageFormat the messageFormat to set
|
||||
*/
|
||||
public void setMessageFormat(int messageFormat) {
|
||||
this.messageFormat = messageFormat;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.ip.AbstractInternetProtocolReceivingChannelAdapter;
|
||||
|
||||
/**
|
||||
* Abstract class for tcp/ip incoming channel adapters. Implementations
|
||||
* for {@link java.net.Socket} and {@link java.nio.channels.SocketChannel}
|
||||
* are provided.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractTcpReceivingChannelAdapter extends
|
||||
AbstractInternetProtocolReceivingChannelAdapter {
|
||||
|
||||
protected volatile SocketMessageMapper mapper = new SocketMessageMapper();
|
||||
|
||||
protected volatile boolean soKeepAlive;
|
||||
|
||||
protected volatile int messageFormat = MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
|
||||
protected volatile boolean close;
|
||||
|
||||
/**
|
||||
* Constructs a receiving channel adapter that listens on the port.
|
||||
* @param port The port to listen on.
|
||||
*/
|
||||
public AbstractTcpReceivingChannelAdapter(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that we have a task executor and calls
|
||||
* {@link #server()}.
|
||||
*/
|
||||
public void run() {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug(this.getClass().getSimpleName() + " running on port: " + port);
|
||||
}
|
||||
checkTaskExecutor("TCP-Incoming-Msg-Handler");
|
||||
server();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the server.
|
||||
*/
|
||||
protected abstract void server();
|
||||
|
||||
/**
|
||||
* Sets soTimeout, soKeepAlive and tcpNoDelay according to the configured
|
||||
* properties.
|
||||
* @param socket The socket.
|
||||
* @throws SocketException
|
||||
*/
|
||||
protected void setSocketOptions(Socket socket) throws SocketException {
|
||||
socket.setSoTimeout(this.soTimeout);
|
||||
if (this.soReceiveBufferSize > 0) {
|
||||
socket.setReceiveBufferSize(this.soReceiveBufferSize);
|
||||
}
|
||||
socket.setKeepAlive(this.soKeepAlive);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Socket#setKeepAlive(boolean)
|
||||
* @param soKeepAlive the soKeepAlive to set
|
||||
*/
|
||||
public void setSoKeepAlive(boolean soKeepAlive) {
|
||||
this.soKeepAlive = soKeepAlive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see MessageFormats
|
||||
* @param messageFormat the messageFormat to set
|
||||
*/
|
||||
public void setMessageFormat(int messageFormat) {
|
||||
this.messageFormat = messageFormat;
|
||||
mapper.setMessageFormat(messageFormat);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param close the close to set
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageDeliveryException;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.MessageRejectedException;
|
||||
import org.springframework.integration.ip.AbstractInternetProtocolSendingMessageHandler;
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
|
||||
/**
|
||||
* Abstract class for TCP sending message handlers. Implementations
|
||||
* for {@link java.net.Socket} and {@link java.nio.channels.SocketChannel}
|
||||
* are provided.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractTcpSendingMessageHandler extends
|
||||
AbstractInternetProtocolSendingMessageHandler {
|
||||
|
||||
protected SocketMessageMapper mapper = new SocketMessageMapper();
|
||||
|
||||
protected AbstractSocketWriter writer;
|
||||
|
||||
protected boolean soTcpNoDelay = false;
|
||||
|
||||
protected int soLinger = -1;
|
||||
|
||||
protected int soTrafficClass = -1;
|
||||
|
||||
protected boolean soKeepAlive = false;
|
||||
|
||||
protected int messageFormat = MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
|
||||
/**
|
||||
* Constructs a message handler that sends messages to the specified
|
||||
* host and port.
|
||||
* @param host The host.
|
||||
* @param port The port.
|
||||
*/
|
||||
public AbstractTcpSendingMessageHandler(String host, int port) {
|
||||
super(host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets socket attributes on the socket.
|
||||
* @param socket The socket.
|
||||
* @throws SocketException
|
||||
*/
|
||||
protected void setSocketAttributes(Socket socket) throws SocketException {
|
||||
if (this.soTimeout >= 0) {
|
||||
socket.setSoTimeout(this.soTimeout);
|
||||
}
|
||||
if (this.soSendBufferSize > 0) {
|
||||
socket.setSendBufferSize(this.soSendBufferSize);
|
||||
}
|
||||
socket.setTcpNoDelay(this.soTcpNoDelay);
|
||||
if (soLinger >= 0) {
|
||||
socket.setSoLinger(true, this.soLinger);
|
||||
}
|
||||
if (soTrafficClass >= 0) {
|
||||
socket.setTrafficClass(this.soTrafficClass);
|
||||
}
|
||||
socket.setKeepAlive(this.soKeepAlive);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the socket writer after instantiating it, if necessary.
|
||||
* @return The writer.
|
||||
*/
|
||||
protected abstract SocketWriter getWriter();
|
||||
|
||||
/**
|
||||
* Writes the message payload to the underlying socket, using the specified
|
||||
* message format.
|
||||
* @see org.springframework.integration.core.MessageHandler#handleMessage(org.springframework.integration.Message)
|
||||
*/
|
||||
public void handleMessage(final Message<?> message) throws MessageRejectedException,
|
||||
MessageHandlingException, MessageDeliveryException {
|
||||
try {
|
||||
doWrite(message);
|
||||
} catch (MessageMappingException e) {
|
||||
// retry - socket may have closed
|
||||
if (e.getCause() instanceof IOException) {
|
||||
doWrite(message);
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Method that actually does the write.
|
||||
* @param message The message to write.
|
||||
*/
|
||||
protected void doWrite(Message<?> message) {
|
||||
try {
|
||||
Object object = mapper.fromMessage(message);
|
||||
SocketWriter writer = this.getWriter();
|
||||
if (writer == null) {
|
||||
throw new MessageMappingException(message, "Failed to create SocketWriter");
|
||||
}
|
||||
writer.write(object);
|
||||
} catch (Exception e) {
|
||||
this.writer = null;
|
||||
if (e instanceof MessageMappingException) {
|
||||
throw (MessageMappingException) e;
|
||||
}
|
||||
throw new MessageMappingException(message, "Failed to map message", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Socket#setTcpNoDelay(boolean)
|
||||
* @param soTcpNoDelay the soTcpNoDelay to set
|
||||
*/
|
||||
public void setSoTcpNoDelay(boolean soTcpNoDelay) {
|
||||
this.soTcpNoDelay = soTcpNoDelay;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables SO_LINGER on the underlying socket.
|
||||
* @see Socket#setSoLinger(boolean, int)
|
||||
* @param soLinger the soLinger to set
|
||||
*/
|
||||
public void setSoLinger(int soLinger) {
|
||||
this.soLinger = soLinger;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Socket#setTrafficClass(int)
|
||||
* @param soTrafficClass the soTrafficClass to set
|
||||
*/
|
||||
public void setSoTrafficClass(int soTrafficClass) {
|
||||
this.soTrafficClass = soTrafficClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Socket#setKeepAlive(boolean)
|
||||
* @param soKeepAlive the soKeepAlive to set
|
||||
*/
|
||||
public void setSoKeepAlive(boolean soKeepAlive) {
|
||||
this.soKeepAlive = soKeepAlive;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see MessageFormats
|
||||
* @param messageFormat the messageFormat to set
|
||||
*/
|
||||
public void setMessageFormat(int messageFormat) {
|
||||
this.messageFormat = messageFormat;
|
||||
mapper.setMessageFormat(messageFormat);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* Definition of message formats supported by tcp channel adapters.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public interface MessageFormats {
|
||||
|
||||
/**
|
||||
* Message has format '<length><message>'.
|
||||
*/
|
||||
public static final int FORMAT_LENGTH_HEADER = 1;
|
||||
/**
|
||||
* Message has format 'STX<message>ETX'.
|
||||
*/
|
||||
public static final int FORMAT_STX_ETX = 2;
|
||||
/**
|
||||
* Message has format '<message>\r\n'.
|
||||
*/
|
||||
public static final int FORMAT_CRLF = 3;
|
||||
/**
|
||||
* Not a real format; any formats less than this must use
|
||||
* a byte[] payload (or a String for outbound). Formats higher
|
||||
* have implied format (e.g. Serializable).
|
||||
*/
|
||||
public static final int FORMAT_IMPLICIT = 128;
|
||||
/**
|
||||
* Message contains a Serializable object
|
||||
*/
|
||||
public static final int FORMAT_JAVA_SERIALIZED = 129;
|
||||
/**
|
||||
* Message has custom format.
|
||||
*/
|
||||
public static final int FORMAT_CUSTOM = 255;
|
||||
|
||||
public static final int STX = 0x02;
|
||||
|
||||
public static final int ETX = 0x03;
|
||||
|
||||
}
|
||||
@@ -1,228 +0,0 @@
|
||||
/*
|
||||
* 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.io.EOFException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
|
||||
/**
|
||||
* A SocketReader that reads from a {@link java.net.Socket}. Threads
|
||||
* calling {@link NetSocketReader#assembledData} will block until a message
|
||||
* is completely assembled.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class NetSocketReader extends AbstractSocketReader {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected Socket socket;
|
||||
|
||||
protected ObjectInputStream objectInputStream;
|
||||
|
||||
/**
|
||||
* Constructs a NetsocketReader which reads from the Socket.
|
||||
* @param socket The socket.
|
||||
*/
|
||||
public NetSocketReader(Socket socket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#read(java.nio.ByteBuffer)
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataLengthFormat() throws IOException {
|
||||
byte[] lengthPart = new byte[4];
|
||||
int status = read(lengthPart, true);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
int messageLength = ByteBuffer.wrap(lengthPart).getInt();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Message length is " + messageLength);
|
||||
}
|
||||
if (messageLength > this.maxMessageSize) {
|
||||
throw new IOException("Message length " + messageLength +
|
||||
" exceeds max message length: " + this.maxMessageSize);
|
||||
}
|
||||
byte[] messagePart = new byte[messageLength];
|
||||
read(messagePart, false);
|
||||
this.assembledData = messagePart;
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataStxEtxFormat()
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataStxEtxFormat() throws IOException {
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
int bite = inputStream.read();
|
||||
if (bite < 0) {
|
||||
return bite;
|
||||
}
|
||||
if (bite != STX)
|
||||
throw new MessageMappingException("Expected STX to begin message");
|
||||
byte[] buffer = new byte[this.maxMessageSize];
|
||||
int n = 0;
|
||||
while ((bite = inputStream.read()) != ETX) {
|
||||
checkClosure(bite);
|
||||
buffer[n++] = (byte) bite;
|
||||
if (n >= this.maxMessageSize) {
|
||||
throw new IOException("ETX not found before max message length: "
|
||||
+ this.maxMessageSize);
|
||||
}
|
||||
}
|
||||
this.assembledData = new byte[n];
|
||||
System.arraycopy(buffer, 0, this.assembledData, 0, n);
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
private void checkClosure(int bite) throws IOException {
|
||||
if (bite < 0) {
|
||||
logger.debug("Socket closed");
|
||||
throw new IOException("Socket closed");
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataCrLfFormat()
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataCrLfFormat() throws IOException {
|
||||
InputStream inputStream = socket.getInputStream();
|
||||
byte[] buffer = new byte[this.maxMessageSize];
|
||||
int n = 0;
|
||||
int bite;
|
||||
while (true) {
|
||||
bite = inputStream.read();
|
||||
if (bite < 0 && n == 0) {
|
||||
return bite;
|
||||
}
|
||||
checkClosure(bite);
|
||||
if (n > 0 && bite == '\n' && buffer[n-1] == '\r')
|
||||
break;
|
||||
buffer[n++] = (byte) bite;
|
||||
if (n >= this.maxMessageSize) {
|
||||
throw new IOException("CRLF not found before max message length: "
|
||||
+ this.maxMessageSize);
|
||||
}
|
||||
};
|
||||
this.assembledData = new byte[n-1];
|
||||
System.arraycopy(buffer, 0, this.assembledData, 0, n-1);
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int assembleDataSerializedFormat() throws IOException {
|
||||
try {
|
||||
if (this.objectInputStream == null) {
|
||||
InputStream is = this.socket.getInputStream();
|
||||
this.objectInputStream = new ObjectInputStream(is);
|
||||
}
|
||||
this.assembledData = this.objectInputStream.readObject();
|
||||
} catch (EOFException ee) {
|
||||
return SOCKET_CLOSED;
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
return SocketReader.MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}; custom implementations can
|
||||
* subclass this class and provide an implementation for this method.
|
||||
* @throws IOException
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataCustomFormat
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataCustomFormat() throws IOException {
|
||||
throw new UnsupportedOperationException("Need to subclass for this format");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data from the socket and puts the data in buffer. Blocks until
|
||||
* buffer is full or a socket timeout occurs.
|
||||
* @param buffer
|
||||
* @param header true if we are reading the header
|
||||
* @return < 0 if socket closed and not in the middle of a message
|
||||
* @throws IOException
|
||||
*/
|
||||
protected int read(byte[] buffer, boolean header) throws IOException {
|
||||
int lengthRead = 0;
|
||||
int needed = buffer.length;
|
||||
while (lengthRead < needed) {
|
||||
int len;
|
||||
len = this.socket.getInputStream().read(buffer, lengthRead,
|
||||
needed - lengthRead);
|
||||
if (len < 0 && header && lengthRead == 0) {
|
||||
return len;
|
||||
}
|
||||
if (len < 0)
|
||||
logger.debug("socket closed after " + lengthRead + " of " + needed);
|
||||
checkClosure(len);
|
||||
lengthRead += len;
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + len + " bytes, buffer is now at " +
|
||||
lengthRead + " of " +
|
||||
needed);
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#doClose()
|
||||
*/
|
||||
@Override
|
||||
protected void doClose() {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("Error on close", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getAddress()
|
||||
*/
|
||||
public InetAddress getAddress() {
|
||||
return this.socket.getInetAddress();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getSocket()
|
||||
*/
|
||||
public Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,114 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
/**
|
||||
* A {@link SocketWriter} that writes to a {@link java.net.Socket}. The
|
||||
* data is wrapped in a wire protocol based on the messageFormat property.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NetSocketWriter extends AbstractSocketWriter {
|
||||
|
||||
protected Socket socket;
|
||||
|
||||
protected ObjectOutputStream objectOutputStream;
|
||||
|
||||
/**
|
||||
* Constructs a NetSocketWriter for the Socket.
|
||||
*
|
||||
* @param socket The socket.
|
||||
*/
|
||||
public NetSocketWriter(Socket socket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeCrLfFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeCrLfFormat(byte[] bytes) throws IOException {
|
||||
OutputStream outputStream = this.socket.getOutputStream();
|
||||
outputStream.write(bytes);
|
||||
outputStream.write('\r');
|
||||
outputStream.write('\n');
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeCustomFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeSerializedFormat(Object object) throws IOException {
|
||||
if (this.objectOutputStream == null) {
|
||||
OutputStream os = this.socket.getOutputStream();
|
||||
this.objectOutputStream = new ObjectOutputStream(os);
|
||||
}
|
||||
this.objectOutputStream.writeObject(object);
|
||||
this.objectOutputStream.flush();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeCustomFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeCustomFormat(Object object) throws IOException {
|
||||
throw new UnsupportedOperationException("Need to subclass for this format");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeLengthFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeLengthFormat(byte[] bytes) throws IOException {
|
||||
ByteBuffer lengthPart = ByteBuffer.allocate(4);
|
||||
lengthPart.putInt(bytes.length);
|
||||
OutputStream outputStream = this.socket.getOutputStream();
|
||||
outputStream.write(lengthPart.array());
|
||||
outputStream.write(bytes);
|
||||
outputStream.flush();
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeStxEtxFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeStxEtxFormat(byte[] bytes) throws IOException {
|
||||
OutputStream outputStream = this.socket.getOutputStream();
|
||||
outputStream.write(STX);
|
||||
outputStream.write(bytes);
|
||||
outputStream.write(ETX);
|
||||
outputStream.flush();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#doClose()
|
||||
*/
|
||||
@Override
|
||||
protected void doClose() {
|
||||
try {
|
||||
this.socket.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("Error on close", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,367 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
|
||||
/**
|
||||
* A non-blocking SocketReader that reads from a {@link java.nio.channels.SocketChannel}.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class NioSocketReader extends AbstractSocketReader {
|
||||
|
||||
protected final Log logger = LogFactory.getLog(getClass());
|
||||
|
||||
protected SocketChannel channel;
|
||||
|
||||
protected boolean usingDirectBuffers;
|
||||
|
||||
protected ByteBuffer lengthPart;
|
||||
|
||||
protected ByteBuffer dataPart;
|
||||
|
||||
protected ByteBuffer rawBuffer;
|
||||
|
||||
protected ByteBuffer buildBuffer;
|
||||
|
||||
protected boolean building;
|
||||
|
||||
/**
|
||||
* Constructs an NioSocketReader which reads from the SocketChannel.
|
||||
* @param channel The channel.
|
||||
*/
|
||||
public NioSocketReader(SocketChannel channel) {
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#assembleData()
|
||||
*/
|
||||
@Override
|
||||
public int assembleDataLengthFormat() throws IOException {
|
||||
if (lengthPart == null) {
|
||||
lengthPart = allocate(4);
|
||||
}
|
||||
if (lengthPart.hasRemaining()) {
|
||||
int status = readChannel(lengthPart);
|
||||
if (status < 0) {
|
||||
if (lengthPart.remaining() == 4) {
|
||||
// not in the middle of a message, clean close
|
||||
return status;
|
||||
}
|
||||
throw new IOException("Channel closed");
|
||||
}
|
||||
return MESSAGE_INCOMPLETE;
|
||||
}
|
||||
if (dataPart == null) {
|
||||
lengthPart.flip();
|
||||
int messageLength = lengthPart.getInt();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Message length is " + messageLength);
|
||||
}
|
||||
if (messageLength > maxMessageSize) {
|
||||
throw new IOException("Message length " + messageLength +
|
||||
" exceeds max message length " + maxMessageSize);
|
||||
}
|
||||
dataPart = ByteBuffer.allocate(messageLength);
|
||||
}
|
||||
if (dataPart.hasRemaining()) {
|
||||
int status = readChannel(dataPart);
|
||||
if (status < 0) {
|
||||
throw new IOException("Channel closed");
|
||||
}
|
||||
if (dataPart.hasRemaining()) {
|
||||
return MESSAGE_INCOMPLETE;
|
||||
}
|
||||
}
|
||||
assembledData = dataPart.array();
|
||||
lengthPart = dataPart = null;
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataStxEtxFormat()
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataStxEtxFormat() throws IOException {
|
||||
int len = readChannelNonDeterministic();
|
||||
if (len > 0) {
|
||||
byte bite = this.rawBuffer.get();
|
||||
int count = 0;
|
||||
if (!this.building) {
|
||||
if (bite != STX) {
|
||||
throw new MessageMappingException("Expected STX, received " + Integer.toHexString(bite));
|
||||
}
|
||||
this.building = true;
|
||||
count++;
|
||||
if (!this.rawBuffer.hasRemaining()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Incomplete message, consumed 1 byte");
|
||||
}
|
||||
return MESSAGE_INCOMPLETE;
|
||||
}
|
||||
} else {
|
||||
if (bite == ETX) {
|
||||
finishAssembly();
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
this.buildBuffer.put(bite);
|
||||
count++;
|
||||
if (this.buildBuffer.position() >= this.buildBuffer.limit()) {
|
||||
throw new IOException("ETX not found before max message length: "
|
||||
+ maxMessageSize);
|
||||
}
|
||||
}
|
||||
while (true) {
|
||||
if (!this.rawBuffer.hasRemaining()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Incomplete message, consumed " + count + " bytes");
|
||||
}
|
||||
return MESSAGE_INCOMPLETE;
|
||||
}
|
||||
bite = this.rawBuffer.get();
|
||||
if (bite == ETX) {
|
||||
break;
|
||||
}
|
||||
this.buildBuffer.put(bite);
|
||||
count++;
|
||||
if (this.buildBuffer.position() >= this.buildBuffer.limit()) {
|
||||
throw new IOException("ETX not found before max message length: "
|
||||
+ maxMessageSize);
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Consumed " + count + " bytes");
|
||||
}
|
||||
finishAssembly();
|
||||
return MESSAGE_COMPLETE;
|
||||
} else if (len == 0) {
|
||||
logger.debug("Incomplete message, nothing to read");
|
||||
return MESSAGE_INCOMPLETE;
|
||||
} else {
|
||||
logger.debug("Channel closed");
|
||||
if (!this.building) {
|
||||
// not in the middle of a message, clean close
|
||||
return SOCKET_CLOSED;
|
||||
}
|
||||
this.building = false;
|
||||
throw new IOException("Channel closed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void finishAssembly() {
|
||||
byte[] assembledData = new byte[buildBuffer.position()];
|
||||
System.arraycopy(this.buildBuffer.array(), 0, assembledData, 0, assembledData.length);
|
||||
this.building = false;
|
||||
this.buildBuffer.clear();
|
||||
this.assembledData = assembledData;
|
||||
logger.debug("Message assembly complete");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataCrLfFormat()
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataCrLfFormat() throws IOException {
|
||||
int len = readChannelNonDeterministic();
|
||||
if (len > 0) {
|
||||
int count = 0;
|
||||
while (true) {
|
||||
if (!rawBuffer.hasRemaining()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Incomplete message, consumed " + count + " bytes");
|
||||
}
|
||||
return MESSAGE_INCOMPLETE;
|
||||
}
|
||||
byte bite = rawBuffer.get();
|
||||
this.building = true;
|
||||
if (bite == '\n' && this.buildBuffer.position() > 0) {
|
||||
this.buildBuffer.position(this.buildBuffer.position() - 1);
|
||||
if (this.buildBuffer.get() == '\r') {
|
||||
this.buildBuffer.position(this.buildBuffer.position() - 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
this.buildBuffer.put(bite);
|
||||
count++;
|
||||
if (this.buildBuffer.position() >= this.buildBuffer.limit()) {
|
||||
throw new IOException("CRLF not found before max message length: "
|
||||
+ this.maxMessageSize);
|
||||
}
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Consumed " + count + " bytes");
|
||||
}
|
||||
finishAssembly();
|
||||
return MESSAGE_COMPLETE;
|
||||
} else if (len == 0) {
|
||||
logger.debug("Incomplete message, nothing to read");
|
||||
return MESSAGE_INCOMPLETE;
|
||||
} else {
|
||||
logger.debug("Channel closed");
|
||||
if (!this.building) {
|
||||
// not in the middle of a message, clean close
|
||||
return SOCKET_CLOSED;
|
||||
}
|
||||
this.building = false;
|
||||
throw new IOException("Channel closed");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}; Java serialization is currently only
|
||||
* supported using the NetSocketReader.
|
||||
* @throws IOException
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataCustomFormat
|
||||
*
|
||||
*/
|
||||
protected int assembleDataSerializedFormat() throws IOException {
|
||||
throw new UnsupportedOperationException("Serializable not supported using NIO");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Throws {@link UnsupportedOperationException}; custom implementations can
|
||||
* subclass this class and provide an implementation.
|
||||
* @throws IOException
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#assembleDataCustomFormat
|
||||
*
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataCustomFormat() throws IOException {
|
||||
throw new UnsupportedOperationException("Need to subclass for this format");
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads from the channel into the buffer. Reads as much data as is
|
||||
* currently available in the channel.
|
||||
* @param buffer
|
||||
* @throws IOException
|
||||
*/
|
||||
protected int readChannel(ByteBuffer buffer) throws IOException {
|
||||
try {
|
||||
int len = channel.read(buffer);
|
||||
if (len < 0) {
|
||||
logger.debug("Socket closed");
|
||||
return len;
|
||||
}
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + len + " bytes, buffer is now at " +
|
||||
buffer.position() + " of " +
|
||||
buffer.capacity());
|
||||
}
|
||||
return len;
|
||||
} catch (IOException e) {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads data into the rawBuffer for non-deterministic algorithms.
|
||||
* @return bytes remaining in raw buffer or < 0 if channel closed
|
||||
* @throws IOException
|
||||
*/
|
||||
protected int readChannelNonDeterministic() throws IOException {
|
||||
if (rawBuffer == null) {
|
||||
rawBuffer = allocate(maxMessageSize);
|
||||
buildBuffer = ByteBuffer.allocate(maxMessageSize);
|
||||
} else if (rawBuffer.hasRemaining()) {
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Raw buffer has " + rawBuffer.remaining() + " remaining");
|
||||
}
|
||||
return rawBuffer.remaining();
|
||||
}
|
||||
rawBuffer.clear();
|
||||
int len = channel.read(rawBuffer);
|
||||
if (len < 0) {
|
||||
return len;
|
||||
}
|
||||
rawBuffer.flip();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Read " + rawBuffer.limit() + " into raw buffer");
|
||||
}
|
||||
return rawBuffer.remaining();
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a ByteBuffer of the requested length using normal or
|
||||
* direct buffers, depending on the usingDirectBuffers field.
|
||||
*/
|
||||
protected ByteBuffer allocate(int length) {
|
||||
ByteBuffer buffer;
|
||||
if (usingDirectBuffers) {
|
||||
buffer = ByteBuffer.allocateDirect(length);
|
||||
} else {
|
||||
buffer = ByteBuffer.allocate(length);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketReader#doClose()
|
||||
*/
|
||||
@Override
|
||||
protected void doClose() {
|
||||
try {
|
||||
channel.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("Error on close", e);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getAddress()
|
||||
*/
|
||||
public InetAddress getAddress() {
|
||||
return this.channel.socket().getInetAddress();
|
||||
}
|
||||
|
||||
public boolean isUsingDirectBuffers() {
|
||||
return usingDirectBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param usingDirectBuffers the usingDirectBuffers to set
|
||||
*/
|
||||
public void setUsingDirectBuffers(boolean usingDirectBuffers) {
|
||||
this.usingDirectBuffers = usingDirectBuffers;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getSocket()
|
||||
*/
|
||||
public Socket getSocket() {
|
||||
return channel.socket();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,268 +0,0 @@
|
||||
/*
|
||||
* Copyright 2002-20/10 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.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* A {@link SocketWriter} that writes to a {@link SocketChannel}. The
|
||||
* data is wrapped in a wire protocol based on the messageFormat property.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class NioSocketWriter extends AbstractSocketWriter {
|
||||
|
||||
protected SocketChannel channel;
|
||||
|
||||
/**
|
||||
* If true, direct buffers are used.
|
||||
* @see ByteBuffer for more information
|
||||
*/
|
||||
protected boolean usingDirectBuffers;
|
||||
|
||||
/**
|
||||
* A buffer containing the length part when the messageFormat is
|
||||
* {@link MessageFormats#FORMAT_LENGTH_HEADER}.
|
||||
*/
|
||||
protected ByteBuffer lengthPart;
|
||||
|
||||
/**
|
||||
* A buffer containing the STX for when the messageFormat is
|
||||
* {@link MessageFormats#FORMAT_STX_ETX}.
|
||||
*/
|
||||
protected ByteBuffer stxPart;
|
||||
|
||||
/**
|
||||
* A buffer containing the ETX for when the messageFormat is
|
||||
* {@link MessageFormats#FORMAT_STX_ETX}.
|
||||
*/
|
||||
protected ByteBuffer etxPart;
|
||||
|
||||
/**
|
||||
* A buffer containing the CRLF for when the messageFormat is
|
||||
* {@link MessageFormats#FORMAT_CRLF}.
|
||||
*/
|
||||
protected ByteBuffer crLfPart;
|
||||
|
||||
/**
|
||||
* If we are using direct buffers, we don't want to churn them using
|
||||
* normal heap management. But,
|
||||
* because we can have multiple threads writing and we might write in
|
||||
* chunks, we need a dedicated buffer for each thread; up to a limit.
|
||||
* We handle this with a blocking queue.
|
||||
*/
|
||||
protected BlockingQueue<ByteBuffer> buffers;
|
||||
|
||||
protected int maxBuffers = 2;
|
||||
|
||||
protected int bufferCount = 0;
|
||||
|
||||
private int sendBufferSize;
|
||||
|
||||
public NioSocketWriter(SocketChannel channel,
|
||||
int maxBuffers,
|
||||
int sendBufferSize) {
|
||||
this.channel = channel;
|
||||
this.maxBuffers = maxBuffers;
|
||||
if (sendBufferSize <= 0) {
|
||||
sendBufferSize = 2048;
|
||||
}
|
||||
this.sendBufferSize = sendBufferSize;
|
||||
buffers = new LinkedBlockingQueue<ByteBuffer>(maxBuffers);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param usingDirectBuffers whether direct buffers are to be used
|
||||
*/
|
||||
public void setUsingDirectBuffers(boolean usingDirectBuffers) {
|
||||
this.usingDirectBuffers = usingDirectBuffers;
|
||||
}
|
||||
|
||||
protected ByteBuffer getBuffer() throws InterruptedException {
|
||||
ByteBuffer buffer = this.buffers.poll();
|
||||
if (buffer != null) {
|
||||
buffer.clear();
|
||||
return buffer;
|
||||
}
|
||||
synchronized (buffers) {
|
||||
if (this.bufferCount < this.maxBuffers) {
|
||||
bufferCount++;
|
||||
return ByteBuffer.allocateDirect(this.sendBufferSize);
|
||||
}
|
||||
}
|
||||
buffer = this.buffers.take();
|
||||
buffer.clear();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
protected void returnBuffer(ByteBuffer buffer) {
|
||||
if (buffer != null) {
|
||||
this.buffers.offer(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeCrLfFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeCrLfFormat(byte[] bytes) throws IOException {
|
||||
ByteBuffer buffer = null;
|
||||
if (this.usingDirectBuffers) {
|
||||
try {
|
||||
checkBufferSize(bytes, 2);
|
||||
buffer = getBuffer();
|
||||
buffer.put(bytes);
|
||||
buffer.put((byte) '\r');
|
||||
buffer.put((byte) '\n');
|
||||
buffer.flip();
|
||||
this.channel.write(buffer);
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Could not get buffer; interrupted");
|
||||
} finally {
|
||||
returnBuffer(buffer);
|
||||
}
|
||||
}
|
||||
synchronized (channel) {
|
||||
if (this.crLfPart == null) {
|
||||
this.crLfPart = ByteBuffer.allocate(2);
|
||||
this.crLfPart.put((byte) '\r');
|
||||
this.crLfPart.put((byte) '\n');
|
||||
}
|
||||
this.channel.write(ByteBuffer.wrap(bytes));
|
||||
this.crLfPart.flip();
|
||||
this.channel.write(this.crLfPart);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeCustomFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeSerializedFormat(Object object) throws IOException {
|
||||
throw new UnsupportedOperationException("Serializable not supported using NIO");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeCustomFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeCustomFormat(Object object) throws IOException {
|
||||
throw new UnsupportedOperationException("Need to subclass for this format");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeLengthFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeLengthFormat(byte[] bytes) throws IOException {
|
||||
ByteBuffer buffer = null;
|
||||
if (this.usingDirectBuffers) {
|
||||
try {
|
||||
checkBufferSize(bytes, 4);
|
||||
buffer = getBuffer();
|
||||
buffer.putInt(bytes.length);
|
||||
buffer.put(bytes);
|
||||
buffer.flip();
|
||||
this.channel.write(buffer);
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Could not get buffer; interrupted");
|
||||
} finally {
|
||||
returnBuffer(buffer);
|
||||
}
|
||||
}
|
||||
synchronized (channel) {
|
||||
if (this.lengthPart == null) {
|
||||
this.lengthPart = ByteBuffer.allocate(4);
|
||||
} else {
|
||||
this.lengthPart.clear();
|
||||
}
|
||||
this.lengthPart.putInt(bytes.length);
|
||||
this.lengthPart.flip();
|
||||
this.channel.write(this.lengthPart);
|
||||
this.channel.write(ByteBuffer.wrap(bytes));
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#writeStxEtxFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeStxEtxFormat(byte[] bytes) throws IOException {
|
||||
ByteBuffer buffer = null;
|
||||
if (this.usingDirectBuffers) {
|
||||
try {
|
||||
checkBufferSize(bytes, 2);
|
||||
buffer = getBuffer();
|
||||
buffer.put((byte) STX);
|
||||
buffer.put(bytes);
|
||||
buffer.put((byte) ETX);
|
||||
buffer.flip();
|
||||
this.channel.write(buffer);
|
||||
return;
|
||||
} catch (InterruptedException e) {
|
||||
throw new IOException("Could not get buffer; interrupted");
|
||||
} finally {
|
||||
returnBuffer(buffer);
|
||||
}
|
||||
}
|
||||
synchronized (channel) {
|
||||
if (this.stxPart == null) {
|
||||
this.stxPart = ByteBuffer.allocate(1);
|
||||
this.stxPart.put((byte) STX);
|
||||
this.etxPart = ByteBuffer.allocate(1);
|
||||
this.etxPart.put((byte) ETX);
|
||||
}
|
||||
this.stxPart.flip();
|
||||
this.channel.write(this.stxPart);
|
||||
this.channel.write(ByteBuffer.wrap(bytes));
|
||||
this.etxPart.flip();
|
||||
this.channel.write(this.etxPart);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bytes
|
||||
* @throws IOException
|
||||
*/
|
||||
private void checkBufferSize(byte[] bytes, int pad) throws IOException {
|
||||
if (bytes.length + pad > this.sendBufferSize) {
|
||||
throw new IOException("Send buffer too small (" + sendBufferSize +
|
||||
") increase so-send-buffer-size to at least " +
|
||||
bytes.length + pad);
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.AbstractSocketWriter#doClose()
|
||||
*/
|
||||
@Override
|
||||
protected void doClose() {
|
||||
try {
|
||||
this.channel.close();
|
||||
} catch (IOException e) {
|
||||
logger.error("Error on close", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,266 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.gateway.AbstractMessagingGateway;
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class SimpleTcpNetInboundGateway extends AbstractMessagingGateway {
|
||||
|
||||
protected SocketMessageMapper mapper = new SocketMessageMapper();
|
||||
|
||||
protected WriteCapableTcpNetReceivingChannelAdapter delegate;
|
||||
|
||||
protected int port;
|
||||
|
||||
protected int messageFormat = MessageFormats.FORMAT_LENGTH_HEADER;
|
||||
|
||||
protected int poolSize = 2;
|
||||
|
||||
protected int receiveBufferSize = 2048;
|
||||
|
||||
protected boolean soKeepAlive;
|
||||
|
||||
protected int soReceiveBufferSize = -1;
|
||||
|
||||
protected int soSendBufferSize = -1;
|
||||
|
||||
protected int soTimeout = 0;
|
||||
|
||||
protected String customSocketReaderClassName;
|
||||
|
||||
protected Class<NetSocketWriter> customSocketWriterClass;
|
||||
|
||||
protected boolean close;
|
||||
|
||||
protected String localAddress;
|
||||
|
||||
protected Executor taskExecutor;
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
super.doStart();
|
||||
this.delegate.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
super.doStop();
|
||||
this.delegate.stop();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() throws Exception {
|
||||
this.delegate = new WriteCapableTcpNetReceivingChannelAdapter(this.port);
|
||||
this.delegate.setMessageFormat(this.messageFormat);
|
||||
this.delegate.setPoolSize(this.poolSize);
|
||||
this.delegate.setReceiveBufferSize(this.receiveBufferSize);
|
||||
this.delegate.setSoKeepAlive(this.soKeepAlive);
|
||||
this.delegate.setSoReceiveBufferSize(this.soReceiveBufferSize);
|
||||
this.delegate.setSoSendBufferSize(this.soSendBufferSize);
|
||||
this.delegate.setSoTimeout(this.soTimeout);
|
||||
this.delegate.setTaskScheduler(getTaskScheduler());
|
||||
this.delegate.setCustomSocketReaderClassName(this.customSocketReaderClassName);
|
||||
this.delegate.setClose(this.close);
|
||||
this.delegate.setLocalAddress(this.localAddress);
|
||||
this.delegate.setTaskExecutor(this.taskExecutor);
|
||||
super.onInit();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object fromMessage(Message<?> message) {
|
||||
throw new MessageMappingException("Cannot map a message to an object in this gateway");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Message<?> toMessage(Object object) {
|
||||
try {
|
||||
return this.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;
|
||||
mapper.setMessageFormat(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 this.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
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomSocketWriterClassName(
|
||||
String customSocketWriterClassName) throws ClassNotFoundException {
|
||||
if (customSocketWriterClassName != null) {
|
||||
this.customSocketWriterClass = (Class<NetSocketWriter>) Class
|
||||
.forName(customSocketWriterClassName);
|
||||
if (!(NetSocketWriter.class.isAssignableFrom(this.customSocketWriterClass))) {
|
||||
throw new IllegalArgumentException("Custom socket writer must be of type NetSocketWriter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param close the close to set
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
public void setTaskExecutor(Executor taskExecutor) {
|
||||
this.taskExecutor = taskExecutor;
|
||||
}
|
||||
|
||||
public boolean isListening() {
|
||||
return delegate.isListening();
|
||||
}
|
||||
|
||||
public void setLocalAddress(String localAddress) {
|
||||
this.localAddress = localAddress;
|
||||
}
|
||||
|
||||
private class WriteCapableTcpNetReceivingChannelAdapter extends TcpNetReceivingChannelAdapter {
|
||||
|
||||
/**
|
||||
* @param port
|
||||
*/
|
||||
public WriteCapableTcpNetReceivingChannelAdapter(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processMessage(NetSocketReader reader) {
|
||||
Socket socket = reader.getSocket();
|
||||
Message<?> message = sendAndReceiveMessage(reader);
|
||||
NetSocketWriter writer = SocketIoUtils.createNetWriter(this.messageFormat,
|
||||
customSocketWriterClass, socket);
|
||||
try {
|
||||
writer.write(this.mapper.fromMessage(message));
|
||||
if (close) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (IOException ioe) {
|
||||
logger.error("Error on close", ioe);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessageMappingException("Failed to map and send response", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStart() {
|
||||
; super.doStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setSocketOptions(Socket socket) throws SocketException {
|
||||
super.setSocketOptions(socket);
|
||||
if (soSendBufferSize > 0) {
|
||||
socket.setSendBufferSize(soSendBufferSize);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,226 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
|
||||
/**
|
||||
* Simple TCP outbound gateway; delegates write to a {@link TcpNetSendingMessageHandler}
|
||||
* then blocks on read of same socket. Uses {@link java.net.Socket} and the client
|
||||
* thread is dedicated to a request/response pair. No multiplexing of requests
|
||||
* over the outbound socket are supported. This class is thread safe in that
|
||||
* if multiple clients attempt to send a message, they will be blocked until
|
||||
* any existing request/response is processed.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class SimpleTcpNetOutboundGateway extends
|
||||
AbstractReplyProducingMessageHandler {
|
||||
|
||||
|
||||
protected TcpNetSendingMessageHandler handler;
|
||||
|
||||
protected Class<NetSocketReader> customSocketReaderClass;
|
||||
|
||||
protected int messageFormat;
|
||||
|
||||
protected int maxMessageSize = 2048;
|
||||
|
||||
protected int soReceiveBufferSize = -1;
|
||||
|
||||
protected NetSocketReader reader;
|
||||
|
||||
protected boolean close;
|
||||
|
||||
/**
|
||||
* Constructs a SimpleTcpNetOutboundGateway that sends data to the
|
||||
* specified host and port, and waits for a response.
|
||||
*
|
||||
* @param host The host.
|
||||
* @param port The port.
|
||||
*/
|
||||
public SimpleTcpNetOutboundGateway(String host, int port) {
|
||||
handler = new TcpNetSendingMessageHandler(host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronized to prevent multiplexing requests over the same socket.
|
||||
*/
|
||||
@Override
|
||||
protected synchronized Object handleRequestMessage(Message<?> requestMessage) {
|
||||
this.handler.handleMessage(requestMessage);
|
||||
Socket socket = this.handler.getSocket();
|
||||
if (this.reader == null ||
|
||||
this.reader.getSocket() != socket) { // might have re-opened on error
|
||||
this.reader = SocketIoUtils.createNetReader(this.messageFormat,
|
||||
this.customSocketReaderClass, socket, this.maxMessageSize,
|
||||
this.soReceiveBufferSize);
|
||||
}
|
||||
try {
|
||||
if (this.reader.assembleData() < 0) {
|
||||
throw new IOException("Socket closed");
|
||||
}
|
||||
Object object = this.reader.getAssembledData();
|
||||
if (close) {
|
||||
logger.debug("Closing socket because close=true");
|
||||
this.handler.close();
|
||||
}
|
||||
return object;
|
||||
} catch (Exception e) {
|
||||
this.reader = null;
|
||||
this.handler.close();
|
||||
throw new MessagingException(requestMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#equals(Object)
|
||||
* @return whether the MessageHandler delegate for this Gateway is equal to the provided object
|
||||
*/
|
||||
public boolean equals(Object obj) {
|
||||
return handler.equals(obj);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.springframework.integration.ip.AbstractInternetProtocolSendingMessageHandler#getPort()
|
||||
* @return the port number of the MessageHandler delegate for this Gateway
|
||||
*/
|
||||
public int getPort() {
|
||||
return handler.getPort();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see java.lang.Object#hashCode()
|
||||
* @return hashcode value of the MessageHandler delegate for this Gateway
|
||||
*/
|
||||
public int hashCode() {
|
||||
return handler.hashCode();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customSocketWriterClassName
|
||||
* @throws ClassNotFoundException
|
||||
* @see org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#setCustomSocketWriterClassName(java.lang.String)
|
||||
*/
|
||||
public void setCustomSocketWriterClassName(
|
||||
String customSocketWriterClassName) throws ClassNotFoundException {
|
||||
handler.setCustomSocketWriterClassName(customSocketWriterClassName);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param messageFormat
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpSendingMessageHandler#setMessageFormat(int)
|
||||
*/
|
||||
public void setMessageFormat(int messageFormat) {
|
||||
handler.setMessageFormat(messageFormat);
|
||||
this.messageFormat = messageFormat;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param soKeepAlive
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpSendingMessageHandler#setSoKeepAlive(boolean)
|
||||
*/
|
||||
public void setSoKeepAlive(boolean soKeepAlive) {
|
||||
handler.setSoKeepAlive(soKeepAlive);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param soLinger
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpSendingMessageHandler#setSoLinger(int)
|
||||
*/
|
||||
public void setSoLinger(int soLinger) {
|
||||
handler.setSoLinger(soLinger);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param size
|
||||
* @see org.springframework.integration.ip.AbstractInternetProtocolSendingMessageHandler#setSoReceiveBufferSize(int)
|
||||
*/
|
||||
public void setSoReceiveBufferSize(int size) {
|
||||
this.soReceiveBufferSize = size;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param size
|
||||
* @see org.springframework.integration.ip.AbstractInternetProtocolSendingMessageHandler#setSoSendBufferSize(int)
|
||||
*/
|
||||
public void setSoSendBufferSize(int size) {
|
||||
handler.setSoSendBufferSize(size);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param soTcpNoDelay
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpSendingMessageHandler#setSoTcpNoDelay(boolean)
|
||||
*/
|
||||
public void setSoTcpNoDelay(boolean soTcpNoDelay) {
|
||||
handler.setSoTcpNoDelay(soTcpNoDelay);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param timeout
|
||||
* @see org.springframework.integration.ip.AbstractInternetProtocolSendingMessageHandler#setSoTimeout(int)
|
||||
*/
|
||||
public void setSoTimeout(int timeout) {
|
||||
handler.setSoTimeout(timeout);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param soTrafficClass
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpSendingMessageHandler#setSoTrafficClass(int)
|
||||
*/
|
||||
public void setSoTrafficClass(int soTrafficClass) {
|
||||
handler.setSoTrafficClass(soTrafficClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customSocketReaderClassName the {@link NetSocketReader} class to use
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomSocketReaderClassName(
|
||||
String customSocketReaderClassName) throws ClassNotFoundException {
|
||||
if (customSocketReaderClassName != null) {
|
||||
this.customSocketReaderClass = (Class<NetSocketReader>) Class
|
||||
.forName(customSocketReaderClassName);
|
||||
if (!(NetSocketReader.class.isAssignableFrom(this.customSocketReaderClass))) {
|
||||
throw new IllegalArgumentException("Custom socket reader must be of type NetSocketReader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the Spring Integration reply channel. If this property is not
|
||||
* set the gateway will check for a 'replyChannel' header on the request.
|
||||
*/
|
||||
public void setReplyChannel(MessageChannel replyChannel) {
|
||||
this.setOutputChannel(replyChannel);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param close the close to set
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,13 +15,8 @@
|
||||
*/
|
||||
package org.springframework.integration.ip.tcp;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -29,100 +24,6 @@ import org.springframework.integration.mapping.MessageMappingException;
|
||||
*/
|
||||
public class SocketIoUtils {
|
||||
|
||||
public static NetSocketReader createNetReader(int messageFormat,
|
||||
Class<NetSocketReader> customSocketReaderClass,
|
||||
Socket socket,
|
||||
int receiveBufferSize,
|
||||
int soReceiveBufferSize) {
|
||||
NetSocketReader reader;
|
||||
if (messageFormat == MessageFormats.FORMAT_CUSTOM) {
|
||||
try {
|
||||
Constructor<NetSocketReader> ctor =
|
||||
customSocketReaderClass.getConstructor(Socket.class);
|
||||
reader = BeanUtils.instantiateClass(ctor, socket);
|
||||
if (soReceiveBufferSize > 0) {
|
||||
socket.setReceiveBufferSize(soReceiveBufferSize);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessageMappingException("Failed to instantiate custom reader", e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
reader = new NetSocketReader(socket);
|
||||
}
|
||||
reader.setMessageFormat(messageFormat);
|
||||
reader.setMaxMessageSize(receiveBufferSize);
|
||||
return reader;
|
||||
}
|
||||
|
||||
public static NetSocketWriter createNetWriter(int messageFormat,
|
||||
Class<NetSocketWriter> customSocketWriterClass, Socket socket) {
|
||||
NetSocketWriter writer;
|
||||
if (messageFormat == MessageFormats.FORMAT_CUSTOM){
|
||||
try {
|
||||
Constructor<NetSocketWriter> ctor = customSocketWriterClass.getConstructor(Socket.class);
|
||||
writer = BeanUtils.instantiateClass(ctor, socket);
|
||||
} catch (Exception e) {
|
||||
throw new MessageMappingException("Failed to instantiate custom writer", e);
|
||||
}
|
||||
} else {
|
||||
writer = new NetSocketWriter(socket);
|
||||
}
|
||||
writer.setMessageFormat(messageFormat);
|
||||
return writer;
|
||||
}
|
||||
|
||||
public static NioSocketReader createNioReader(int messageFormat,
|
||||
Class<NioSocketReader> customSocketReaderClass,
|
||||
SocketChannel channel,
|
||||
int receiveBufferSize,
|
||||
int soReceiveBufferSize,
|
||||
boolean usingDirectBuffers ) {
|
||||
NioSocketReader reader;
|
||||
if (messageFormat == MessageFormats.FORMAT_CUSTOM) {
|
||||
try {
|
||||
Constructor<NioSocketReader> ctor =
|
||||
customSocketReaderClass.getConstructor(SocketChannel.class);
|
||||
reader = BeanUtils.instantiateClass(ctor, channel);
|
||||
if (soReceiveBufferSize > 0) {
|
||||
channel.socket().setReceiveBufferSize(soReceiveBufferSize);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new MessageMappingException("Failed to instantiate custom reader", e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
reader = new NioSocketReader(channel);
|
||||
}
|
||||
reader.setMessageFormat(messageFormat);
|
||||
reader.setMaxMessageSize(receiveBufferSize);
|
||||
reader.setUsingDirectBuffers(usingDirectBuffers);
|
||||
return reader;
|
||||
}
|
||||
|
||||
public static NioSocketWriter createNioWriter(int messageFormat,
|
||||
Class<NioSocketWriter> customSocketWriterClass,
|
||||
SocketChannel channel,
|
||||
int maxBuffers,
|
||||
int sendBufferSize,
|
||||
boolean usingDirectBuffers) {
|
||||
NioSocketWriter writer;
|
||||
if (messageFormat == MessageFormats.FORMAT_CUSTOM){
|
||||
try {
|
||||
Constructor<NioSocketWriter> ctor = customSocketWriterClass
|
||||
.getConstructor(SocketChannel.class, int.class, int.class);
|
||||
writer = BeanUtils.instantiateClass(ctor, channel, maxBuffers, sendBufferSize);
|
||||
} catch (Exception e) {
|
||||
throw new MessageMappingException("Failed to instantiate custom writer", e);
|
||||
}
|
||||
} else {
|
||||
writer = new NioSocketWriter(channel, maxBuffers, sendBufferSize);
|
||||
}
|
||||
writer.setMessageFormat(messageFormat);
|
||||
writer.setUsingDirectBuffers(usingDirectBuffers);
|
||||
return writer;
|
||||
}
|
||||
|
||||
public static String getSocketId(Socket socket) {
|
||||
InetAddress inetAddress = socket.getInetAddress();
|
||||
String hostName = "";
|
||||
|
||||
@@ -1,120 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageHandlingException;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.IpHeaders;
|
||||
import org.springframework.integration.mapping.InboundMessageMapper;
|
||||
import org.springframework.integration.mapping.OutboundMessageMapper;
|
||||
|
||||
/**
|
||||
* Maps incoming data from a {@link SocketReader} to a {@link Message} and from
|
||||
* a Message to outgoing data forwarded to a {@link SocketWriter}.
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class SocketMessageMapper implements
|
||||
InboundMessageMapper<SocketReader>,
|
||||
OutboundMessageMapper<Object> {
|
||||
|
||||
private volatile String charset = "UTF-8";
|
||||
|
||||
private volatile int messageFormat;
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.message.InboundMessageMapper#toMessage(java.lang.Object)
|
||||
*/
|
||||
public Message<Object> toMessage(SocketReader socketReader) throws Exception {
|
||||
return fromRaw(socketReader);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Calls {@link SocketReader#getAssembledData()} and creates a message with
|
||||
* the socket data (excluding any protocol parts) as the payload. The source
|
||||
* hostname and ip address are added to the message headers.
|
||||
* @param socketReader
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private Message<Object> fromRaw(SocketReader socketReader) throws IOException {
|
||||
Object payload = socketReader.getAssembledData();
|
||||
Message<Object> message = null;
|
||||
if (payload != null) {
|
||||
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;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.message.OutboundMessageMapper#fromMessage(org.springframework.integration.core.Message)
|
||||
*/
|
||||
public Object fromMessage(Message<?> message) throws Exception {
|
||||
if (this.messageFormat < MessageFormats.FORMAT_IMPLICIT) {
|
||||
return getPayloadAsBytes(message);
|
||||
}
|
||||
return message.getPayload();
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the payload as a byte array.
|
||||
* @param message
|
||||
* @return
|
||||
*/
|
||||
private byte[] getPayloadAsBytes(Message<?> message) {
|
||||
byte[] bytes = null;
|
||||
Object payload = message.getPayload();
|
||||
if (payload instanceof byte[]) {
|
||||
bytes = (byte[]) payload;
|
||||
}
|
||||
else if (payload instanceof String) {
|
||||
try {
|
||||
bytes = ((String) payload).getBytes(this.charset);
|
||||
}
|
||||
catch (UnsupportedEncodingException e) {
|
||||
throw new MessageHandlingException(message, e);
|
||||
}
|
||||
}
|
||||
else {
|
||||
throw new MessageHandlingException(message, "The socket mapper expects " +
|
||||
"either a byte array or String payload, but received: " + payload.getClass());
|
||||
}
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @param charset the charset to set
|
||||
*/
|
||||
public void setCharset(String charset) {
|
||||
this.charset = charset;
|
||||
}
|
||||
|
||||
|
||||
public void setMessageFormat(int messageFormat) {
|
||||
this.messageFormat = messageFormat;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* General interface for assembling message data from a TCP/IP Socket.
|
||||
* Implementations for {@link java.net.Socket} and {@link java.nio.channels.SocketChannel}
|
||||
* are provided.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public interface SocketReader {
|
||||
|
||||
public static int SOCKET_CLOSED = -1;
|
||||
|
||||
public static int MESSAGE_INCOMPLETE = 0;
|
||||
|
||||
public static int MESSAGE_COMPLETE = 1;
|
||||
|
||||
/**
|
||||
* Reads the data the socket and assembles
|
||||
* packets of data into a complete message, depending on the format of that
|
||||
* data.
|
||||
* @return MESSAGE_COMPLETE when message is assembled, otherwise MESSAGE_IMCOMPLETE, or
|
||||
* < 0 if socket closed before any data for a message is received.
|
||||
* @throws IOException
|
||||
*/
|
||||
public int assembleData() throws IOException;
|
||||
|
||||
/**
|
||||
* Retrieves the assembled tcp data or null if the data is not
|
||||
* yet assembled. Once this method is called, the assembled data is
|
||||
* again null until a new assembly is completed.
|
||||
* @return The assembled data or null.
|
||||
*/
|
||||
public Object getAssembledData();
|
||||
|
||||
/**
|
||||
* Returns the InetAddress of the underlying socket.
|
||||
* @return The InetAddress.
|
||||
*/
|
||||
public InetAddress getAddress();
|
||||
|
||||
/**
|
||||
* @return the Socket
|
||||
*/
|
||||
public Socket getSocket();
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
|
||||
|
||||
/**
|
||||
* A general interface for writing to sockets.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public interface SocketWriter {
|
||||
|
||||
/**
|
||||
* Write the entire buffer to the underlying socket. Appropriate wire
|
||||
* protocols will be implemented so the receiving side can decode and
|
||||
* reassemble the message, if packetized by the network.
|
||||
* @param object The object to write.
|
||||
* @throws IOException
|
||||
*/
|
||||
void write(Object object) throws IOException;
|
||||
|
||||
/**
|
||||
* @param messageFormat the messageFormat to set
|
||||
*/
|
||||
public void setMessageFormat(int messageFormat);
|
||||
|
||||
}
|
||||
@@ -1,167 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
|
||||
/**
|
||||
* Tcp Receiving Channel adapter that uses a {@link Socket}. Each
|
||||
* connected socket uses a dedicated thread so the pool size must be set
|
||||
* accordingly.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class TcpNetReceivingChannelAdapter extends
|
||||
AbstractTcpReceivingChannelAdapter {
|
||||
|
||||
protected ServerSocket serverSocket;
|
||||
|
||||
protected Class<NetSocketReader> customSocketReaderClass;
|
||||
/**
|
||||
* Constructs a TcpNetReceivingChannelAdapter that listens on the provided port.
|
||||
* @param port the port on which to listen
|
||||
*/
|
||||
public TcpNetReceivingChannelAdapter(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the server socket, listens for incoming connections and schedules
|
||||
* execution of the {@link #handleSocket(Socket)} method for each new
|
||||
* connection.
|
||||
*
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpReceivingChannelAdapter#server()
|
||||
*/
|
||||
@Override
|
||||
protected void server() {
|
||||
while (this.active) {
|
||||
try {
|
||||
if (this.localAddress == null) {
|
||||
this.serverSocket = ServerSocketFactory.getDefault()
|
||||
.createServerSocket(this.port, Math.abs(this.poolSize));
|
||||
} else {
|
||||
InetAddress whichNic = InetAddress.getByName(this.localAddress);
|
||||
this.serverSocket = ServerSocketFactory.getDefault()
|
||||
.createServerSocket(port, Math.abs(poolSize), whichNic);
|
||||
}
|
||||
this.listening = true;
|
||||
while (true) {
|
||||
final Socket socket = serverSocket.accept();
|
||||
setSocketOptions(socket);
|
||||
this.taskExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
handleSocket(socket);
|
||||
}});
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (this.serverSocket != null) {
|
||||
try {
|
||||
this.serverSocket.close();
|
||||
} catch (IOException e1) {}
|
||||
}
|
||||
this.listening = false;
|
||||
this.serverSocket = null;
|
||||
if (this.active) {
|
||||
logger.error("Error on ServerSocket", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a {@link NetSocketReader} and calls its {@link NetSocketReader#assembledData}
|
||||
* method repeatedly; for each assembled message, calls {@link #sendMessage(Message)} with
|
||||
* the mapped message.
|
||||
*/
|
||||
protected void handleSocket(Socket socket) {
|
||||
NetSocketReader reader = SocketIoUtils.createNetReader(messageFormat,
|
||||
customSocketReaderClass, socket, this.receiveBufferSize,
|
||||
this.soReceiveBufferSize);
|
||||
while (true) {
|
||||
try {
|
||||
int messageStatus = reader.assembleData();
|
||||
if (messageStatus < 0) {
|
||||
return;
|
||||
}
|
||||
if (messageStatus == SocketReader.MESSAGE_COMPLETE) {
|
||||
if (close) {
|
||||
logger.debug("Closing socket because close=true");
|
||||
try {
|
||||
reader.getSocket().close();
|
||||
} catch (IOException ioe) {
|
||||
logger.error("Error on close", ioe);
|
||||
}
|
||||
}
|
||||
processMessage(reader);
|
||||
if (close) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("processMessage failed", e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMessage(NetSocketReader reader)
|
||||
throws Exception {
|
||||
Message<Object> message = mapper.toMessage(reader);
|
||||
if (message != null) {
|
||||
sendMessage(message);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
super.doStop();
|
||||
try {
|
||||
this.serverSocket.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customSocketReaderClassName the {@link NetSocketReader} class to use
|
||||
* @throws ClassNotFoundException if the named class cannot be loaded
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomSocketReaderClassName(
|
||||
String customSocketReaderClassName) throws ClassNotFoundException {
|
||||
if (customSocketReaderClassName != null) {
|
||||
this.customSocketReaderClass = (Class<NetSocketReader>) Class
|
||||
.forName(customSocketReaderClassName);
|
||||
if (!(NetSocketReader.class.isAssignableFrom(this.customSocketReaderClass))) {
|
||||
throw new IllegalArgumentException("Custom socket reader must be of type NetSocketReader");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* 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 javax.net.SocketFactory;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TCP Sending Channel Adapter that that uses a {@link java.net.Socket}.
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class TcpNetSendingMessageHandler extends
|
||||
AbstractTcpSendingMessageHandler {
|
||||
|
||||
protected Class<NetSocketWriter> customSocketWriterClass;
|
||||
|
||||
/**
|
||||
* Constructs a TcpNetSendingMessageHandler that sends data to the
|
||||
* specified host and port.
|
||||
* @param host The host.
|
||||
* @param port The port.
|
||||
*/
|
||||
public TcpNetSendingMessageHandler(String host, int port) {
|
||||
super(host, port);
|
||||
}
|
||||
|
||||
protected volatile Socket socket;
|
||||
|
||||
/**
|
||||
* @return the socket
|
||||
*/
|
||||
protected Socket getSocket() {
|
||||
return socket;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the writer
|
||||
*/
|
||||
protected synchronized SocketWriter getWriter() {
|
||||
if (this.writer == null) {
|
||||
try {
|
||||
logger.debug("Opening new socket connection");
|
||||
this.socket = SocketFactory.getDefault().createSocket(this.host, this.port);
|
||||
this.setSocketAttributes(socket);
|
||||
NetSocketWriter writer = SocketIoUtils.createNetWriter(messageFormat,
|
||||
customSocketWriterClass, socket);
|
||||
this.writer = writer;
|
||||
} catch (Exception e) {
|
||||
logger.error("Error creating SocketWriter", e);
|
||||
}
|
||||
}
|
||||
return this.writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customSocketWriterClassName the customSocketWriterClassName to set
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomSocketWriterClassName(
|
||||
String customSocketWriterClassName) throws ClassNotFoundException {
|
||||
if (customSocketWriterClassName != null) {
|
||||
this.customSocketWriterClass = (Class<NetSocketWriter>) Class
|
||||
.forName(customSocketWriterClassName);
|
||||
if (!(NetSocketWriter.class.isAssignableFrom(this.customSocketWriterClass))) {
|
||||
throw new IllegalArgumentException("Custom socket writer must be of type NetSocketWriter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Close the underlying socket and prepare to establish a new socket on
|
||||
* the next write.
|
||||
*/
|
||||
protected void close() {
|
||||
this.writer.doClose();
|
||||
this.writer = null;
|
||||
}
|
||||
|
||||
public void setLocalAddress(String localAddress) {
|
||||
logger.warn("localAddress not used on tcp outbound endpoints");
|
||||
}
|
||||
}
|
||||
@@ -1,237 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
|
||||
/**
|
||||
* Tcp Receiving Channel adapter that uses a {@link java.nio.channels.SocketChannel}.
|
||||
* Sockets are multiplexed across the pooled threads. More than one thread will
|
||||
* be required with large numbers of connections and incoming traffic. The
|
||||
* number of threads is controlled by the poolSize property.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class TcpNioReceivingChannelAdapter extends
|
||||
AbstractTcpReceivingChannelAdapter {
|
||||
|
||||
protected ServerSocketChannel serverChannel;
|
||||
protected boolean usingDirectBuffers;
|
||||
protected Class<NioSocketReader> customSocketReaderClass;
|
||||
|
||||
/**
|
||||
* Constructs a TcpNioReceivingChannelAdapter to listen on the port.
|
||||
* @param port The port.
|
||||
*/
|
||||
public TcpNioReceivingChannelAdapter(int port) {
|
||||
super(port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Opens a non-blocking {@link ServerSocketChannel}, registers it with a
|
||||
* {@link Selector} and calls {@link #doSelect(ServerSocketChannel, Selector)}.
|
||||
*
|
||||
* @see org.springframework.integration.ip.tcp.AbstractTcpReceivingChannelAdapter#server()
|
||||
*/
|
||||
@Override
|
||||
protected void server() {
|
||||
try {
|
||||
this.serverChannel = ServerSocketChannel.open();
|
||||
this.listening = true;
|
||||
this.serverChannel.configureBlocking(false);
|
||||
if (this.localAddress == null) {
|
||||
this.serverChannel.socket().bind(new InetSocketAddress(this.port),
|
||||
Math.abs(this.poolSize));
|
||||
} else {
|
||||
InetAddress whichNic = InetAddress.getByName(this.localAddress);
|
||||
this.serverChannel.socket().bind(new InetSocketAddress(whichNic, this.port),
|
||||
Math.abs(this.poolSize));
|
||||
}
|
||||
final Selector selector = Selector.open();
|
||||
this.serverChannel.register(selector, SelectionKey.OP_ACCEPT);
|
||||
doSelect(this.serverChannel, selector);
|
||||
|
||||
} catch (IOException e) {
|
||||
try {
|
||||
serverChannel.close();
|
||||
} catch (IOException e1) { }
|
||||
this.listening = false;
|
||||
this.serverChannel = null;
|
||||
if (this.active) {
|
||||
logger.error("Error on ServerSocketChannel", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listens for incoming connections and for notifications that a connected
|
||||
* socket is ready for reading.
|
||||
* Accepts incoming connections, registers the new socket with the
|
||||
* selector for reading.
|
||||
* When a socket is ready for reading, unregisters the read interest and
|
||||
* schedules a call to doRead which reads all available data. When the read
|
||||
* is complete, the socket is again registered for read interest.
|
||||
* @param server
|
||||
* @param selector
|
||||
* @throws IOException
|
||||
* @throws ClosedChannelException
|
||||
* @throws SocketException
|
||||
*/
|
||||
private void doSelect(ServerSocketChannel server, final Selector selector)
|
||||
throws IOException, ClosedChannelException, SocketException {
|
||||
while (active) {
|
||||
int selectionCount = selector.select();
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug("Port " + port + " SelectionCount: " + selectionCount);
|
||||
if (selectionCount > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
SocketChannel channel = null;
|
||||
while (iterator.hasNext()) {
|
||||
final SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isAcceptable()) {
|
||||
channel = server.accept();
|
||||
channel.configureBlocking(false);
|
||||
channel.register(selector, SelectionKey.OP_READ);
|
||||
Socket socket = channel.socket();
|
||||
setSocketOptions(socket);
|
||||
}
|
||||
else if (key.isReadable()) {
|
||||
key.interestOps(key.interestOps() - key.readyOps());
|
||||
if (key.attachment() == null) {
|
||||
NioSocketReader reader = createSocketReader(key);
|
||||
if (reader == null) {
|
||||
continue;
|
||||
}
|
||||
key.attach(reader);
|
||||
}
|
||||
this.taskExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
doRead(key);
|
||||
if (key.channel().isOpen()) {
|
||||
key.interestOps(SelectionKey.OP_READ);
|
||||
selector.wakeup();
|
||||
}
|
||||
}});
|
||||
}
|
||||
else {
|
||||
logger.error("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an NioSocketReader, either directly,or
|
||||
* from the supplied class if {@link MessageFormats#FORMAT_CUSTOM}
|
||||
* is used.
|
||||
* @param key The selection key.
|
||||
* @return The NioSocketReader.
|
||||
*/
|
||||
private NioSocketReader createSocketReader(final SelectionKey key) {
|
||||
SocketChannel channel = (SocketChannel) key.channel();
|
||||
NioSocketReader reader = SocketIoUtils.createNioReader(messageFormat,
|
||||
this.customSocketReaderClass, channel, this.receiveBufferSize,
|
||||
this.receiveBufferSize, this.usingDirectBuffers);
|
||||
return reader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Obtains the {@link NetSocketReader} associated with the channel
|
||||
* and calls its {@link NetSocketReader#assembledData}
|
||||
* method; if a message is fully assembled, calls {@link #sendMessage(Message)} with the
|
||||
* mapped message.
|
||||
*/
|
||||
private void doRead(SelectionKey key) {
|
||||
NioSocketReader reader = (NioSocketReader) key.attachment();
|
||||
try {
|
||||
int messageStatus = reader.assembleData();
|
||||
if (messageStatus < 0) {
|
||||
return;
|
||||
}
|
||||
if (messageStatus == SocketReader.MESSAGE_COMPLETE) {
|
||||
if (close) {
|
||||
logger.debug("Closing channel because close=true");
|
||||
try {
|
||||
key.channel().close();
|
||||
} catch (IOException ioe) {
|
||||
logger.error("Error on close", ioe);
|
||||
}
|
||||
}
|
||||
Message<Object> message;
|
||||
message = mapper.toMessage(reader);
|
||||
if (message != null) {
|
||||
sendMessage(message);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Failure on read or message send", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doStop() {
|
||||
super.doStop();
|
||||
try {
|
||||
this.serverChannel.close();
|
||||
}
|
||||
catch (Exception e) {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param usingDirectBuffers Set true if you wish to use direct buffers
|
||||
* for NIO operations.
|
||||
*/
|
||||
public void setUsingDirectBuffers(boolean usingDirectBuffers) {
|
||||
this.usingDirectBuffers = usingDirectBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customSocketReaderClassName the customSocketReaderClassName to set
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomSocketReaderClassName(String customSocketReaderClassName)
|
||||
throws ClassNotFoundException {
|
||||
this.customSocketReaderClass = (Class<NioSocketReader>) Class
|
||||
.forName(customSocketReaderClassName);
|
||||
if (!(NioSocketReader.class.isAssignableFrom(this.customSocketReaderClass))) {
|
||||
throw new IllegalArgumentException("Custom socket reader must be of type NioSocketReader");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,107 +0,0 @@
|
||||
/*
|
||||
* 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.nio.channels.SocketChannel;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* TCP Sending Channel Adapter that that uses a {@link java.nio.channels.SocketChannel}.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class TcpNioSendingMessageHandler extends
|
||||
AbstractTcpSendingMessageHandler {
|
||||
|
||||
protected volatile SocketChannel socketChannel;
|
||||
|
||||
protected boolean usingDirectBuffers;
|
||||
|
||||
protected Class<NioSocketWriter> customSocketWriterClass;
|
||||
|
||||
protected int buffsPerConnection = 5;
|
||||
|
||||
/**
|
||||
* @param host
|
||||
* @param port
|
||||
*/
|
||||
public TcpNioSendingMessageHandler(String host, int port) {
|
||||
super(host, port);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the socket
|
||||
*/
|
||||
protected synchronized SocketWriter getWriter() {
|
||||
if (this.socketChannel == null) {
|
||||
try {
|
||||
logger.debug("Creating new SocketChannel");
|
||||
this.socketChannel = SocketChannel.open(this.destinationAddress);
|
||||
this.setSocketAttributes(socketChannel.socket());
|
||||
NioSocketWriter writer = SocketIoUtils.createNioWriter(messageFormat,
|
||||
customSocketWriterClass, socketChannel,
|
||||
buffsPerConnection, soSendBufferSize, usingDirectBuffers);
|
||||
this.writer = writer;
|
||||
} catch (Exception e) {
|
||||
logger.error("Error creating SocketWriter", e);
|
||||
}
|
||||
}
|
||||
return this.writer;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param usingDirectBuffers Set true if you wish to use direct buffers
|
||||
* for NIO operations.
|
||||
*/
|
||||
public void setUsingDirectBuffers(boolean usingDirectBuffers) {
|
||||
this.usingDirectBuffers = usingDirectBuffers;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param customSocketWriterClassName the customSocketWriterClassName to set
|
||||
* @throws ClassNotFoundException
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public void setCustomSocketWriterClassName(
|
||||
String customSocketWriterClassName) throws ClassNotFoundException {
|
||||
if (customSocketWriterClassName != null) {
|
||||
this.customSocketWriterClass = (Class<NioSocketWriter>) Class
|
||||
.forName(customSocketWriterClassName);
|
||||
if (!(NioSocketWriter.class.isAssignableFrom(this.customSocketWriterClass))) {
|
||||
throw new IllegalArgumentException("Custom socket writer must be of type NioSocketWriter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If direct buffers are being used, sets the max number of
|
||||
* buffers allowed per connection. Defaults to 5. It is unlikely
|
||||
* this would ever need to be changed. Each buffer is set at the
|
||||
* soSendBufferSize or, if not set, 2048 bytes.
|
||||
*
|
||||
* @param buffsPerConnection the buffsPerConnection to set
|
||||
*/
|
||||
public void setBuffsPerConnection(int buffsPerConnection) {
|
||||
this.buffsPerConnection = buffsPerConnection;
|
||||
}
|
||||
|
||||
public void setLocalAddress(String localAddress) {
|
||||
logger.warn("localAddress not used on tcp outbound endpoints");
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessageTimeoutException;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.core.MessageChannel;
|
||||
import org.springframework.integration.handler.AbstractReplyProducingMessageHandler;
|
||||
import org.springframework.integration.ip.IpHeaders;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
|
||||
@@ -93,6 +94,7 @@ public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler
|
||||
if (e instanceof MessagingException) {
|
||||
throw (MessagingException) e;
|
||||
}
|
||||
logger.error("Tcp Gateway exception", e);
|
||||
throw new MessagingException("Failed to send or receive", e);
|
||||
} finally {
|
||||
if (haveSemaphore) {
|
||||
@@ -180,4 +182,11 @@ public class TcpOutboundGateway extends AbstractReplyProducingMessageHandler
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Specify the Spring Integration reply channel. If this property is not
|
||||
* set the gateway will check for a 'replyChannel' header on the request.
|
||||
*/
|
||||
public void setReplyChannel(MessageChannel replyChannel) {
|
||||
this.setOutputChannel(replyChannel);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,8 +40,6 @@ public class TcpReceivingChannelAdapter
|
||||
|
||||
protected ServerSocket serverSocket;
|
||||
|
||||
protected Class<NetSocketReader> customSocketReaderClass;
|
||||
|
||||
protected ConnectionFactory clientConnectionFactory;
|
||||
|
||||
protected ConnectionFactory serverConnectionFactory;
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.commons.serializer.InputStreamingConverter;
|
||||
import org.springframework.commons.serializer.OutputStreamingConverter;
|
||||
import org.springframework.context.Lifecycle;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayCrLfConverter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -37,7 +37,7 @@ import org.springframework.util.Assert;
|
||||
*
|
||||
*/
|
||||
public abstract class AbstractConnectionFactory
|
||||
implements ConnectionFactory, Runnable, Lifecycle {
|
||||
implements ConnectionFactory, Runnable, SmartLifecycle {
|
||||
|
||||
protected Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
@@ -341,6 +341,17 @@ public abstract class AbstractConnectionFactory
|
||||
return connection;
|
||||
}
|
||||
|
||||
|
||||
public int getPhase() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public boolean isAutoStartup() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void stop(Runnable callback) {
|
||||
stop();
|
||||
callback.run();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.io.IOException;
|
||||
import java.net.InetAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
@@ -50,6 +51,7 @@ public class TcpNetServerConnectionFactory extends AbstractServerConnectionFacto
|
||||
* I/O errors on the server socket/channel are logged and the factory is stopped.
|
||||
*/
|
||||
public void run() {
|
||||
ServerSocket theServerSocket = null;
|
||||
if (this.listener == null) {
|
||||
logger.info("No listener bound to server connection factory; will not read; exiting...");
|
||||
return;
|
||||
@@ -63,6 +65,7 @@ public class TcpNetServerConnectionFactory extends AbstractServerConnectionFacto
|
||||
this.serverSocket = ServerSocketFactory.getDefault()
|
||||
.createServerSocket(port, Math.abs(poolSize), whichNic);
|
||||
}
|
||||
theServerSocket = this.serverSocket;
|
||||
this.listening = true;
|
||||
logger.info("Listening on port " + this.port);
|
||||
while (true) {
|
||||
@@ -76,7 +79,10 @@ public class TcpNetServerConnectionFactory extends AbstractServerConnectionFacto
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.listening = false;
|
||||
if (this.active) {
|
||||
// don't log an error if we had a good socket once and now it's closed
|
||||
if (e instanceof SocketException && theServerSocket != null) {
|
||||
logger.warn("Server Socket closed");
|
||||
} else if (this.active) {
|
||||
logger.error("Error on ServerSocket", e);
|
||||
}
|
||||
this.active = false;
|
||||
|
||||
@@ -46,6 +46,7 @@ public class TcpNioClientConnectionFactory extends
|
||||
protected Map<SocketChannel, TcpNioConnection> connections = new ConcurrentHashMap<SocketChannel, TcpNioConnection>();
|
||||
|
||||
protected BlockingQueue<SocketChannel> newChannels = new LinkedBlockingQueue<SocketChannel>();
|
||||
|
||||
|
||||
/**
|
||||
* Creates a TcpNioClientConnectionFactory for connections to the host and port.
|
||||
|
||||
@@ -27,6 +27,7 @@ import java.nio.channels.Selector;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.ip.tcp.SocketIoUtils;
|
||||
@@ -60,6 +61,8 @@ public class TcpNioConnection extends AbstractTcpConnection {
|
||||
private boolean active = true;
|
||||
|
||||
private long lastRead;
|
||||
|
||||
private AtomicInteger executionControl = new AtomicInteger();
|
||||
|
||||
/**
|
||||
* Constructs a TcpNetConnection for the SocketChannel.
|
||||
@@ -151,15 +154,20 @@ public class TcpNioConnection extends AbstractTcpConnection {
|
||||
logger.debug("TcpListener exiting - no listener and not single use");
|
||||
return;
|
||||
}
|
||||
if (active) {
|
||||
while (active) {
|
||||
try {
|
||||
while (pipedInputStream.available() > 0) {
|
||||
while (this.socketChannel.isOpen() &&
|
||||
this.pipedInputStream.available() > 0) {
|
||||
convertAndSend();
|
||||
}
|
||||
} catch (IOException e) {
|
||||
logger.error("Unexpected exception, exiting...", e);
|
||||
return;
|
||||
}
|
||||
// currently no more work to do
|
||||
if (this.executionControl.decrementAndGet() < 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
logger.debug("Nio message assembler exiting...");
|
||||
@@ -167,7 +175,7 @@ public class TcpNioConnection extends AbstractTcpConnection {
|
||||
}
|
||||
|
||||
private synchronized void convertAndSend() throws IOException {
|
||||
if (this.pipedInputStream.available() <= 0) {
|
||||
if (!this.socketChannel.isOpen() || this.pipedInputStream.available() <= 0) {
|
||||
return;
|
||||
}
|
||||
Message<?> message = null;
|
||||
@@ -236,10 +244,12 @@ public class TcpNioConnection extends AbstractTcpConnection {
|
||||
pipedOutputStream.write(rawBuffer.array(), 0, rawBuffer.limit());
|
||||
pipedOutputStream.flush();
|
||||
|
||||
if (!socketChannel.isBlocking()) {
|
||||
if (this.taskExecutor == null) {
|
||||
this.taskExecutor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
if (this.taskExecutor == null) {
|
||||
this.taskExecutor = Executors.newSingleThreadExecutor();
|
||||
}
|
||||
if (this.executionControl.incrementAndGet() <= 1) {
|
||||
// only execute run() if we don't already have one running
|
||||
this.executionControl.set(1);
|
||||
this.taskExecutor.execute(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,6 +70,7 @@ public class TcpNioServerConnectionFactory extends AbstractServerConnectionFacto
|
||||
try {
|
||||
this.serverChannel = ServerSocketChannel.open();
|
||||
this.listening = true;
|
||||
logger.info("Listening on port " + this.port);
|
||||
this.serverChannel.configureBlocking(false);
|
||||
if (this.localAddress == null) {
|
||||
this.serverChannel.socket().bind(new InetSocketAddress(this.port),
|
||||
@@ -144,11 +145,13 @@ public class TcpNioServerConnectionFactory extends AbstractServerConnectionFacto
|
||||
logger.debug("Selection key no longer valid");
|
||||
}
|
||||
else if (key.isAcceptable()) {
|
||||
logger.debug("New accept");
|
||||
channel = server.accept();
|
||||
channel.configureBlocking(false);
|
||||
Socket socket = channel.socket();
|
||||
setSocketAttributes(socket);
|
||||
TcpNioConnection connection = createTcpNioConnection(channel);
|
||||
connection.setTaskExecutor(this.taskExecutor);
|
||||
connection.setLastRead(now);
|
||||
connections.put(channel, connection);
|
||||
channel.register(selector, SelectionKey.OP_READ, connection);
|
||||
|
||||
@@ -19,15 +19,15 @@
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
<xsd:element name="inbound-channel-adapter">
|
||||
<xsd:element name="udp-inbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an inbound Channel Adapter for receiving incoming IP packets.
|
||||
Defines a udp inbound Channel Adapter for receiving incoming udp packets.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="ipAdapterType">
|
||||
<xsd:extension base="udpAdapterType">
|
||||
<xsd:attribute name="pool-size" type="xsd:string" >
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -39,23 +39,6 @@ its configuration specifies the number of threads.
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="receive-buffer-size" type="xsd:string" />
|
||||
<xsd:attribute name="multicast-address" type="xsd:string" />
|
||||
<xsd:attribute name="custom-socket-reader-class-name" type="xsd:string" >
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="close" type="xsd:string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
If true, the socket will be closed after a message is received and sent to the
|
||||
outbound channel. If false, the socket will remain open ready to receive the
|
||||
next message.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="task-executor" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -70,15 +53,15 @@ next message.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-channel-adapter">
|
||||
<xsd:element name="udp-outbound-channel-adapter">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound IP packet-sending Channel Adapter.
|
||||
Defines an outbound UDP packet-sending Channel Adapter.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="ipAdapterType">
|
||||
<xsd:extension base="udpAdapterType">
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="acknowledge" type="xsd:string" />
|
||||
<xsd:attribute name="ack-host" type="xsd:string" />
|
||||
@@ -86,17 +69,6 @@ next message.
|
||||
<xsd:attribute name="ack-timeout" type="xsd:string" />
|
||||
<xsd:attribute name="min-acks-for-success" type="xsd:string" />
|
||||
<xsd:attribute name="time-to-live" type="xsd:string" />
|
||||
<xsd:attribute name="custom-socket-writer-class-name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="so-linger" type="xsd:string" />
|
||||
<xsd:attribute name="so-tcp-no-delay" type="xsd:string" />
|
||||
<xsd:attribute name="so-traffic-class" type="xsd:string" />
|
||||
<xsd:attribute name="task-executor" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
@@ -111,115 +83,6 @@ task executors such as a WorkManagerTaskExecutor.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="inbound-gateway">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an inbound Gateway for receiving and replying to incoming tcp messages.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="gatewayType">
|
||||
<xsd:attribute name="pool-size" type="xsd:string" >
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
The number of threads that will be used for socket/channel handling. Only applies
|
||||
if an external task-executor is NOT being used. When using an external task executor,
|
||||
its configuration specifies the number of threads.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="custom-socket-reader-class-name" type="xsd:string" >
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="custom-socket-writer-class-name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="task-executor" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specifies a specific Executor to be used for socket handling. If not supplied, an internal
|
||||
pooled executor will be used (See pool-size). Needed on some platforms that require the use of specific
|
||||
task executors such as a WorkManagerTaskExecutor.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="outbound-gateway">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines an outbound Gateway for sending and receiving responses over TCP.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="gatewayType">
|
||||
<xsd:attribute name="host" type="xsd:string" />
|
||||
<xsd:attribute name="custom-socket-reader-class-name" type="xsd:string" >
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="custom-socket-writer-class-name" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
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.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="tcp-outbound-channel-adapter">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
<xsd:attribute name="connection-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ip.tcp.connection.ConnectionFactory"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
A connection factory is needed by an outbound adapter. If the connection factory has a type 'client',
|
||||
the factory is 'owned' by this adapter. If it has a type 'server', it is owned by an inbound channel
|
||||
adapter and this adapter will attempt to correlate messages to the connection on which an original
|
||||
inbound message was received.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="tcp-inbound-channel-adapter">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
@@ -250,6 +113,111 @@ adapter.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="tcp-outbound-channel-adapter">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
<xsd:attribute name="connection-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ip.tcp.connection.ConnectionFactory"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
A connection factory is needed by an outbound adapter. If the connection factory has a type 'client',
|
||||
the factory is 'owned' by this adapter. If it has a type 'server', it is owned by an inbound channel
|
||||
adapter and this adapter will attempt to correlate messages to the connection on which an original
|
||||
inbound message was received.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="tcp-inbound-gateway">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
<xsd:attribute name="connection-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
A connection factory is needed by an inbound adapter. The connection factory must be of type 'server'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-channel" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="tcp-outbound-gateway">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
<xsd:attribute name="connection-factory" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.ip.tcp.connection.ConnectionFactory"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
<xsd:documentation>
|
||||
A connection factory is needed by an outbound adapter. The connection factory must be of 'client'.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-channel" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-timeout" type="xsd:string"/>
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string"/>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="tcp-connection-factory">
|
||||
<xsd:complexType>
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
@@ -384,10 +352,10 @@ its configuration specifies the number of threads.
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="ipAdapterType">
|
||||
<xsd:complexType name="udpAdapterType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Common configuration for IP-based adapters.
|
||||
Common configuration for UDP-based adapters.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
@@ -401,87 +369,18 @@ its configuration specifies the number of threads.
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="protocol" use="required">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="tcp" />
|
||||
<xsd:enumeration value="udp" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="using-nio" type="xsd:string" />
|
||||
<xsd:attribute name="using-direct-buffers" type="xsd:string" />
|
||||
<xsd:attribute name="check-length" type="xsd:string" />
|
||||
<xsd:attribute name="multicast" type="xsd:string" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="gatewayType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Defines common configuration for gateway adapters.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="common-attributes">
|
||||
<xsd:attribute name="name" type="xsd:string"/>
|
||||
<xsd:attribute name="request-channel" type="xsd:string" use="required">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="reply-channel" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:expected-type type="org.springframework.integration.core.MessageChannel"/>
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="request-timeout" type="xsd:string"/>
|
||||
<xsd:attribute name="reply-timeout" type="xsd:string"/>
|
||||
<xsd:attribute name="auto-startup" type="xsd:string" default="true"/>
|
||||
<xsd:attribute name="receive-buffer-size" type="xsd:string" />
|
||||
<xsd:attribute name="close" type="xsd:string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
If true, for an outbound gateway, the socket will be closed after a response
|
||||
is received and sent to the
|
||||
reply channel. If false, the socket will remain open and be used to send the
|
||||
next message. If true, for an inbound gateway, the socket will be closed after
|
||||
the response is sent. If false, the socket will remain open and be used to
|
||||
receive the next message.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="common-attributes">
|
||||
<xsd:attribute name="id" type="xsd:ID"/>
|
||||
<xsd:attribute name="port" type="xsd:string" />
|
||||
<xsd:attribute name="so-receive-buffer-size" type="xsd:string" />
|
||||
<xsd:attribute name="so-send-buffer-size" type="xsd:string" />
|
||||
<xsd:attribute name="so-timeout" type="xsd:string" />
|
||||
<xsd:attribute name="message-format">
|
||||
<xsd:simpleType>
|
||||
<xsd:restriction base="xsd:NMTOKEN">
|
||||
<xsd:enumeration value="length-header" />
|
||||
<xsd:enumeration value="stx-etx" />
|
||||
<xsd:enumeration value="crlf" />
|
||||
<xsd:enumeration value="serialized" />
|
||||
<xsd:enumeration value="custom" />
|
||||
</xsd:restriction>
|
||||
</xsd:simpleType>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="so-keep-alive" type="xsd:string" />
|
||||
<xsd:attribute name="local-address" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
|
||||
@@ -1,269 +0,0 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.tcp.TcpNetReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler;
|
||||
import org.springframework.integration.ip.tcp.TcpNioReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler;
|
||||
import org.springframework.integration.ip.udp.UnicastReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration(locations={"inboundAdapters.xml"
|
||||
,"outboundAdapters.xml"
|
||||
})
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class IpChannelAdapterParserTests
|
||||
// implements ApplicationContextAware
|
||||
{
|
||||
|
||||
@Autowired
|
||||
QueueChannel channel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="tcp1")
|
||||
TcpNioReceivingChannelAdapter tcp1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="tcp2")
|
||||
TcpNioReceivingChannelAdapter tcp2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="tcp3")
|
||||
TcpNetReceivingChannelAdapter tcp3;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="tcp4")
|
||||
TcpNetReceivingChannelAdapter tcp4;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="tcp5")
|
||||
TcpNetReceivingChannelAdapter tcp5;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="tcp6")
|
||||
TcpNetReceivingChannelAdapter tcp6;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="udp1")
|
||||
UnicastReceivingChannelAdapter udp1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler#0")
|
||||
TcpNioSendingMessageHandler tcpOut1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler#1")
|
||||
TcpNioSendingMessageHandler tcpOut2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#0")
|
||||
TcpNetSendingMessageHandler tcpOut3;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#1")
|
||||
TcpNetSendingMessageHandler tcpOut4;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#2")
|
||||
TcpNetSendingMessageHandler tcpOut5;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#3")
|
||||
TcpNetSendingMessageHandler tcpOut6;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpInbound1() {
|
||||
SocketUtils.testSendFragmented(tcp1.getPort(), true);
|
||||
Message<byte[]> message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("xx", new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpInbound2() {
|
||||
SocketUtils.testSendFragmented(tcp2.getPort(), true);
|
||||
Message<byte[]> message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("xx", new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpInbound3() {
|
||||
SocketUtils.testSendFragmented(tcp3.getPort(), true);
|
||||
Message<byte[]> message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("xx", new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpInbound4() {
|
||||
SocketUtils.testSendStxEtx(tcp4.getPort(), null);
|
||||
Message<byte[]> message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING, new String(message.getPayload()));
|
||||
message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING, new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpInbound5() {
|
||||
SocketUtils.testSendCrLf(tcp5.getPort(), null);
|
||||
Message<byte[]> message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING, new String(message.getPayload()));
|
||||
message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING, new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpInbound6() {
|
||||
SocketUtils.testSendStxEtx(tcp6.getPort(), null);
|
||||
Message<byte[]> message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("\u0002" + SocketUtils.TEST_STRING + SocketUtils.TEST_STRING + "\u0003",
|
||||
new String(message.getPayload()));
|
||||
message = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("\u0002" + SocketUtils.TEST_STRING + SocketUtils.TEST_STRING + "\u0003",
|
||||
new String(message.getPayload()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUdpInbound1() {
|
||||
assertNotNull(udp1);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound1() {
|
||||
Message<String> message = MessageBuilder.withPayload("TESTING").build();
|
||||
tcpOut1.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
assertEquals("TESTING", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound2() {
|
||||
Message<String> message = MessageBuilder.withPayload("TESTING").build();
|
||||
tcpOut2.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
assertEquals("TESTING", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound3() {
|
||||
Message<String> message = MessageBuilder.withPayload("TESTING").build();
|
||||
tcpOut3.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
assertEquals("TESTING", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound4() {
|
||||
Message<String> message = MessageBuilder.withPayload("TESTING").build();
|
||||
tcpOut4.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
assertEquals("TESTING", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound5() {
|
||||
Message<String> message = MessageBuilder.withPayload("TESTING").build();
|
||||
tcpOut5.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
assertEquals("TESTING", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound6() {
|
||||
Message<String> message = MessageBuilder.withPayload("TESTING").build();
|
||||
tcpOut6.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
// custom format pads to 24 bytes
|
||||
assertEquals("TESTING ", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testTcpOutbound6a() {
|
||||
Message<String> message = MessageBuilder.withPayload(
|
||||
"abcdefghijklmnopqrdtuvwxyz").build();
|
||||
tcpOut6.handleMessage(message);
|
||||
Message<byte[]> mOut = (Message<byte[]>) channel.receive(10000);
|
||||
assertNotNull(mOut);
|
||||
// custom format truncates to 24 bytes
|
||||
assertEquals("abcdefghijklmnopqrdtuvwx", new String(mOut.getPayload()));
|
||||
|
||||
}
|
||||
|
||||
// /* (non-Javadoc)
|
||||
// * @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
// */
|
||||
// @Override
|
||||
// public void setApplicationContext(ApplicationContext applicationContext)
|
||||
// throws BeansException {
|
||||
// String[] names =
|
||||
// applicationContext.getBeanNamesForType(TcpNetSendingMessageHandler.class);
|
||||
// for (String n : names) {
|
||||
// System.out.println(n);
|
||||
// }
|
||||
// }
|
||||
|
||||
}
|
||||
@@ -17,16 +17,13 @@
|
||||
|
||||
<task:executor id="externalTE" pool-size="10"/>
|
||||
|
||||
<ip:inbound-channel-adapter id="testInUdp"
|
||||
<ip:udp-inbound-channel-adapter id="testInUdp"
|
||||
channel="udpChannel"
|
||||
check-length="true"
|
||||
message-format="stx-etx"
|
||||
multicast="false"
|
||||
pool-size="27"
|
||||
port="#{tcpIpUtils.findAvailableUdpSocket(5000)}"
|
||||
protocol="udp"
|
||||
receive-buffer-size="29"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="30"
|
||||
so-send-buffer-size="31"
|
||||
so-timeout="32"
|
||||
@@ -34,95 +31,39 @@
|
||||
task-executor="externalTE"
|
||||
/>
|
||||
|
||||
<ip:inbound-channel-adapter id="testInUdpMulticast"
|
||||
<ip:udp-inbound-channel-adapter id="testInUdpMulticast"
|
||||
channel="udpChannel"
|
||||
check-length="true"
|
||||
message-format="stx-etx"
|
||||
multicast="true"
|
||||
multicast-address="225.6.7.8"
|
||||
pool-size="27"
|
||||
port="#{tcpIpUtils.findAvailableUdpSocket(5100)}"
|
||||
protocol="udp"
|
||||
receive-buffer-size="29"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="30"
|
||||
so-send-buffer-size="31"
|
||||
so-timeout="32"
|
||||
local-address="127.0.0.1"
|
||||
/>
|
||||
|
||||
<ip:inbound-channel-adapter id="testInTcpNio"
|
||||
channel="tcpChannel"
|
||||
check-length="true"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNioSocketReader"
|
||||
message-format="stx-etx"
|
||||
pool-size="27"
|
||||
<ip:tcp-connection-factory id="cfS1"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5200)}"
|
||||
protocol="tcp"
|
||||
receive-buffer-size="29"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="30"
|
||||
so-timeout="32"
|
||||
using-direct-buffers="false"
|
||||
using-nio="true"
|
||||
local-address="127.0.0.1"
|
||||
/>
|
||||
|
||||
<ip:inbound-channel-adapter id="testInTcpNioDirect"
|
||||
/>
|
||||
|
||||
<ip:tcp-inbound-channel-adapter id="testInTcp"
|
||||
channel="tcpChannel"
|
||||
check-length="true"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNioSocketReader"
|
||||
message-format="stx-etx"
|
||||
pool-size="27"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5300)}"
|
||||
protocol="tcp"
|
||||
receive-buffer-size="29"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="30"
|
||||
so-timeout="32"
|
||||
using-direct-buffers="true"
|
||||
using-nio="true"
|
||||
close="true"
|
||||
connection-factory="cfS1"
|
||||
/>
|
||||
|
||||
<ip:inbound-channel-adapter id="testInTcpNet"
|
||||
channel="tcpChannel"
|
||||
check-length="true"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
message-format="stx-etx"
|
||||
pool-size="27"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5400)}"
|
||||
protocol="tcp"
|
||||
receive-buffer-size="29"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="30"
|
||||
so-timeout="32"
|
||||
local-address="127.0.0.1"
|
||||
/>
|
||||
|
||||
<ip:inbound-channel-adapter id="testInTcpNetSerialized"
|
||||
channel="tcpChannel"
|
||||
check-length="true"
|
||||
message-format="serialized"
|
||||
pool-size="27"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5450)}"
|
||||
protocol="tcp"
|
||||
receive-buffer-size="29"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="30"
|
||||
so-timeout="32"
|
||||
/>
|
||||
|
||||
<ip:outbound-channel-adapter id="testOutUdp"
|
||||
<ip:udp-outbound-channel-adapter id="testOutUdp"
|
||||
ack-host="somehost"
|
||||
ack-port="#{tcpIpUtils.findAvailableUdpSocket(7000)}"
|
||||
ack-port="#{tcpIpUtils.findAvailableUdpSocket(5300)}"
|
||||
ack-timeout="51"
|
||||
acknowledge="true"
|
||||
channel="udpChannel"
|
||||
check-length="true"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableUdpSocket(6000)}"
|
||||
protocol="udp"
|
||||
port="#{tcpIpUtils.findAvailableUdpSocket(5400)}"
|
||||
multicast="false"
|
||||
so-receive-buffer-size="52"
|
||||
so-send-buffer-size="53"
|
||||
@@ -131,16 +72,15 @@
|
||||
task-executor="externalTE"
|
||||
/>
|
||||
|
||||
<ip:outbound-channel-adapter id="testOutUdpiMulticast"
|
||||
<ip:udp-outbound-channel-adapter id="testOutUdpiMulticast"
|
||||
ack-host="somehost"
|
||||
ack-port="#{tcpIpUtils.findAvailableUdpSocket(7100)}"
|
||||
ack-port="#{tcpIpUtils.findAvailableUdpSocket(5500)}"
|
||||
ack-timeout="51"
|
||||
acknowledge="true"
|
||||
channel="udpChannel"
|
||||
check-length="true"
|
||||
host="225.6.7.8"
|
||||
port="#{tcpIpUtils.findAvailableUdpSocket(6100)}"
|
||||
protocol="udp"
|
||||
port="#{tcpIpUtils.findAvailableUdpSocket(5600)}"
|
||||
multicast="true"
|
||||
min-acks-for-success="2"
|
||||
so-receive-buffer-size="52"
|
||||
@@ -149,140 +89,48 @@
|
||||
time-to-live="55"
|
||||
/>
|
||||
|
||||
<ip:outbound-channel-adapter id="testOutTcpNio"
|
||||
channel="tcpChannel"
|
||||
<ip:tcp-connection-factory id="cfC1"
|
||||
type="client"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5700)}"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6200)}"
|
||||
protocol="tcp"
|
||||
so-send-buffer-size="53"
|
||||
so-timeout="54"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNioSocketWriter"
|
||||
message-format="stx-etx"
|
||||
so-keep-alive="true"
|
||||
so-linger="3"
|
||||
so-tcp-no-delay="true"
|
||||
so-traffic-class="27"
|
||||
using-nio="true"
|
||||
using-direct-buffers="false"
|
||||
/>
|
||||
|
||||
<ip:outbound-channel-adapter id="testOutTcpNioDirect"
|
||||
/>
|
||||
|
||||
<ip:tcp-outbound-channel-adapter id="testOutTcpNio"
|
||||
channel="tcpChannel"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6300)}"
|
||||
protocol="tcp"
|
||||
so-send-buffer-size="53"
|
||||
so-timeout="54"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNioSocketWriter"
|
||||
message-format="stx-etx"
|
||||
so-keep-alive="true"
|
||||
so-linger="3"
|
||||
so-tcp-no-delay="true"
|
||||
so-traffic-class="27"
|
||||
using-nio="true"
|
||||
using-direct-buffers="true"
|
||||
connection-factory="cfC1"
|
||||
/>
|
||||
|
||||
|
||||
<ip:outbound-channel-adapter id="testOutTcpNet"
|
||||
channel="tcpChannel"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6400)}"
|
||||
protocol="tcp"
|
||||
so-send-buffer-size="53"
|
||||
so-timeout="54"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"
|
||||
message-format="stx-etx"
|
||||
so-keep-alive="true"
|
||||
so-linger="3"
|
||||
so-tcp-no-delay="true"
|
||||
so-traffic-class="27"
|
||||
/>
|
||||
|
||||
<ip:outbound-channel-adapter id="testOutTcpNetSerialized"
|
||||
channel="tcpChannel"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6450)}"
|
||||
protocol="tcp"
|
||||
so-send-buffer-size="53"
|
||||
so-timeout="54"
|
||||
message-format="serialized"
|
||||
so-keep-alive="true"
|
||||
so-linger="3"
|
||||
so-tcp-no-delay="true"
|
||||
so-traffic-class="27"
|
||||
/>
|
||||
|
||||
<ip:inbound-gateway id="simpleInGateway"
|
||||
<ip:tcp-connection-factory id="cfS2"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5800)}"
|
||||
/>
|
||||
|
||||
<ip:tcp-inbound-gateway id="inGateway"
|
||||
request-channel="tcpChannel"
|
||||
reply-channel="replyChannel"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"
|
||||
message-format="crlf"
|
||||
pool-size="23"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6500)}"
|
||||
receive-buffer-size="123"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="124"
|
||||
so-send-buffer-size="125"
|
||||
so-timeout="126"
|
||||
local-address="127.0.0.1"
|
||||
task-executor="externalTE"
|
||||
connection-factory="cfS2"
|
||||
reply-timeout="456"
|
||||
/>
|
||||
|
||||
<ip:outbound-gateway id="simpleOutGateway"
|
||||
request-channel="tcpChannel"
|
||||
reply-channel="replyChannel"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"
|
||||
message-format="crlf"
|
||||
<ip:tcp-connection-factory id="cfC2"
|
||||
type="client"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5900)}"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6600)}"
|
||||
receive-buffer-size="223"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="224"
|
||||
so-send-buffer-size="225"
|
||||
so-timeout="226"
|
||||
close="false"
|
||||
/>
|
||||
|
||||
<ip:inbound-gateway id="simpleInGatewayClose"
|
||||
/>
|
||||
|
||||
<ip:tcp-outbound-gateway id="outGateway"
|
||||
request-channel="tcpChannel"
|
||||
reply-channel="replyChannel"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"
|
||||
message-format="crlf"
|
||||
pool-size="23"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6700)}"
|
||||
receive-buffer-size="123"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="124"
|
||||
so-send-buffer-size="125"
|
||||
so-timeout="126"
|
||||
close="true"
|
||||
/>
|
||||
|
||||
<ip:outbound-gateway id="simpleOutGatewayClose"
|
||||
request-channel="tcpChannel"
|
||||
reply-channel="replyChannel"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"
|
||||
message-format="crlf"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6800)}"
|
||||
receive-buffer-size="223"
|
||||
so-keep-alive="true"
|
||||
so-receive-buffer-size="224"
|
||||
so-send-buffer-size="225"
|
||||
so-timeout="226"
|
||||
close="true"
|
||||
connection-factory="cfC2"
|
||||
request-timeout="234"
|
||||
reply-timeout="567"
|
||||
/>
|
||||
|
||||
<ip:tcp-connection-factory
|
||||
id="client1"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="9876"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6000)}"
|
||||
input-converter="serial"
|
||||
output-converter="serial"
|
||||
so-keep-alive="true"
|
||||
@@ -303,7 +151,7 @@
|
||||
<ip:tcp-connection-factory
|
||||
id="server1"
|
||||
type="server"
|
||||
port="9876"
|
||||
port="#{client1.port}"
|
||||
local-address="127.0.0.1"
|
||||
input-converter="serial"
|
||||
output-converter="serial"
|
||||
@@ -322,6 +170,48 @@
|
||||
interceptor-factory-chain="interceptors"
|
||||
/>
|
||||
|
||||
<ip:tcp-connection-factory
|
||||
id="client2"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6000)}"
|
||||
input-converter="serial"
|
||||
output-converter="serial"
|
||||
so-keep-alive="true"
|
||||
so-linger="54"
|
||||
so-receive-buffer-size="1234"
|
||||
so-send-buffer-size="1235"
|
||||
so-tcp-no-delay="true"
|
||||
so-timeout="1236"
|
||||
so-traffic-class="12"
|
||||
using-nio="false"
|
||||
single-use="true"
|
||||
task-executor="externalTE"
|
||||
pool-size="321"
|
||||
interceptor-factory-chain="interceptors"
|
||||
/>
|
||||
|
||||
<ip:tcp-connection-factory
|
||||
id="server2"
|
||||
type="server"
|
||||
port="#{client1.port}"
|
||||
local-address="127.0.0.1"
|
||||
input-converter="serial"
|
||||
output-converter="serial"
|
||||
so-keep-alive="true"
|
||||
so-linger="55"
|
||||
so-receive-buffer-size="1234"
|
||||
so-send-buffer-size="1235"
|
||||
so-tcp-no-delay="true"
|
||||
so-timeout="1236"
|
||||
so-traffic-class="12"
|
||||
using-nio="false"
|
||||
single-use="true"
|
||||
task-executor="externalTE"
|
||||
pool-size="123"
|
||||
interceptor-factory-chain="interceptors"
|
||||
/>
|
||||
|
||||
<bean id="interceptors" class="org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain" />
|
||||
|
||||
<bean id="serial" class="org.springframework.commons.serializer.java.JavaStreamingConverter" />
|
||||
|
||||
@@ -29,20 +29,13 @@ import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.commons.serializer.InputStreamingConverter;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.core.task.TaskExecutor;
|
||||
import org.springframework.integration.ip.tcp.CustomNetSocketReader;
|
||||
import org.springframework.integration.ip.tcp.CustomNetSocketWriter;
|
||||
import org.springframework.integration.ip.tcp.CustomNioSocketReader;
|
||||
import org.springframework.integration.ip.tcp.CustomNioSocketWriter;
|
||||
import org.springframework.integration.ip.tcp.MessageFormats;
|
||||
import org.springframework.integration.ip.tcp.SimpleTcpNetInboundGateway;
|
||||
import org.springframework.integration.ip.tcp.SimpleTcpNetOutboundGateway;
|
||||
import org.springframework.integration.ip.tcp.TcpNetReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler;
|
||||
import org.springframework.integration.ip.tcp.TcpNioReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler;
|
||||
import org.springframework.integration.ip.tcp.TcpInboundGateway;
|
||||
import org.springframework.integration.ip.tcp.TcpOutboundGateway;
|
||||
import org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.TcpSendingMessageHandler;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpNetClientConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpNetServerConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpNioClientConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
|
||||
import org.springframework.integration.ip.udp.DatagramPacketMessageMapper;
|
||||
@@ -74,20 +67,8 @@ public class ParserUnitTests {
|
||||
MulticastReceivingChannelAdapter udpInMulticast;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="testInTcpNio")
|
||||
TcpNioReceivingChannelAdapter tcpInNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="testInTcpNioDirect")
|
||||
TcpNioReceivingChannelAdapter tcpInNioDirect;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="testInTcpNet")
|
||||
TcpNetReceivingChannelAdapter tcpInNet;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="testInTcpNetSerialized")
|
||||
TcpNetReceivingChannelAdapter tcpInNetSerialized;
|
||||
@Qualifier(value="testInTcp")
|
||||
TcpReceivingChannelAdapter tcpIn;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.udp.UnicastSendingMessageHandler#0")
|
||||
@@ -98,37 +79,17 @@ public class ParserUnitTests {
|
||||
MulticastSendingMessageHandler udpOutMulticast;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler#0")
|
||||
TcpNioSendingMessageHandler tcpOutNio;
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpSendingMessageHandler#0")
|
||||
TcpSendingMessageHandler tcpOut;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNioSendingMessageHandler#1")
|
||||
TcpNioSendingMessageHandler tcpOutNioDirect;
|
||||
@Qualifier(value="inGateway")
|
||||
TcpInboundGateway tcpInboundGateway;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#0")
|
||||
TcpNetSendingMessageHandler tcpOutNet;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpNetSendingMessageHandler#1")
|
||||
TcpNetSendingMessageHandler tcpOutNetSerialized;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="simpleInGateway")
|
||||
SimpleTcpNetInboundGateway simpleTcpNetInboundGateway;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.SimpleTcpNetOutboundGateway#0")
|
||||
SimpleTcpNetOutboundGateway simpleTcpNetOutboundGateway;
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpOutboundGateway#0")
|
||||
TcpOutboundGateway tcpOutboundGateway;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="simpleInGatewayClose")
|
||||
SimpleTcpNetInboundGateway simpleTcpNetInboundGatewayClose;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.SimpleTcpNetOutboundGateway#1")
|
||||
SimpleTcpNetOutboundGateway simpleTcpNetOutboundGatewayClose;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="externalTE")
|
||||
TaskExecutor taskExecutor;
|
||||
@@ -137,6 +98,18 @@ public class ParserUnitTests {
|
||||
@Qualifier(value="client1")
|
||||
AbstractConnectionFactory client1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="client2")
|
||||
AbstractConnectionFactory client2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="cfC1")
|
||||
AbstractConnectionFactory cfC1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="cfC2")
|
||||
AbstractConnectionFactory cfC2;
|
||||
|
||||
@Autowired
|
||||
InputStreamingConverter<byte[]> converter;
|
||||
|
||||
@@ -145,11 +118,23 @@ public class ParserUnitTests {
|
||||
AbstractConnectionFactory server1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpSendingMessageHandler#0")
|
||||
TcpSendingMessageHandler tcpNewOut1;
|
||||
@Qualifier(value="server2")
|
||||
AbstractConnectionFactory server2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="cfS1")
|
||||
AbstractConnectionFactory cfS1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="cfS2")
|
||||
AbstractConnectionFactory cfS2;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpSendingMessageHandler#1")
|
||||
TcpSendingMessageHandler tcpNewOut1;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="org.springframework.integration.ip.tcp.TcpSendingMessageHandler#2")
|
||||
TcpSendingMessageHandler tcpNewOut2;
|
||||
|
||||
@Autowired
|
||||
@@ -188,71 +173,18 @@ public class ParserUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInTcpNio() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpInNio);
|
||||
assertTrue(tcpInNio.getPort() >= 5200);
|
||||
assertEquals(CustomNioSocketReader.class, dfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(false, dfa.getPropertyValue("usingDirectBuffers"));
|
||||
assertEquals(MessageFormats.FORMAT_STX_ETX, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(27, dfa.getPropertyValue("poolSize"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(29, dfa.getPropertyValue("receiveBufferSize"));
|
||||
assertEquals(30, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(32, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(false, dfa.getPropertyValue("close"));
|
||||
assertEquals("127.0.0.1", dfa.getPropertyValue("localAddress"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInTcpNioDirect() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpInNioDirect);
|
||||
assertTrue(tcpInNioDirect.getPort() >= 5300);
|
||||
assertEquals(CustomNioSocketReader.class, dfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(true, dfa.getPropertyValue("usingDirectBuffers"));
|
||||
assertEquals(MessageFormats.FORMAT_STX_ETX, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(27, dfa.getPropertyValue("poolSize"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(29, dfa.getPropertyValue("receiveBufferSize"));
|
||||
assertEquals(30, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(32, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(true, dfa.getPropertyValue("close"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInTcpNet() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpInNet);
|
||||
assertTrue(tcpInNet.getPort() >= 5400);
|
||||
assertEquals(CustomNetSocketReader.class, dfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(MessageFormats.FORMAT_STX_ETX, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(27, dfa.getPropertyValue("poolSize"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(29, dfa.getPropertyValue("receiveBufferSize"));
|
||||
assertEquals(30, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(32, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(false, dfa.getPropertyValue("close"));
|
||||
assertEquals("127.0.0.1", dfa.getPropertyValue("localAddress"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInTcpNetSerialized() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpInNetSerialized);
|
||||
assertTrue(tcpInNetSerialized.getPort() >= 5450);
|
||||
assertEquals(MessageFormats.FORMAT_JAVA_SERIALIZED, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(27, dfa.getPropertyValue("poolSize"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(29, dfa.getPropertyValue("receiveBufferSize"));
|
||||
assertEquals(30, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(32, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(false, dfa.getPropertyValue("close"));
|
||||
public void testInTcp() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpIn);
|
||||
assertSame(cfS1, dfa.getPropertyValue("serverConnectionFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutUdp() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(udpOut);
|
||||
assertTrue(udpOut.getPort() >= 6000);
|
||||
assertTrue(udpOut.getPort() >= 5400);
|
||||
assertEquals("localhost", dfa.getPropertyValue("host"));
|
||||
int ackPort = (Integer) dfa.getPropertyValue("ackPort");
|
||||
assertTrue("Expected ackPort >= 7000 was:" + ackPort, ackPort >= 7000);
|
||||
assertTrue("Expected ackPort >= 5300 was:" + ackPort, ackPort >= 5300);
|
||||
DatagramPacketMessageMapper mapper = (DatagramPacketMessageMapper) dfa
|
||||
.getPropertyValue("mapper");
|
||||
String ackAddress = (String) new DirectFieldAccessor(mapper)
|
||||
@@ -270,10 +202,10 @@ public class ParserUnitTests {
|
||||
@Test
|
||||
public void testOutUdpMulticast() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(udpOutMulticast);
|
||||
assertTrue(udpOutMulticast.getPort() >= 6100);
|
||||
assertTrue(udpOutMulticast.getPort() >= 5600);
|
||||
assertEquals("225.6.7.8", dfa.getPropertyValue("host"));
|
||||
int ackPort = (Integer) dfa.getPropertyValue("ackPort");
|
||||
assertTrue("Expected ackPort >= 7100 was:" + ackPort, ackPort >= 7100);
|
||||
assertTrue("Expected ackPort >= 5500 was:" + ackPort, ackPort >= 5500);
|
||||
DatagramPacketMessageMapper mapper = (DatagramPacketMessageMapper) dfa
|
||||
.getPropertyValue("mapper");
|
||||
String ackAddress = (String) new DirectFieldAccessor(mapper)
|
||||
@@ -288,142 +220,31 @@ public class ParserUnitTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutTcpNio() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOutNio);
|
||||
assertTrue(tcpOutNio.getPort() >= 6200);
|
||||
assertEquals(MessageFormats.FORMAT_STX_ETX, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(CustomNioSocketWriter.class, dfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(3, dfa.getPropertyValue("soLinger"));
|
||||
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
|
||||
assertEquals(27, dfa.getPropertyValue("soTrafficClass"));
|
||||
assertEquals(53, dfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(54, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(false, dfa.getPropertyValue("usingDirectBuffers"));
|
||||
public void testOutTcp() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOut);
|
||||
assertSame(cfC1, dfa.getPropertyValue("clientConnectionFactory"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutTcpNioDirect() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOutNioDirect);
|
||||
assertTrue(tcpOutNioDirect.getPort() >= 6300);
|
||||
assertEquals(MessageFormats.FORMAT_STX_ETX, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(CustomNioSocketWriter.class, dfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(3, dfa.getPropertyValue("soLinger"));
|
||||
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
|
||||
assertEquals(27, dfa.getPropertyValue("soTrafficClass"));
|
||||
assertEquals(53, dfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(54, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(true, dfa.getPropertyValue("usingDirectBuffers"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutTcpNet() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOutNet);
|
||||
assertTrue(tcpOutNet.getPort() >= 6400);
|
||||
assertEquals(MessageFormats.FORMAT_STX_ETX, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(CustomNetSocketWriter.class, dfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(3, dfa.getPropertyValue("soLinger"));
|
||||
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
|
||||
assertEquals(27, dfa.getPropertyValue("soTrafficClass"));
|
||||
assertEquals(53, dfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(54, dfa.getPropertyValue("soTimeout"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutTcpNetSerialized() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOutNetSerialized);
|
||||
assertTrue(tcpOutNetSerialized.getPort() >= 6450);
|
||||
assertEquals(MessageFormats.FORMAT_JAVA_SERIALIZED, dfa.getPropertyValue("messageFormat"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(3, dfa.getPropertyValue("soLinger"));
|
||||
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
|
||||
assertEquals(27, dfa.getPropertyValue("soTrafficClass"));
|
||||
assertEquals(53, dfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(54, dfa.getPropertyValue("soTimeout"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInGateway() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(simpleTcpNetInboundGateway);
|
||||
assertTrue(simpleTcpNetInboundGateway.getPort() >= 6500);
|
||||
assertEquals(MessageFormats.FORMAT_CRLF, dfa.getPropertyValue("messageFormat"));
|
||||
TcpNetReceivingChannelAdapter delegate = (TcpNetReceivingChannelAdapter) dfa
|
||||
.getPropertyValue("delegate");
|
||||
DirectFieldAccessor delegateDfa = new DirectFieldAccessor(delegate);
|
||||
assertEquals(CustomNetSocketReader.class, delegateDfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(CustomNetSocketWriter.class, dfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(123, dfa.getPropertyValue("receiveBufferSize"));
|
||||
assertEquals(124, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(125, dfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(126, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(23, dfa.getPropertyValue("poolSize"));
|
||||
assertEquals(false, dfa.getPropertyValue("close"));
|
||||
assertEquals("127.0.0.1", dfa.getPropertyValue("localAddress"));
|
||||
assertSame(taskExecutor, dfa.getPropertyValue("taskExecutor"));
|
||||
assertSame(taskExecutor, delegateDfa.getPropertyValue("taskExecutor"));
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpInboundGateway);
|
||||
assertSame(cfS2, dfa.getPropertyValue("connectionFactory"));
|
||||
assertEquals(456L, dfa.getPropertyValue("replyTimeout"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutGateway() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(simpleTcpNetOutboundGateway);
|
||||
assertTrue(simpleTcpNetOutboundGateway.getPort() >= 6600);
|
||||
assertEquals(MessageFormats.FORMAT_CRLF, dfa.getPropertyValue("messageFormat"));
|
||||
TcpNetSendingMessageHandler handler = (TcpNetSendingMessageHandler) dfa
|
||||
.getPropertyValue("handler");
|
||||
DirectFieldAccessor delegateDfa = new DirectFieldAccessor(handler);
|
||||
assertEquals(CustomNetSocketReader.class, dfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(CustomNetSocketWriter.class, delegateDfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, delegateDfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(224, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(225, delegateDfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(226, delegateDfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(false, dfa.getPropertyValue("close"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInGatewayClose() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(simpleTcpNetInboundGatewayClose);
|
||||
assertTrue(simpleTcpNetInboundGatewayClose.getPort() >= 6700);
|
||||
assertEquals(MessageFormats.FORMAT_CRLF, dfa.getPropertyValue("messageFormat"));
|
||||
TcpNetReceivingChannelAdapter delegate = (TcpNetReceivingChannelAdapter) dfa
|
||||
.getPropertyValue("delegate");
|
||||
DirectFieldAccessor delegateDfa = new DirectFieldAccessor(delegate);
|
||||
assertEquals(CustomNetSocketReader.class, delegateDfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(CustomNetSocketWriter.class, dfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, dfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(123, dfa.getPropertyValue("receiveBufferSize"));
|
||||
assertEquals(124, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(125, dfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(126, dfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(23, dfa.getPropertyValue("poolSize"));
|
||||
assertEquals(true, dfa.getPropertyValue("close"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutGatewayClose() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(simpleTcpNetOutboundGatewayClose);
|
||||
assertTrue(simpleTcpNetOutboundGatewayClose.getPort() >= 6800);
|
||||
assertEquals(MessageFormats.FORMAT_CRLF, dfa.getPropertyValue("messageFormat"));
|
||||
TcpNetSendingMessageHandler handler = (TcpNetSendingMessageHandler) dfa
|
||||
.getPropertyValue("handler");
|
||||
DirectFieldAccessor delegateDfa = new DirectFieldAccessor(handler);
|
||||
assertEquals(CustomNetSocketReader.class, dfa.getPropertyValue("customSocketReaderClass"));
|
||||
assertEquals(CustomNetSocketWriter.class, delegateDfa.getPropertyValue("customSocketWriterClass"));
|
||||
assertEquals(true, delegateDfa.getPropertyValue("soKeepAlive"));
|
||||
assertEquals(224, dfa.getPropertyValue("soReceiveBufferSize"));
|
||||
assertEquals(225, delegateDfa.getPropertyValue("soSendBufferSize"));
|
||||
assertEquals(226, delegateDfa.getPropertyValue("soTimeout"));
|
||||
assertEquals(true, dfa.getPropertyValue("close"));
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpOutboundGateway);
|
||||
assertSame(cfC2, dfa.getPropertyValue("connectionFactory"));
|
||||
assertEquals(234L, dfa.getPropertyValue("requestTimeout"));
|
||||
assertEquals(567L, dfa.getPropertyValue("replyTimeout"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnClient1() {
|
||||
assertTrue(client1 instanceof TcpNioClientConnectionFactory);
|
||||
assertEquals("localhost", client1.getHost());
|
||||
assertEquals(9876, client1.getPort());
|
||||
assertTrue(client1.getPort() >= 6000);
|
||||
assertEquals(54, client1.getSoLinger());
|
||||
assertEquals(1234, client1.getSoReceiveBufferSize());
|
||||
assertEquals(1235, client1.getSoSendBufferSize());
|
||||
@@ -443,7 +264,7 @@ public class ParserUnitTests {
|
||||
@Test
|
||||
public void testConnServer1() {
|
||||
assertTrue(server1 instanceof TcpNioServerConnectionFactory);
|
||||
assertEquals(9876, server1.getPort());
|
||||
assertEquals(client1.getPort(), server1.getPort());
|
||||
assertEquals(55, server1.getSoLinger());
|
||||
assertEquals(1234, server1.getSoReceiveBufferSize());
|
||||
assertEquals(1235, server1.getSoSendBufferSize());
|
||||
@@ -460,6 +281,45 @@ public class ParserUnitTests {
|
||||
assertNotNull(dfa.getPropertyValue("interceptorFactoryChain"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnClient2() {
|
||||
assertTrue(client2 instanceof TcpNetClientConnectionFactory);
|
||||
assertEquals("localhost", client1.getHost());
|
||||
assertTrue(client1.getPort() >= 6000);
|
||||
assertEquals(54, client1.getSoLinger());
|
||||
assertEquals(1234, client1.getSoReceiveBufferSize());
|
||||
assertEquals(1235, client1.getSoSendBufferSize());
|
||||
assertEquals(1236, client1.getSoTimeout());
|
||||
assertEquals(12, client1.getSoTrafficClass());
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(client1);
|
||||
assertSame(converter, dfa.getPropertyValue("inputConverter"));
|
||||
assertSame(converter, dfa.getPropertyValue("outputConverter"));
|
||||
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
|
||||
assertEquals(true, dfa.getPropertyValue("singleUse"));
|
||||
assertSame(taskExecutor, dfa.getPropertyValue("taskExecutor"));
|
||||
assertEquals(321, dfa.getPropertyValue("poolSize"));
|
||||
assertNotNull(dfa.getPropertyValue("interceptorFactoryChain"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConnServer2() {
|
||||
assertTrue(server2 instanceof TcpNetServerConnectionFactory);
|
||||
assertEquals(client1.getPort(), server1.getPort());
|
||||
assertEquals(55, server1.getSoLinger());
|
||||
assertEquals(1234, server1.getSoReceiveBufferSize());
|
||||
assertEquals(1235, server1.getSoSendBufferSize());
|
||||
assertEquals(1236, server1.getSoTimeout());
|
||||
assertEquals(12, server1.getSoTrafficClass());
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(server1);
|
||||
assertSame(converter, dfa.getPropertyValue("inputConverter"));
|
||||
assertSame(converter, dfa.getPropertyValue("outputConverter"));
|
||||
assertEquals(true, dfa.getPropertyValue("soTcpNoDelay"));
|
||||
assertEquals(true, dfa.getPropertyValue("singleUse"));
|
||||
assertSame(taskExecutor, dfa.getPropertyValue("taskExecutor"));
|
||||
assertEquals(123, dfa.getPropertyValue("poolSize"));
|
||||
assertNotNull(dfa.getPropertyValue("interceptorFactoryChain"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNewOut1() {
|
||||
DirectFieldAccessor dfa = new DirectFieldAccessor(tcpNewOut1);
|
||||
|
||||
@@ -1,102 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:ip="http://www.springframework.org/schema/integration/ip"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/ip
|
||||
http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
|
||||
|
||||
<beans:bean id="tcpIpUtils" class="org.springframework.integration.ip.util.SocketUtils" />
|
||||
|
||||
<!-- nio without direct buffers -->
|
||||
<ip:inbound-channel-adapter id="tcp1"
|
||||
channel="channel"
|
||||
protocol="tcp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5000)}"
|
||||
message-format="length-header"
|
||||
using-nio="true"
|
||||
using-direct-buffers="false"
|
||||
pool-size="2"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- nio with direct buffers -->
|
||||
<ip:inbound-channel-adapter id="tcp2"
|
||||
channel="channel"
|
||||
protocol="tcp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6000)}"
|
||||
message-format="length-header"
|
||||
using-nio="true"
|
||||
using-direct-buffers="true"
|
||||
pool-size="2"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net -->
|
||||
<ip:inbound-channel-adapter id="tcp3"
|
||||
channel="channel"
|
||||
protocol="tcp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(7000)}"
|
||||
message-format="length-header"
|
||||
using-nio="false"
|
||||
pool-size="2"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net stxetx -->
|
||||
<ip:inbound-channel-adapter id="tcp4"
|
||||
channel="channel"
|
||||
protocol="tcp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(8000)}"
|
||||
message-format="stx-etx"
|
||||
using-nio="false"
|
||||
pool-size="2"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net crlf -->
|
||||
<ip:inbound-channel-adapter id="tcp5"
|
||||
channel="channel"
|
||||
protocol="tcp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(9000)}"
|
||||
message-format="crlf"
|
||||
using-nio="false"
|
||||
pool-size="2"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net custom -->
|
||||
<ip:inbound-channel-adapter id="tcp6"
|
||||
channel="channel"
|
||||
protocol="tcp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(10000)}"
|
||||
message-format="custom"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
using-nio="false"
|
||||
pool-size="2"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<ip:inbound-channel-adapter id="udp1"
|
||||
channel="channel"
|
||||
protocol="udp"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(11000)}"
|
||||
receive-buffer-size="500"
|
||||
multicast="false"
|
||||
check-length="true" />
|
||||
|
||||
<channel id="channel" >
|
||||
<queue capacity="2"/>
|
||||
</channel>
|
||||
|
||||
</beans:beans>
|
||||
@@ -1,95 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:ip="http://www.springframework.org/schema/integration/ip"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/ip
|
||||
http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
|
||||
|
||||
<channel id="inChannel"/>
|
||||
|
||||
<!-- nio without direct buffers -->
|
||||
<ip:outbound-channel-adapter id="tcpOut1"
|
||||
channel="inChannel"
|
||||
protocol="tcp"
|
||||
host="localhost"
|
||||
port="#{tcp1.port}"
|
||||
message-format="length-header"
|
||||
using-nio="true"
|
||||
using-direct-buffers="false"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- nio with direct buffers -->
|
||||
<ip:outbound-channel-adapter id="tcpOut2"
|
||||
channel="inChannel"
|
||||
protocol="tcp"
|
||||
host="localhost"
|
||||
port="#{tcp2.port}"
|
||||
message-format="length-header"
|
||||
using-nio="true"
|
||||
using-direct-buffers="true"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net -->
|
||||
<ip:outbound-channel-adapter id="tcpOut3"
|
||||
channel="inChannel"
|
||||
protocol="tcp"
|
||||
host="localhost"
|
||||
port="#{tcp3.port}"
|
||||
message-format="length-header"
|
||||
using-nio="false"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net stxetx -->
|
||||
<ip:outbound-channel-adapter id="tcpOut4"
|
||||
channel="inChannel"
|
||||
protocol="tcp"
|
||||
host="localhost"
|
||||
port="#{tcp4.port}"
|
||||
message-format="stx-etx"
|
||||
using-nio="false"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net crlf -->
|
||||
<ip:outbound-channel-adapter id="tcpOut5"
|
||||
channel="inChannel"
|
||||
protocol="tcp"
|
||||
host="localhost"
|
||||
port="#{tcp5.port}"
|
||||
message-format="crlf"
|
||||
using-nio="false"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<!-- net custom -->
|
||||
<ip:outbound-channel-adapter id="tcpOut6"
|
||||
channel="inChannel"
|
||||
protocol="tcp"
|
||||
host="localhost"
|
||||
port="#{tcp6.port}"
|
||||
message-format="custom"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"
|
||||
using-nio="false"
|
||||
so-keep-alive="true"
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<beans:bean id="taskScheduler" class="org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler">
|
||||
<beans:property name="daemon" value="true" />
|
||||
<beans:property name="poolSize" value="20" />
|
||||
</beans:bean>
|
||||
|
||||
</beans:beans>
|
||||
@@ -23,4 +23,13 @@
|
||||
so-timeout="100000"
|
||||
/>
|
||||
|
||||
<int-ip:tcp-inbound-gateway id="looper"
|
||||
request-channel="queue"
|
||||
connection-factory="server"
|
||||
/>
|
||||
|
||||
<int:channel id="queue">
|
||||
<int:queue/>
|
||||
</int:channel>
|
||||
|
||||
</beans>
|
||||
|
||||
@@ -16,9 +16,9 @@
|
||||
|
||||
package org.springframework.integration.ip.tcp;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
@@ -26,7 +26,6 @@ import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.tcp.TcpReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpConnection;
|
||||
@@ -52,14 +51,8 @@ public class ConnectionToConnectionTests {
|
||||
@Autowired
|
||||
private AbstractServerConnectionFactory server;
|
||||
|
||||
private TcpReceivingChannelAdapter receiver;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
receiver = new TcpReceivingChannelAdapter();
|
||||
server.registerListener(receiver);
|
||||
ctx.start();
|
||||
}
|
||||
@Autowired
|
||||
private QueueChannel serverSideChannel;
|
||||
|
||||
@Test
|
||||
public void testConnect() throws Exception {
|
||||
@@ -71,11 +64,10 @@ public class ConnectionToConnectionTests {
|
||||
}
|
||||
}
|
||||
TcpConnection connection = client.getConnection();
|
||||
QueueChannel channel = new QueueChannel();
|
||||
receiver.setOutputChannel(channel);
|
||||
connection.send(MessageBuilder.withPayload("Test").build());
|
||||
Message<?> m = channel.receive(10000);
|
||||
assertNotNull(m);
|
||||
Message<?> message = serverSideChannel.receive(10000);
|
||||
assertNotNull(message);
|
||||
assertEquals("Test", new String((byte[]) message.getPayload()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Reads messages that are exactly 24 bytes long.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class CustomNetSocketReader extends NetSocketReader {
|
||||
|
||||
public CustomNetSocketReader() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param socket
|
||||
*/
|
||||
public CustomNetSocketReader(Socket socket) {
|
||||
super(socket);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.NetSocketReader#assembleDataCustomFormat()
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataCustomFormat() throws IOException {
|
||||
byte[] buff = new byte[24];
|
||||
int status = read(buff, true);
|
||||
if (status < 0) {
|
||||
return status;
|
||||
}
|
||||
assembledData = buff;
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.net.Socket;
|
||||
|
||||
/**
|
||||
* Writes packets that are always 24 bytes long.
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class CustomNetSocketWriter extends NetSocketWriter {
|
||||
|
||||
/**
|
||||
* @param socket
|
||||
*/
|
||||
public CustomNetSocketWriter(Socket socket) {
|
||||
super(socket);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.NetSocketWriter#writeCustomFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeCustomFormat(Object object) throws IOException {
|
||||
byte[] bytes;
|
||||
if (object instanceof byte[]) {
|
||||
bytes = (byte[]) object;
|
||||
} else if (object instanceof String) {
|
||||
bytes = ((String) object).getBytes();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Only supports String and byte[]");
|
||||
}
|
||||
|
||||
if (bytes.length > 24) {
|
||||
socket.getOutputStream().write(bytes, 0, 24);
|
||||
return;
|
||||
}
|
||||
socket.getOutputStream().write(bytes);
|
||||
if (bytes.length < 24) {
|
||||
socket.getOutputStream().write(
|
||||
" ".substring(bytes.length) .getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,64 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
/**
|
||||
* Reads messages that are exactly 24 bytes long.
|
||||
*
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class CustomNioSocketReader extends NioSocketReader {
|
||||
|
||||
private ByteBuffer buffer;
|
||||
|
||||
public CustomNioSocketReader() {
|
||||
super(null);
|
||||
}
|
||||
|
||||
public CustomNioSocketReader(SocketChannel channel) {
|
||||
super(channel);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.NetSocketReader#assembleDataCustomFormat()
|
||||
*/
|
||||
@Override
|
||||
protected int assembleDataCustomFormat() throws IOException {
|
||||
if (buffer == null) {
|
||||
buffer = allocate(24);
|
||||
}
|
||||
int status = readChannel(buffer);
|
||||
if (status < 0 ) {
|
||||
if (buffer.remaining() == 24)
|
||||
return status;
|
||||
throw new IOException("Channel closed");
|
||||
}
|
||||
if (buffer.hasRemaining()) {
|
||||
return MESSAGE_INCOMPLETE;
|
||||
}
|
||||
assembledData = buffer.array();
|
||||
buffer = null;
|
||||
return MESSAGE_COMPLETE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
|
||||
/**
|
||||
* Writes packets that are always 24 bytes long.
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class CustomNioSocketWriter extends NioSocketWriter {
|
||||
|
||||
|
||||
/**
|
||||
* @param channel
|
||||
* @param maxBuffers
|
||||
* @param sendBufferSize
|
||||
*/
|
||||
public CustomNioSocketWriter(SocketChannel channel, int maxBuffers,
|
||||
int sendBufferSize) {
|
||||
super(channel, maxBuffers, sendBufferSize);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.NetSocketWriter#writeCustomFormat(byte[])
|
||||
*/
|
||||
@Override
|
||||
protected void writeCustomFormat(Object object) throws IOException {
|
||||
byte[] bytes;
|
||||
if (object instanceof byte[]) {
|
||||
bytes = (byte[]) object;
|
||||
} else if (object instanceof String) {
|
||||
bytes = ((String) object).getBytes();
|
||||
} else {
|
||||
throw new UnsupportedOperationException("Only supports String and byte[]");
|
||||
}
|
||||
|
||||
ByteBuffer data = ByteBuffer.wrap(bytes);
|
||||
if (bytes.length > 24) {
|
||||
data.limit(24);
|
||||
channel.write(data);
|
||||
return;
|
||||
}
|
||||
channel.write(data);
|
||||
if (bytes.length < 24) {
|
||||
data = ByteBuffer.wrap(
|
||||
" ".substring(bytes.length).getBytes());
|
||||
channel.write(data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -62,7 +62,6 @@ public class InterceptedSharedConnectionTests {
|
||||
@Test
|
||||
public void test1() throws Exception {
|
||||
int n = 0;
|
||||
Object o = ctx.getBean("inboundServer");
|
||||
while (!listener.isListening()) {
|
||||
Thread.sleep(100);
|
||||
if (n++ > 100) {
|
||||
|
||||
@@ -1,126 +0,0 @@
|
||||
/*
|
||||
* 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.assertNotNull;
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* For both .net. and .nio. adapters, creates a single server and 10 clients
|
||||
* and sends 3 long messages from each client to the associated server.
|
||||
* Ensures that all messages are correctly assembled and received ok.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*
|
||||
*/
|
||||
public class MultiClientTests {
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test @Ignore
|
||||
public void testNet() throws Exception {
|
||||
final String payload = largePayload(10000); // force fragmentation
|
||||
final TcpNetReceivingChannelAdapter adapter =
|
||||
new TcpNetReceivingChannelAdapter(SocketUtils.findAvailableServerSocket());
|
||||
int drivers = 10;
|
||||
adapter.setPoolSize(drivers);
|
||||
adapter.setReceiveBufferSize(10000);
|
||||
QueueChannel queue = new QueueChannel(drivers * 3);
|
||||
adapter.setOutputChannel(queue);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
for (int i = 0; i < drivers; i++) {
|
||||
Thread t = new Thread( new Runnable() {
|
||||
public void run() {
|
||||
TcpNetSendingMessageHandler sender = new TcpNetSendingMessageHandler("localhost", adapter.getPort());
|
||||
Message<String> message = MessageBuilder.withPayload(payload).build();
|
||||
sender.handleMessage(message);
|
||||
// and again
|
||||
sender.handleMessage(message);
|
||||
// and again
|
||||
sender.handleMessage(message);
|
||||
}});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
for (int i = 0; i < drivers * 3 ; i++) {
|
||||
Message<byte[]> messageOut = (Message<byte[]>) queue.receive(6000);
|
||||
assertNotNull(messageOut);
|
||||
Assert.assertEquals(payload, new String(messageOut.getPayload()));
|
||||
}
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test @Ignore
|
||||
public void testNio() throws Exception {
|
||||
final String payload = largePayload(10000); // force fragmentation
|
||||
final TcpNioReceivingChannelAdapter adapter =
|
||||
new TcpNioReceivingChannelAdapter(SocketUtils.findAvailableServerSocket());
|
||||
adapter.setPoolSize(4);
|
||||
adapter.setReceiveBufferSize(10000);
|
||||
int drivers = 10;
|
||||
QueueChannel queue = new QueueChannel(drivers * 3);
|
||||
adapter.setOutputChannel(queue);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
for (int i = 0; i < drivers; i++) {
|
||||
Thread t = new Thread( new Runnable() {
|
||||
public void run() {
|
||||
TcpNioSendingMessageHandler sender = new TcpNioSendingMessageHandler("localhost", adapter.getPort());
|
||||
Message<String> message = MessageBuilder.withPayload(payload).build();
|
||||
sender.handleMessage(message);
|
||||
// and again
|
||||
sender.handleMessage(message);
|
||||
// and again
|
||||
sender.handleMessage(message);
|
||||
}});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
}
|
||||
for (int i = 0; i < drivers * 3 ; i++) {
|
||||
Message<byte[]> messageOut = (Message<byte[]>) queue.receive(6000);
|
||||
assertNotNull(messageOut);
|
||||
Assert.assertEquals(payload, new String(messageOut.getPayload()));
|
||||
}
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
private String largePayload(int n) {
|
||||
StringBuilder sb = new StringBuilder(n);
|
||||
for (int i = 0; i < n; i++) {
|
||||
sb.append('x');
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,417 +0,0 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class NetSocketReaderTests {
|
||||
|
||||
@Test
|
||||
public void testReadLength() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendLength(port, null);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble first message");
|
||||
}
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble second message");
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadStxEtx() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendStxEtx(port, null);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble first message");
|
||||
}
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble second message");
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCrLf() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendCrLf(port, null);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble first message");
|
||||
}
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble second message");
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadSerialized() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendSerialized(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING,
|
||||
reader.getAssembledData());
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble first message");
|
||||
}
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING,
|
||||
reader.getAssembledData());
|
||||
}
|
||||
else {
|
||||
fail("Failed to assemble second message");
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLengthOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendLengthOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Message length")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadStxEtxTimeout() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendStxEtxOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(500);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Read timed out")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadStxEtxOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendStxEtxOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
reader.setMaxMessageSize(1024);
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("ETX not found")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCrLfTimeout() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendCrLfOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(500);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Read timed out")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCrLfOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendCrLfOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
reader.setMaxMessageSize(1024);
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("CRLF not found")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when no data received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testCloseCleanupNoData() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Socket socket = server.accept();
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
semaphore.release();
|
||||
assertTrue(reader.assembleData() < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
semaphore.release();
|
||||
assertTrue(reader.assembleData() < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
semaphore.release();
|
||||
assertTrue(reader.assembleData() < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
|
||||
semaphore.release();
|
||||
assertTrue(reader.assembleData() < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new CustomNetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
semaphore.release();
|
||||
assertTrue(reader.assembleData() < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when mid-message
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testCloseCleanup() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
byte[] header = {0, 0, 0, 10};
|
||||
socket.getOutputStream().write(header);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
|
||||
socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
|
||||
socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write(MessageFormats.STX);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
|
||||
socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write(MessageFormats.STX);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Socket socket = server.accept();
|
||||
NetSocketReader reader = new NetSocketReader(socket);
|
||||
semaphore.release();
|
||||
try {
|
||||
reader.assembleData();
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
semaphore.release();
|
||||
try {
|
||||
reader.assembleData();
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new NetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
semaphore.release();
|
||||
try {
|
||||
reader.assembleData();
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
socket = server.accept();
|
||||
reader = new CustomNetSocketReader(socket);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
semaphore.release();
|
||||
try {
|
||||
reader.assembleData();
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -1,578 +0,0 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.Socket;
|
||||
import java.nio.channels.ClosedChannelException;
|
||||
import java.nio.channels.SelectionKey;
|
||||
import java.nio.channels.Selector;
|
||||
import java.nio.channels.ServerSocketChannel;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Semaphore;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class NioSocketReaderTests {
|
||||
|
||||
private CountDownLatch latch = new CountDownLatch(1);
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadLength() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendLength(port, latch);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
int count = 0;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
count++;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertEquals("Did not receive data", 2, count);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFragmented() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendFragmented(port, false);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
boolean done = false;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", "xx",
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
done = true;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertTrue("Did not receive data", done);
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadStxEtx() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendStxEtx(port, latch);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
int count = 0;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
count++;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertEquals("Did not receive data", 2, count);
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadCrLf() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendCrLf(port, latch);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
int count = 0;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[]) reader.getAssembledData()));
|
||||
count++;
|
||||
}
|
||||
latch.countDown();
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
}
|
||||
assertEquals("Did not receive data", 2, count);
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadLengthOverflow() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendLengthOverflow(port);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
int count = 0;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Message length")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadStxEtxOverflow() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendStxEtxOverflow(port);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
reader.setMaxMessageSize(1024);
|
||||
int count = 0;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("ETX not found")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadCrLfOverflow() throws Exception {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendCrLfOverflow(port);
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
reader.setMaxMessageSize(1024);
|
||||
int count = 0;
|
||||
while(selector.select(1000) > 0) {
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isReadable()) {
|
||||
assertEquals(channel, key.channel());
|
||||
try {
|
||||
if (reader.assembleData() == SocketReader.MESSAGE_COMPLETE) {
|
||||
fail("Expected message length exceeded exception");
|
||||
}
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("CRLF not found")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
count++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when no data received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testCloseCleanupNoData() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
semaphore.acquire();
|
||||
while (true) {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
semaphore.release();
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
semaphore.release();
|
||||
assertTrue(assembleData(reader) < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
channel = accept(server, selector);
|
||||
reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
semaphore.release();
|
||||
assertTrue(assembleData(reader) < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
channel = accept(server, selector);
|
||||
reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
semaphore.release();
|
||||
assertTrue(assembleData(reader) < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
channel = accept(server, selector);
|
||||
reader = new CustomNioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
semaphore.release();
|
||||
assertTrue(assembleData(reader) < 0);
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when mid-message
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testCloseCleanup() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
semaphore.acquire();
|
||||
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
byte[] header = {0, 0, 0, 10};
|
||||
socket.getOutputStream().write(header);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
|
||||
socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
|
||||
socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write(MessageFormats.STX);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
|
||||
socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write(MessageFormats.STX);
|
||||
socket.getOutputStream().write("xx".getBytes());
|
||||
semaphore.acquire();
|
||||
socket.close();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
try {
|
||||
ServerSocketChannel server = ServerSocketChannel.open();
|
||||
server.configureBlocking(false);
|
||||
server.socket().bind(new InetSocketAddress(port));
|
||||
final Selector selector = Selector.open();
|
||||
server.register(selector, SelectionKey.OP_ACCEPT);
|
||||
|
||||
semaphore.release();
|
||||
|
||||
SocketChannel channel = accept(server, selector);
|
||||
|
||||
NioSocketReader reader = new NioSocketReader(channel);
|
||||
semaphore.release();
|
||||
try {
|
||||
assembleData(reader);
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
channel = accept(server, selector);
|
||||
reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
semaphore.release();
|
||||
try {
|
||||
assembleData(reader);
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
channel = accept(server, selector);
|
||||
reader = new NioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
semaphore.release();
|
||||
try {
|
||||
assembleData(reader);
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
channel = accept(server, selector);
|
||||
reader = new CustomNioSocketReader(channel);
|
||||
reader.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
semaphore.release();
|
||||
try {
|
||||
assembleData(reader);
|
||||
fail("Exception expected");
|
||||
} catch (IOException e) { }
|
||||
assertTrue(reader.getSocket().isClosed());
|
||||
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
fail(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** Poor man's nio reader
|
||||
*
|
||||
* @param reader
|
||||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private int assembleData(NioSocketReader reader) throws Exception {
|
||||
int m = 0;
|
||||
while (true) {
|
||||
int n = reader.assembleData();
|
||||
if (n < 0) {
|
||||
return n;
|
||||
}
|
||||
Thread.sleep(10);
|
||||
if (m++ > 1000)
|
||||
throw new Exception("No close detected");
|
||||
}
|
||||
}
|
||||
|
||||
private SocketChannel accept(ServerSocketChannel server,
|
||||
final Selector selector) throws IOException, ClosedChannelException {
|
||||
SocketChannel channel = null;
|
||||
|
||||
if(selector.select(10000) <= 0) {
|
||||
fail("Socket failed to connect");
|
||||
}
|
||||
Set<SelectionKey> keys = selector.selectedKeys();
|
||||
Iterator<SelectionKey> iterator = keys.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
SelectionKey key = iterator.next();
|
||||
iterator.remove();
|
||||
if (key.isAcceptable()) {
|
||||
channel = server.accept();
|
||||
channel.configureBlocking(false);
|
||||
channel.register(selector, SelectionKey.OP_READ);
|
||||
}
|
||||
else {
|
||||
fail("Unexpected key: " + key);
|
||||
}
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:ip="http://www.springframework.org/schema/integration/ip"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/ip
|
||||
http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
|
||||
|
||||
<beans:bean id="tcpIpUtils" class="org.springframework.integration.ip.util.SocketUtils" />
|
||||
|
||||
<ip:inbound-gateway id="gatewayCrLf"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5200)}"
|
||||
request-channel="toSA"
|
||||
message-format="crlf" />
|
||||
|
||||
<ip:inbound-gateway id="gatewayStxEtx"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5300)}"
|
||||
request-channel="toSA"
|
||||
message-format="stx-etx" />
|
||||
|
||||
<ip:inbound-gateway id="gatewayLength"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5400)}"
|
||||
request-channel="toSA"
|
||||
message-format="length-header" />
|
||||
|
||||
<ip:inbound-gateway id="gatewaySerialized"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5450)}"
|
||||
request-channel="toSA"
|
||||
message-format="serialized" />
|
||||
|
||||
<ip:inbound-gateway id="gatewayCustom"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(5500)}"
|
||||
request-channel="toSA"
|
||||
message-format="custom"
|
||||
custom-socket-reader-class-name="org.springframework.integration.ip.tcp.CustomNetSocketReader"
|
||||
custom-socket-writer-class-name="org.springframework.integration.ip.tcp.CustomNetSocketWriter"/>
|
||||
|
||||
<channel id="toSA" />
|
||||
|
||||
<service-activator id="SA"
|
||||
input-channel="toSA"
|
||||
ref="service"
|
||||
method="test"
|
||||
/>
|
||||
|
||||
<beans:bean id="service" class="org.springframework.integration.ip.tcp.TestService" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* 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.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class SimpleTcpNetInboundGatewayTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayCrLf")
|
||||
SimpleTcpNetInboundGateway gatewayCrLf;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayStxEtx")
|
||||
SimpleTcpNetInboundGateway gatewayStxEtx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayLength")
|
||||
SimpleTcpNetInboundGateway gatewayLength;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewaySerialized")
|
||||
SimpleTcpNetInboundGateway gatewaySerialized;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayCustom")
|
||||
SimpleTcpNetInboundGateway gatewayCustom;
|
||||
|
||||
@Test @Ignore
|
||||
public void testCrLf() throws Exception {
|
||||
waitListening(gatewayCrLf);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayCrLf.getPort());
|
||||
socket.setSoTimeout(5000);
|
||||
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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStxEtx() throws Exception {
|
||||
waitListening(gatewayStxEtx);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayStxEtx.getPort());
|
||||
socket.setSoTimeout(5000);
|
||||
String greetings = "Hello World!";
|
||||
socket.getOutputStream().write(MessageFormats.STX);
|
||||
socket.getOutputStream().write((greetings).getBytes());
|
||||
socket.getOutputStream().write(MessageFormats.ETX);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
while (true) {
|
||||
c = socket.getInputStream().read();
|
||||
if (c == MessageFormats.STX) {
|
||||
continue;
|
||||
}
|
||||
if (c == MessageFormats.ETX) {
|
||||
break;
|
||||
}
|
||||
sb.append((char) c);
|
||||
}
|
||||
assertEquals("echo:" + greetings, sb.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerialized() throws Exception {
|
||||
waitListening(gatewaySerialized);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewaySerialized.getPort());
|
||||
socket.setSoTimeout(5000);
|
||||
String greetings = "Hello World!";
|
||||
new ObjectOutputStream(socket.getOutputStream()).writeObject(greetings);
|
||||
String echo = (String) new ObjectInputStream(socket.getInputStream()).readObject();
|
||||
assertEquals("echo:" + greetings, echo);
|
||||
}
|
||||
|
||||
@Test @Ignore
|
||||
public void testLength() throws Exception {
|
||||
waitListening(gatewayLength);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayLength.getPort());
|
||||
socket.setSoTimeout(5000);
|
||||
String greetings = "Hello World!";
|
||||
byte[] header = new byte[4];
|
||||
header[3] = (byte) greetings.length();
|
||||
socket.getOutputStream().write(header);
|
||||
socket.getOutputStream().write((greetings).getBytes());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
int n = 0;
|
||||
int size = 0;
|
||||
while (true) {
|
||||
c = socket.getInputStream().read();
|
||||
if (n++ < 3) {
|
||||
continue;
|
||||
}
|
||||
if (n == 4) {
|
||||
size = c;
|
||||
continue;
|
||||
}
|
||||
sb.append((char) c);
|
||||
if (n - 4 >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEquals("echo:" + greetings, sb.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCustom() throws Exception {
|
||||
waitListening(gatewayCustom);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", gatewayCustom.getPort());
|
||||
String greetings = "Hello World!";
|
||||
String pad = " ";
|
||||
socket.getOutputStream().write((greetings).getBytes());
|
||||
socket.getOutputStream().write(pad.getBytes());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
int n = 0;
|
||||
int size = 24; // custom format is fixed 24 bytes
|
||||
while (true) {
|
||||
c = socket.getInputStream().read();
|
||||
sb.append((char) c);
|
||||
if (++n >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEquals("echo:" + greetings, sb.toString().trim());
|
||||
}
|
||||
|
||||
private void waitListening(SimpleTcpNetInboundGateway gateway) throws Exception {
|
||||
int n = 0;
|
||||
while (!gateway.isListening()) {
|
||||
Thread.sleep(100);
|
||||
if (n++ > 100) {
|
||||
throw new Exception("Gateway failed to listen");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,242 +0,0 @@
|
||||
/*
|
||||
* 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 static org.junit.Assert.fail;
|
||||
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.core.SubscribableChannel;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class SimpleTcpNetOutboundGatewayTests {
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayCrLf")
|
||||
private SimpleTcpNetInboundGateway inboundGatewayCrLf;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayStxEtx")
|
||||
private SimpleTcpNetInboundGateway inboundGatewayStxEtx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayLength")
|
||||
private SimpleTcpNetInboundGateway inboundGatewayLength;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewaySerialized")
|
||||
private SimpleTcpNetInboundGateway inboundGatewaySerialized;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayCustom")
|
||||
private SimpleTcpNetInboundGateway inboundGatewayCustom;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("requestChannel")
|
||||
SubscribableChannel requestChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("replyChannel")
|
||||
PollableChannel replyChannel;
|
||||
|
||||
@Test
|
||||
public void testOutboundCrLf() throws Exception {
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", inboundGatewayCrLf.getPort());
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
waitListening(inboundGatewayCrLf);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
byte[] bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("echo:test", new String(bytes));
|
||||
}
|
||||
|
||||
private void waitListening(SimpleTcpNetInboundGateway gateway) throws Exception {
|
||||
int n = 0;
|
||||
while (!gateway.isListening()) {
|
||||
Thread.sleep(100);
|
||||
if (n++ > 100) {
|
||||
throw new Exception("Gateway failed to listen");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundStxEtx() throws Exception {
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", inboundGatewayStxEtx.getPort());
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
waitListening(inboundGatewayStxEtx);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
byte[] bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("echo:test", new String(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundSerialized() throws Exception {
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", inboundGatewaySerialized.getPort());
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
|
||||
waitListening(inboundGatewaySerialized);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
Object response = gateway.handleRequestMessage(message);
|
||||
assertEquals("echo:test", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundLength() throws Exception {
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", inboundGatewayLength.getPort());
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_LENGTH_HEADER);
|
||||
waitListening(inboundGatewayLength);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
byte[] bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("echo:test", new String(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundCustom() throws Exception {
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", inboundGatewayCustom.getPort());
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
gateway.setCustomSocketReaderClassName("org.springframework.integration.ip.tcp.CustomNetSocketReader");
|
||||
gateway.setCustomSocketWriterClassName("org.springframework.integration.ip.tcp.CustomNetSocketWriter");
|
||||
waitListening(inboundGatewayCustom);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
byte[] bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("echo:test", new String(bytes).trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundUsingConfig() {
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
requestChannel.send(message);
|
||||
byte[] bytes = (byte[]) replyChannel.receive().getPayload();
|
||||
assertEquals("echo:test", new String(bytes).trim());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundClose() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final Semaphore semaphore1 = new Semaphore(0);
|
||||
final Semaphore semaphore2 = new Semaphore(0);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(port, 10);
|
||||
semaphore1.release();
|
||||
while (true) {
|
||||
Socket s = ss.accept();
|
||||
byte[] b = new byte[1024];
|
||||
s.getInputStream().read(b);
|
||||
s.getOutputStream().write("OK\r\n".getBytes());
|
||||
semaphore2.acquire();
|
||||
s.close();
|
||||
semaphore1.release();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}});
|
||||
t.start();
|
||||
if (!semaphore1.tryAcquire(2000, TimeUnit.MILLISECONDS)) {
|
||||
fail("Server not ready");
|
||||
}
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", port);
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
gateway.setClose(true);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
byte[] bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("OK", new String(bytes));
|
||||
semaphore2.release();
|
||||
if (!semaphore1.tryAcquire(2000, TimeUnit.MILLISECONDS)) {
|
||||
fail("Server failed to close");
|
||||
}
|
||||
bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("OK", new String(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundCloseOnTimeout() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final Semaphore semaphore1 = new Semaphore(0);
|
||||
final Semaphore semaphore2 = new Semaphore(0);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket ss = ServerSocketFactory.getDefault().createServerSocket(port, 10);
|
||||
semaphore1.release();
|
||||
boolean first = true;
|
||||
while (true) {
|
||||
Socket s = ss.accept();
|
||||
byte[] b = new byte[1024];
|
||||
s.getInputStream().read(b);
|
||||
if (!first)
|
||||
s.getOutputStream().write("OK\r\n".getBytes());
|
||||
first = false;
|
||||
semaphore2.acquire();
|
||||
s.close();
|
||||
semaphore1.release();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}});
|
||||
t.start();
|
||||
if (!semaphore1.tryAcquire(2000, TimeUnit.MILLISECONDS)) {
|
||||
fail("Server not ready");
|
||||
}
|
||||
SimpleTcpNetOutboundGateway gateway = new SimpleTcpNetOutboundGateway
|
||||
("localhost", port);
|
||||
gateway.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
gateway.setClose(false);
|
||||
gateway.setSoTimeout(500);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
try {
|
||||
gateway.handleRequestMessage(message);
|
||||
fail("Expected failure");
|
||||
} catch (Exception e) { }
|
||||
semaphore2.release();
|
||||
if (!semaphore1.tryAcquire(2000, TimeUnit.MILLISECONDS)) {
|
||||
fail("Server failed to close");
|
||||
}
|
||||
byte[] bytes = (byte[]) gateway.handleRequestMessage(message);
|
||||
assertEquals("OK", new String(bytes));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans:beans xmlns="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:beans="http://www.springframework.org/schema/beans"
|
||||
xmlns:ip="http://www.springframework.org/schema/integration/ip"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/ip
|
||||
http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
|
||||
|
||||
<beans:import resource="common-context.xml" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewayCrLf"
|
||||
connection-factory="crLfServer"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewayStxEtx"
|
||||
connection-factory="stxEtxServer"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewayLength"
|
||||
connection-factory="lengthHeaderServer"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewaySerialized"
|
||||
connection-factory="javaSerialServer"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewayCrLfNio"
|
||||
connection-factory="crLfServerNio"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewayStxEtxNio"
|
||||
connection-factory="stxEtxServerNio"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewayLengthNio"
|
||||
connection-factory="lengthHeaderServerNio"
|
||||
request-channel="toSA" />
|
||||
|
||||
<ip:tcp-inbound-gateway id="gatewaySerializedNio"
|
||||
connection-factory="javaSerialServerNio"
|
||||
request-channel="toSA" />
|
||||
|
||||
<channel id="toSA" />
|
||||
|
||||
<service-activator id="SA"
|
||||
input-channel="toSA"
|
||||
ref="service"
|
||||
method="test"
|
||||
/>
|
||||
|
||||
<beans:bean id="service" class="org.springframework.integration.ip.tcp.TestService" />
|
||||
|
||||
</beans:beans>
|
||||
@@ -0,0 +1,302 @@
|
||||
/*
|
||||
* 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.io.IOException;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.net.Socket;
|
||||
import java.net.SocketException;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayStxEtxConverter;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class TcpConfigInboundGatewayTests {
|
||||
|
||||
static AbstractApplicationContext staticContext;
|
||||
|
||||
@Autowired
|
||||
AbstractApplicationContext ctx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="crLfServer")
|
||||
AbstractServerConnectionFactory crLfServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="stxEtxServer")
|
||||
AbstractServerConnectionFactory stxEtxServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="lengthHeaderServer")
|
||||
AbstractServerConnectionFactory lengthHeaderServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="javaSerialServer")
|
||||
AbstractServerConnectionFactory javaSerialServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="crLfClient")
|
||||
AbstractClientConnectionFactory crLfClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="stxEtxClient")
|
||||
AbstractClientConnectionFactory stxEtxClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="lengthHeaderClient")
|
||||
AbstractClientConnectionFactory lengthHeaderClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="javaSerialClient")
|
||||
AbstractClientConnectionFactory javaSerialClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="crLfServerNio")
|
||||
AbstractServerConnectionFactory crLfServerNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="stxEtxServerNio")
|
||||
AbstractServerConnectionFactory stxEtxServerNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="lengthHeaderServerNio")
|
||||
AbstractServerConnectionFactory lengthHeaderServerNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="javaSerialServerNio")
|
||||
AbstractServerConnectionFactory javaSerialServerNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="crLfClientNio")
|
||||
AbstractClientConnectionFactory crLfClientNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="stxEtxClientNio")
|
||||
AbstractClientConnectionFactory stxEtxClientNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="lengthHeaderClientNio")
|
||||
AbstractClientConnectionFactory lengthHeaderClientNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="javaSerialClientNio")
|
||||
AbstractClientConnectionFactory javaSerialClientNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayCrLf")
|
||||
TcpInboundGateway gatewayCrLf;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayStxEtx")
|
||||
TcpInboundGateway gatewayStxEtx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayLength")
|
||||
TcpInboundGateway gatewayLength;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewaySerialized")
|
||||
TcpInboundGateway gatewaySerialized;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayCrLfNio")
|
||||
TcpInboundGateway gatewayCrLfNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayStxEtxNio")
|
||||
TcpInboundGateway gatewayStxEtxNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayLengthNio")
|
||||
TcpInboundGateway gatewayLengthNio;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewaySerializedNio")
|
||||
TcpInboundGateway gatewaySerializedNio;
|
||||
|
||||
@Test
|
||||
public void testCrLf() throws Exception {
|
||||
waitListening(gatewayCrLf);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", crLfServer.getPort());
|
||||
crLfGuts(socket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCrLfNio() throws Exception {
|
||||
waitListening(gatewayCrLf);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", crLfServer.getPort());
|
||||
crLfGuts(socket);
|
||||
}
|
||||
|
||||
private void crLfGuts(Socket socket) throws SocketException, IOException {
|
||||
socket.setSoTimeout(5000);
|
||||
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());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStxEtx() throws Exception {
|
||||
waitListening(gatewayStxEtx);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", stxEtxServer.getPort());
|
||||
stxEtxGuts(socket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStxEtxNio() throws Exception {
|
||||
waitListening(gatewayStxEtxNio);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", stxEtxServerNio.getPort());
|
||||
stxEtxGuts(socket);
|
||||
}
|
||||
|
||||
private void stxEtxGuts(Socket socket) throws SocketException, IOException {
|
||||
socket.setSoTimeout(5000);
|
||||
String greetings = "Hello World!";
|
||||
socket.getOutputStream().write(ByteArrayStxEtxConverter.STX);
|
||||
socket.getOutputStream().write((greetings).getBytes());
|
||||
socket.getOutputStream().write(ByteArrayStxEtxConverter.ETX);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
while (true) {
|
||||
c = socket.getInputStream().read();
|
||||
if (c == ByteArrayStxEtxConverter.STX) {
|
||||
continue;
|
||||
}
|
||||
if (c == ByteArrayStxEtxConverter.ETX) {
|
||||
break;
|
||||
}
|
||||
sb.append((char) c);
|
||||
}
|
||||
assertEquals("echo:" + greetings, sb.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerialized() throws Exception {
|
||||
waitListening(gatewaySerialized);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", javaSerialServer.getPort());
|
||||
serializedGuts(socket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSerializedNio() throws Exception {
|
||||
waitListening(gatewaySerializedNio);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", javaSerialServerNio.getPort());
|
||||
serializedGuts(socket);
|
||||
}
|
||||
|
||||
private void serializedGuts(Socket socket) throws SocketException,
|
||||
IOException, ClassNotFoundException {
|
||||
socket.setSoTimeout(5000);
|
||||
String greetings = "Hello World!";
|
||||
new ObjectOutputStream(socket.getOutputStream()).writeObject(greetings);
|
||||
String echo = (String) new ObjectInputStream(socket.getInputStream()).readObject();
|
||||
assertEquals("echo:" + greetings, echo);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLength() throws Exception {
|
||||
waitListening(gatewayLength);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", lengthHeaderServer.getPort());
|
||||
lengthGuts(socket);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLengthNio() throws Exception {
|
||||
waitListening(gatewayLengthNio);
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", lengthHeaderServerNio.getPort());
|
||||
lengthGuts(socket);
|
||||
}
|
||||
|
||||
private void lengthGuts(Socket socket) throws SocketException, IOException {
|
||||
socket.setSoTimeout(5000);
|
||||
String greetings = "Hello World!";
|
||||
byte[] header = new byte[4];
|
||||
header[3] = (byte) greetings.length();
|
||||
socket.getOutputStream().write(header);
|
||||
socket.getOutputStream().write((greetings).getBytes());
|
||||
StringBuilder sb = new StringBuilder();
|
||||
int c;
|
||||
int n = 0;
|
||||
int size = 0;
|
||||
while (true) {
|
||||
c = socket.getInputStream().read();
|
||||
if (n++ < 3) {
|
||||
continue;
|
||||
}
|
||||
if (n == 4) {
|
||||
size = c;
|
||||
continue;
|
||||
}
|
||||
sb.append((char) c);
|
||||
if (n - 4 >= size) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
assertEquals("echo:" + greetings, sb.toString());
|
||||
}
|
||||
|
||||
private void waitListening(TcpInboundGateway gateway) throws Exception {
|
||||
int n = 0;
|
||||
while (!gateway.isListening()) {
|
||||
Thread.sleep(100);
|
||||
if (n++ > 100) {
|
||||
throw new Exception("Gateway failed to listen");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void copyContext() {
|
||||
if (staticContext == null) {
|
||||
staticContext = ctx;
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutDown() {
|
||||
staticContext.close();
|
||||
}
|
||||
}
|
||||
@@ -10,16 +10,20 @@
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<import resource="SimpleTcpNetInboundGatewayTests-context.xml" />
|
||||
<import resource="TcpConfigInboundGatewayTests-context.xml" />
|
||||
|
||||
<ip:outbound-gateway id="tcpOutGateway"
|
||||
host="localhost"
|
||||
port="#{gatewayCrLf.port}"
|
||||
message-format="crlf"
|
||||
<ip:tcp-outbound-gateway id="tcpOutGateway"
|
||||
connection-factory="crLfClient"
|
||||
request-channel="requestChannel"
|
||||
reply-channel="replyChannel"
|
||||
/>
|
||||
|
||||
<ip:tcp-outbound-gateway id="tcpOutGatewayNio"
|
||||
connection-factory="crLfClientNio"
|
||||
request-channel="requestChannelNio"
|
||||
reply-channel="replyChannel"
|
||||
/>
|
||||
|
||||
<int:channel id="replyChannel" >
|
||||
<int:queue />
|
||||
</int:channel>
|
||||
@@ -0,0 +1,192 @@
|
||||
/*
|
||||
* 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 org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.support.AbstractApplicationContext;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.core.PollableChannel;
|
||||
import org.springframework.integration.core.SubscribableChannel;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public class TcpConfigOutboundGatewayTests {
|
||||
|
||||
static AbstractApplicationContext staticContext;
|
||||
|
||||
@Autowired
|
||||
AbstractApplicationContext ctx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="crLfServer")
|
||||
AbstractServerConnectionFactory crLfServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="stxEtxServer")
|
||||
AbstractServerConnectionFactory stxEtxServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="lengthHeaderServer")
|
||||
AbstractServerConnectionFactory lengthHeaderServer;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="javaSerialServer")
|
||||
AbstractServerConnectionFactory javaSerialServer;
|
||||
|
||||
@Autowired @Qualifier(value="crLfClient")
|
||||
AbstractClientConnectionFactory crLfClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="stxEtxClient")
|
||||
AbstractClientConnectionFactory stxEtxClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="lengthHeaderClient")
|
||||
AbstractClientConnectionFactory lengthHeaderClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="javaSerialClient")
|
||||
AbstractClientConnectionFactory javaSerialClient;
|
||||
|
||||
@Autowired
|
||||
@Qualifier(value="gatewayCrLf")
|
||||
TcpInboundGateway gatewayCrLf;
|
||||
|
||||
// @Autowired
|
||||
// @Qualifier("gatewayCrLf")
|
||||
// private TcpInboundGateway inboundGatewayCrLf;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayStxEtx")
|
||||
private TcpInboundGateway inboundGatewayStxEtx;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewayLength")
|
||||
private TcpInboundGateway inboundGatewayLength;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("gatewaySerialized")
|
||||
private TcpInboundGateway inboundGatewaySerialized;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("requestChannel")
|
||||
SubscribableChannel requestChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("replyChannel")
|
||||
PollableChannel replyChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("requestChannelNio")
|
||||
SubscribableChannel requestChannelNio;
|
||||
|
||||
@Test
|
||||
public void testOutboundCrLf() throws Exception {
|
||||
testOutboundUsingConfig();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundCrLfNio() throws Exception {
|
||||
testOutboundUsingConfigNio();
|
||||
}
|
||||
|
||||
private void waitListening(TcpInboundGateway gateway) throws Exception {
|
||||
int n = 0;
|
||||
while (!gateway.isListening()) {
|
||||
Thread.sleep(100);
|
||||
if (n++ > 100) {
|
||||
throw new Exception("Gateway failed to listen");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundStxEtx() throws Exception {
|
||||
TcpOutboundGateway gateway = new TcpOutboundGateway();
|
||||
gateway.setConnectionFactory(stxEtxClient);
|
||||
waitListening(inboundGatewayStxEtx);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
@SuppressWarnings("unchecked")
|
||||
byte[] bytes = ((Message<byte[]>) gateway.handleRequestMessage(message)).getPayload();
|
||||
assertEquals("echo:test", new String(bytes));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundSerialized() throws Exception {
|
||||
TcpOutboundGateway gateway = new TcpOutboundGateway();
|
||||
gateway.setConnectionFactory(javaSerialClient);
|
||||
waitListening(inboundGatewaySerialized);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
@SuppressWarnings("unchecked")
|
||||
Object response = ((Message<Object>) gateway.handleRequestMessage(message)).getPayload();
|
||||
assertEquals("echo:test", response);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOutboundLength() throws Exception {
|
||||
TcpOutboundGateway gateway = new TcpOutboundGateway();
|
||||
gateway.setConnectionFactory(lengthHeaderClient);
|
||||
waitListening(inboundGatewayLength);
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
@SuppressWarnings("unchecked")
|
||||
byte[] bytes = ((Message<byte[]>) gateway.handleRequestMessage(message)).getPayload();
|
||||
assertEquals("echo:test", new String(bytes));
|
||||
}
|
||||
|
||||
private void testOutboundUsingConfig() {
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
requestChannel.send(message);
|
||||
byte[] bytes = (byte[]) replyChannel.receive().getPayload();
|
||||
assertEquals("echo:test", new String(bytes).trim());
|
||||
}
|
||||
|
||||
private void testOutboundUsingConfigNio() {
|
||||
Message<String> message = MessageBuilder.withPayload("test").build();
|
||||
requestChannelNio.send(message);
|
||||
byte[] bytes = (byte[]) replyChannel.receive().getPayload();
|
||||
assertEquals("echo:test", new String(bytes).trim());
|
||||
}
|
||||
|
||||
@Before
|
||||
public void copyContext() {
|
||||
if (staticContext == null) {
|
||||
staticContext = ctx;
|
||||
}
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void shutDown() {
|
||||
staticContext.close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -64,7 +64,7 @@ public class TcpOutboundGatewayTests {
|
||||
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port, 100);
|
||||
latch.countDown();
|
||||
int i = 0;
|
||||
while (true) {
|
||||
@@ -117,7 +117,7 @@ public class TcpOutboundGatewayTests {
|
||||
Executors.newSingleThreadExecutor().execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port, 10);
|
||||
latch.countDown();
|
||||
int i = 0;
|
||||
Socket socket = server.accept();
|
||||
@@ -214,6 +214,7 @@ public class TcpOutboundGatewayTests {
|
||||
try {
|
||||
results.get(i).get();
|
||||
} catch (InterruptedException e) {
|
||||
|
||||
} catch (ExecutionException e) {
|
||||
if (i == 0) {
|
||||
fail("Unexpected " + e.getMessage());
|
||||
|
||||
@@ -29,7 +29,6 @@ import java.util.HashSet;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
@@ -39,7 +38,6 @@ import org.junit.Test;
|
||||
import org.springframework.commons.serializer.java.JavaStreamingConverter;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.channel.QueueChannel;
|
||||
import org.springframework.integration.ip.AbstractInternetProtocolReceivingChannelAdapter;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.HelloWorldInterceptorFactory;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactory;
|
||||
@@ -48,7 +46,6 @@ import org.springframework.integration.ip.tcp.connection.TcpNetServerConnectionF
|
||||
import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayCrLfConverter;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -56,186 +53,6 @@ import org.springframework.scheduling.concurrent.ThreadPoolTaskScheduler;
|
||||
*/
|
||||
public class TcpReceivingChannelAdapterTests {
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.TcpNetReceivingChannelAdapter#run()}.
|
||||
*/
|
||||
@Test
|
||||
public void testNet() throws Exception {
|
||||
QueueChannel channel = new QueueChannel(2);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
AbstractInternetProtocolReceivingChannelAdapter adapter = new TcpNetReceivingChannelAdapter(port);
|
||||
adapter.setOutputChannel(channel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
SocketUtils.setLocalNicIfPossible(adapter);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
SocketUtils.testSendLength(port, null); //sends 2 copies of TEST_STRING twice
|
||||
Message<?> message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.TcpNetReceivingChannelAdapter#run()}.
|
||||
* Verifies operation of custom message formats.
|
||||
*/
|
||||
@Test
|
||||
public void testNetCustom() throws Exception {
|
||||
QueueChannel channel = new QueueChannel(2);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
TcpNetReceivingChannelAdapter adapter = new TcpNetReceivingChannelAdapter(port);
|
||||
adapter.setOutputChannel(channel);
|
||||
adapter.setCustomSocketReaderClassName("org.springframework.integration.ip.tcp.CustomNetSocketReader");
|
||||
adapter.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
SocketUtils.testSendStxEtx(port, null); //sends 2 copies of TEST_STRING twice
|
||||
Message<?> message = channel.receive(4000);
|
||||
assertNotNull(message);
|
||||
assertEquals("\u0002" + SocketUtils.TEST_STRING + SocketUtils.TEST_STRING + "\u0003",
|
||||
new String((byte[])message.getPayload()));
|
||||
message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals("\u0002" + SocketUtils.TEST_STRING + SocketUtils.TEST_STRING + "\u0003",
|
||||
new String((byte[])message.getPayload()));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.TcpNioReceivingChannelAdapter#run()}.
|
||||
*/
|
||||
@Test
|
||||
public void testNio() throws Exception {
|
||||
QueueChannel channel = new QueueChannel(2);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
TcpNioReceivingChannelAdapter adapter = new TcpNioReceivingChannelAdapter(port);
|
||||
adapter.setOutputChannel(channel);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
SocketUtils.setLocalNicIfPossible(adapter);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
SocketUtils.testSendLength(port, null); //sends 2 copies of TEST_STRING twice
|
||||
Message<?> message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.TcpNioReceivingChannelAdapter#run()}.
|
||||
* Verifies operation of custom message formats. */
|
||||
@Test
|
||||
public void testNioCustom() throws Exception {
|
||||
QueueChannel channel = new QueueChannel(2);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
TcpNioReceivingChannelAdapter adapter = new TcpNioReceivingChannelAdapter(port);
|
||||
adapter.setOutputChannel(channel);
|
||||
adapter.setCustomSocketReaderClassName("org.springframework.integration.ip.tcp.CustomNioSocketReader");
|
||||
adapter.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
SocketUtils.testSendStxEtx(port, null); //sends 2 copies of TEST_STRING twice
|
||||
Message<?> message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals("\u0002" + SocketUtils.TEST_STRING + SocketUtils.TEST_STRING + "\u0003",
|
||||
new String((byte[])message.getPayload()));
|
||||
message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals("\u0002" + SocketUtils.TEST_STRING + SocketUtils.TEST_STRING + "\u0003",
|
||||
new String((byte[])message.getPayload()));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests close option on inbound adapter.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testNetClose() throws Exception {
|
||||
QueueChannel channel = new QueueChannel(2);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
AbstractTcpReceivingChannelAdapter adapter = new TcpNetReceivingChannelAdapter(port);
|
||||
adapter.setOutputChannel(channel);
|
||||
adapter.setClose(true);
|
||||
adapter.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
SocketUtils.testSendCrLfSingle(port, latch);
|
||||
Message<?> message = channel.receive(5000);
|
||||
latch.countDown();
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
latch = new CountDownLatch(1);
|
||||
SocketUtils.testSendCrLfSingle(port, latch);
|
||||
message = channel.receive(5000);
|
||||
latch.countDown();
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests close option on inbound adapter.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testNioClose() throws Exception {
|
||||
QueueChannel channel = new QueueChannel(2);
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
AbstractTcpReceivingChannelAdapter adapter = new TcpNioReceivingChannelAdapter(port);
|
||||
adapter.setOutputChannel(channel);
|
||||
adapter.setClose(true);
|
||||
adapter.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
ThreadPoolTaskScheduler taskScheduler = new ThreadPoolTaskScheduler();
|
||||
taskScheduler.initialize();
|
||||
adapter.setTaskScheduler(taskScheduler);
|
||||
adapter.start();
|
||||
SocketUtils.waitListening(adapter);
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
SocketUtils.testSendCrLfSingle(port, latch);
|
||||
Message<?> message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
latch = new CountDownLatch(1);
|
||||
SocketUtils.testSendCrLfSingle(port, latch);
|
||||
message = channel.receive(2000);
|
||||
assertNotNull(message);
|
||||
assertEquals(SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String((byte[])message.getPayload()));
|
||||
adapter.stop();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void newTestNet() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
@@ -548,6 +365,7 @@ public class TcpReceivingChannelAdapterTests {
|
||||
scf.setInputConverter(converter);
|
||||
scf.setOutputConverter(converter);
|
||||
scf.setSingleUse(true);
|
||||
scf.setPoolSize(100);
|
||||
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
|
||||
handler.setConnectionFactory(scf);
|
||||
TcpReceivingChannelAdapter adapter = new TcpReceivingChannelAdapter();
|
||||
|
||||
@@ -60,167 +60,6 @@ import org.springframework.integration.ip.util.SocketUtils;
|
||||
*/
|
||||
public class TcpSendingMessageHandlerTests {
|
||||
|
||||
@Test
|
||||
public void testNet() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final String testString = "abcdef";
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
TcpNetSendingMessageHandler handler = new TcpNetSendingMessageHandler("localhost", port);
|
||||
handler.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
Message<String> message = MessageBuilder.withPayload(testString).build();
|
||||
handler.handleMessage(message);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[testString.length() + 2];
|
||||
readFully(is, buff);
|
||||
assertEquals(MessageFormats.STX, buff[0]);
|
||||
assertEquals(testString, new String(buff, 1, testString.length()));
|
||||
assertEquals(MessageFormats.ETX, buff[testString.length() + 1]);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNetCustom() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final String testString = "abcdef";
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
TcpNetSendingMessageHandler handler = new TcpNetSendingMessageHandler("localhost", port);
|
||||
handler.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
handler.setCustomSocketWriterClassName("org.springframework.integration.ip.tcp.CustomNetSocketWriter");
|
||||
Message<String> message = MessageBuilder.withPayload(testString).build();
|
||||
handler.handleMessage(message);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[24];
|
||||
readFully(is, buff);
|
||||
assertEquals((testString + " ").substring(0, 24),
|
||||
new String(buff));
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNio() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final String testString = "abcdef";
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
TcpNioSendingMessageHandler handler = new TcpNioSendingMessageHandler("localhost", port);
|
||||
handler.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
Message<String> message = MessageBuilder.withPayload(testString).build();
|
||||
handler.handleMessage(message);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[testString.length() + 2];
|
||||
readFully(is, buff);
|
||||
assertEquals(MessageFormats.STX, buff[0]);
|
||||
assertEquals(testString, new String(buff, 1, testString.length()));
|
||||
assertEquals(MessageFormats.ETX, buff[testString.length() + 1]);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNioDirect() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final String testString = "abcdef";
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
TcpNioSendingMessageHandler handler = new TcpNioSendingMessageHandler("localhost", port);
|
||||
handler.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
handler.setUsingDirectBuffers(true);
|
||||
Message<String> message = MessageBuilder.withPayload(testString).build();
|
||||
handler.handleMessage(message);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[testString.length() + 2];
|
||||
readFully(is, buff);
|
||||
assertEquals(MessageFormats.STX, buff[0]);
|
||||
assertEquals(testString, new String(buff, 1, testString.length()));
|
||||
assertEquals(MessageFormats.ETX, buff[testString.length() + 1]);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNioCustom() throws Exception {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final String testString = "abcdef";
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
TcpNioSendingMessageHandler handler = new TcpNioSendingMessageHandler("localhost", port);
|
||||
handler.setMessageFormat(MessageFormats.FORMAT_CUSTOM);
|
||||
handler.setCustomSocketWriterClassName("org.springframework.integration.ip.tcp.CustomNioSocketWriter");
|
||||
Message<String> message = MessageBuilder.withPayload(testString).build();
|
||||
handler.handleMessage(message);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
});
|
||||
t.setDaemon(true);
|
||||
t.start();
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[24];
|
||||
readFully(is, buff);
|
||||
assertEquals((testString + " ").substring(0, 24),
|
||||
new String(buff));
|
||||
server.close();
|
||||
}
|
||||
|
||||
private void readFully(InputStream is, byte[] buff) throws IOException {
|
||||
for (int i = 0; i < buff.length; i++) {
|
||||
buff[i] = (byte) is.read();
|
||||
@@ -304,7 +143,7 @@ public class TcpSendingMessageHandlerTests {
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
ccf.setInputConverter(converter);
|
||||
ccf.setOutputConverter(converter);
|
||||
// ccf.setSoTimeout(10000);
|
||||
ccf.setSoTimeout(10000);
|
||||
ccf.start();
|
||||
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
|
||||
handler.setConnectionFactory(ccf);
|
||||
@@ -849,6 +688,7 @@ public class TcpSendingMessageHandlerTests {
|
||||
ccf.setOutputConverter(converter);
|
||||
ccf.setSoTimeout(10000);
|
||||
ccf.setSingleUse(true);
|
||||
ccf.setTaskExecutor(Executors.newFixedThreadPool(100));
|
||||
ccf.start();
|
||||
TcpSendingMessageHandler handler = new TcpSendingMessageHandler();
|
||||
handler.setConnectionFactory(ccf);
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns:int="http://www.springframework.org/schema/integration"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:ip="http://www.springframework.org/schema/integration/ip"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||
http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/integration
|
||||
http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/ip
|
||||
http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
|
||||
|
||||
<bean id="tcpIpUtils" class="org.springframework.integration.ip.util.SocketUtils" />
|
||||
|
||||
<bean id="crLfConverter" class="org.springframework.integration.ip.tcp.converter.ByteArrayCrLfConverter" />
|
||||
<bean id="stxEtxConverter" class="org.springframework.integration.ip.tcp.converter.ByteArrayStxEtxConverter" />
|
||||
<bean id="lengthHeaderConverter" class="org.springframework.integration.ip.tcp.converter.ByteArrayLengthHeaderConverter" />
|
||||
<bean id="javaConverter" class="org.springframework.commons.serializer.java.JavaStreamingConverter" />
|
||||
|
||||
<ip:tcp-connection-factory id="crLfServer"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6000)}"
|
||||
input-converter="crLfConverter"
|
||||
output-converter="crLfConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="stxEtxServer"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6100)}"
|
||||
input-converter="stxEtxConverter"
|
||||
output-converter="stxEtxConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="lengthHeaderServer"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6200)}"
|
||||
input-converter="lengthHeaderConverter"
|
||||
output-converter="lengthHeaderConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="javaSerialServer"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6300)}"
|
||||
input-converter="javaConverter"
|
||||
output-converter="javaConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="crLfClient"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{crLfServer.port}"
|
||||
input-converter="crLfConverter"
|
||||
output-converter="crLfConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="stxEtxClient"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{stxEtxServer.port}"
|
||||
input-converter="stxEtxConverter"
|
||||
output-converter="stxEtxConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="lengthHeaderClient"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{lengthHeaderServer.port}"
|
||||
input-converter="lengthHeaderConverter"
|
||||
output-converter="lengthHeaderConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="javaSerialClient"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{javaSerialServer.port}"
|
||||
input-converter="javaConverter"
|
||||
output-converter="javaConverter"/>
|
||||
|
||||
<ip:tcp-connection-factory id="crLfServerNio"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6400)}"
|
||||
input-converter="crLfConverter"
|
||||
output-converter="crLfConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="stxEtxServerNio"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6500)}"
|
||||
input-converter="stxEtxConverter"
|
||||
output-converter="stxEtxConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="lengthHeaderServerNio"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6600)}"
|
||||
input-converter="lengthHeaderConverter"
|
||||
output-converter="lengthHeaderConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="javaSerialServerNio"
|
||||
type="server"
|
||||
port="#{tcpIpUtils.findAvailableServerSocket(6700)}"
|
||||
input-converter="javaConverter"
|
||||
output-converter="javaConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="crLfClientNio"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{crLfServer.port}"
|
||||
input-converter="crLfConverter"
|
||||
output-converter="crLfConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="stxEtxClientNio"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{stxEtxServer.port}"
|
||||
input-converter="stxEtxConverter"
|
||||
output-converter="stxEtxConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="lengthHeaderClientNio"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{lengthHeaderServer.port}"
|
||||
input-converter="lengthHeaderConverter"
|
||||
output-converter="lengthHeaderConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
<ip:tcp-connection-factory id="javaSerialClientNio"
|
||||
type="client"
|
||||
host="localhost"
|
||||
port="#{javaSerialServer.port}"
|
||||
input-converter="javaConverter"
|
||||
output-converter="javaConverter"
|
||||
using-nio="true"/>
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -23,7 +23,6 @@ import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.MessagingException;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.tcp.connection.AbstractTcpConnectionInterceptor;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package org.springframework.integration.ip.tcp.connection;
|
||||
|
||||
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactory;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
|
||||
@@ -13,25 +13,24 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.ip.tcp;
|
||||
package org.springframework.integration.ip.tcp.connection;
|
||||
|
||||
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 static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.IpHeaders;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpConnection;
|
||||
import org.springframework.integration.ip.tcp.connection.TcpMessageMapper;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class SocketMessageMapperTests {
|
||||
public class TcpMessageMapperTests {
|
||||
|
||||
/**
|
||||
*
|
||||
@@ -44,14 +43,20 @@ public class SocketMessageMapperTests {
|
||||
*/
|
||||
@Test
|
||||
public void testToMessage() throws Exception {
|
||||
SocketMessageMapper mapper = new SocketMessageMapper();
|
||||
Message<Object> message = mapper.toMessage(new StubSocketReader());
|
||||
|
||||
TcpMessageMapper mapper = new TcpMessageMapper();
|
||||
TcpConnection connection = mock(TcpConnection.class);
|
||||
when(connection.getPayload()).thenReturn(TEST_PAYLOAD.getBytes());
|
||||
when(connection.getHostName()).thenReturn("MyHost");
|
||||
when(connection.getHostAddress()).thenReturn("1.1.1.1");
|
||||
when(connection.getPort()).thenReturn(1234);
|
||||
Message<Object> message = mapper.toMessage(connection);
|
||||
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
|
||||
assertEquals(InetAddress.getLocalHost().getHostName(), message
|
||||
assertEquals("MyHost", message
|
||||
.getHeaders().get(IpHeaders.HOSTNAME));
|
||||
assertEquals(InetAddress.getLocalHost().getHostAddress(), message
|
||||
assertEquals("1.1.1.1", message
|
||||
.getHeaders().get(IpHeaders.IP_ADDRESS));
|
||||
assertEquals(0, message
|
||||
assertEquals(1234, message
|
||||
.getHeaders().get(IpHeaders.REMOTE_PORT));
|
||||
}
|
||||
|
||||
@@ -60,49 +65,26 @@ public class SocketMessageMapperTests {
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testFromMessage() throws Exception {
|
||||
public void testFromMessageBytes() throws Exception {
|
||||
String s = "test";
|
||||
Message<String> message = MessageBuilder.withPayload(s).build();
|
||||
SocketMessageMapper mapper = new SocketMessageMapper();
|
||||
TcpMessageMapper mapper = new TcpMessageMapper();
|
||||
mapper.setStringToBytes(true);
|
||||
byte[] bArray = (byte[]) mapper.fromMessage(message);
|
||||
assertEquals(s, new String(bArray));
|
||||
|
||||
}
|
||||
|
||||
|
||||
private class StubSocketReader implements SocketReader {
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getAddress()
|
||||
*/
|
||||
public InetAddress getAddress() {
|
||||
try {
|
||||
return InetAddress.getLocalHost();
|
||||
} catch (UnknownHostException e) {
|
||||
fail("Unexpected Exception: " + e.getMessage());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public byte[] getAssembledData() {
|
||||
return TEST_PAYLOAD.getBytes();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#assembleData()
|
||||
*/
|
||||
public int assembleData() {
|
||||
return SocketReader.MESSAGE_INCOMPLETE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.integration.ip.tcp.SocketReader#getSocket()
|
||||
*/
|
||||
public Socket getSocket() {
|
||||
return new Socket();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFromMessage() throws Exception {
|
||||
String s = "test";
|
||||
Message<String> message = MessageBuilder.withPayload(s).build();
|
||||
TcpMessageMapper mapper = new TcpMessageMapper();
|
||||
mapper.setStringToBytes(false);
|
||||
String out = (String) mapper.fromMessage(message);
|
||||
assertEquals(s, out);
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,426 @@
|
||||
/*
|
||||
* 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.connection;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Semaphore;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.ip.tcp.converter.AbstractByteArrayStreamingConverter;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayCrLfConverter;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayLengthHeaderConverter;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayStxEtxConverter;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class TcpNioConnectionReadTests {
|
||||
|
||||
private CountDownLatch latch = new CountDownLatch(1);
|
||||
|
||||
private AbstractServerConnectionFactory getConnectionFactory(int port,
|
||||
AbstractByteArrayStreamingConverter converter, TcpListener listener) throws Exception {
|
||||
return getConnectionFactory(port, converter, listener, null);
|
||||
}
|
||||
|
||||
private AbstractServerConnectionFactory getConnectionFactory(int port,
|
||||
AbstractByteArrayStreamingConverter converter, TcpListener listener, TcpSender sender) throws Exception {
|
||||
AbstractServerConnectionFactory scf = new TcpNioServerConnectionFactory(port);
|
||||
scf.setInputConverter(converter);
|
||||
scf.setOutputConverter(converter);
|
||||
scf.registerListener(listener);
|
||||
if (sender != null) {
|
||||
scf.registerSender(sender);
|
||||
}
|
||||
scf.start();
|
||||
int n = 0;
|
||||
while (!scf.isListening()) {
|
||||
Thread.sleep(100);
|
||||
if (n++ > 200) {
|
||||
fail("Failed to listen");
|
||||
}
|
||||
}
|
||||
return scf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testReadLength() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendLength(port, latch);
|
||||
latch.countDown();
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertEquals("Did not receive data", 2, responses.size());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(((Message<byte[]>) responses.get(0)).getPayload()));
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(((Message<byte[]>) responses.get(1)).getPayload()));
|
||||
scf.close();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testFragmented() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
SocketUtils.testSendFragmented(port, false);
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertEquals("Data", "xx",
|
||||
new String(((Message<byte[]>) responses.get(0)).getPayload()));
|
||||
assertEquals("Expected", 1, responses.size());
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testReadStxEtx() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendStxEtx(port, latch);
|
||||
latch.countDown();
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertEquals("Did not receive data", 2, responses.size());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(((Message<byte[]>) responses.get(0)).getPayload()));
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(((Message<byte[]>) responses.get(1)).getPayload()));
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Test
|
||||
public void testReadCrLf() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendCrLf(port, latch);
|
||||
latch.countDown();
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertTrue(semaphore.tryAcquire(1, 10000, TimeUnit.MILLISECONDS));
|
||||
assertEquals("Did not receive data", 2, responses.size());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(((Message<byte[]>) responses.get(0)).getPayload()));
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(((Message<byte[]>) responses.get(1)).getPayload()));
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadLengthOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final List<TcpConnection> added = new ArrayList<TcpConnection>();
|
||||
final List<TcpConnection> removed = new ArrayList<TcpConnection>();
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
}, new TcpSender() {
|
||||
public void addNewConnection(TcpConnection connection) {
|
||||
added.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
public void removeDeadConnection(TcpConnection connection) {
|
||||
removed.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendLengthOverflow(port);
|
||||
whileOpen(semaphore, added);
|
||||
assertEquals(1, added.size());
|
||||
assertTrue(removed.size() > 0);
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadStxEtxOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
converter.setMaxMessageSize(1024);
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final List<TcpConnection> added = new ArrayList<TcpConnection>();
|
||||
final List<TcpConnection> removed = new ArrayList<TcpConnection>();
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
}, new TcpSender() {
|
||||
public void addNewConnection(TcpConnection connection) {
|
||||
added.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
public void removeDeadConnection(TcpConnection connection) {
|
||||
removed.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendStxEtxOverflow(port);
|
||||
whileOpen(semaphore, added);
|
||||
assertEquals(1, added.size());
|
||||
assertTrue(removed.size() > 0);
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.springframework.integration.ip.tcp.NioSocketReader}.
|
||||
*/
|
||||
@Test
|
||||
public void testReadCrLfOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
converter.setMaxMessageSize(1024);
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final List<TcpConnection> added = new ArrayList<TcpConnection>();
|
||||
final List<TcpConnection> removed = new ArrayList<TcpConnection>();
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
}, new TcpSender() {
|
||||
public void addNewConnection(TcpConnection connection) {
|
||||
added.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
public void removeDeadConnection(TcpConnection connection) {
|
||||
removed.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
|
||||
// Fire up the sender.
|
||||
|
||||
SocketUtils.testSendCrLfOverflow(port);
|
||||
whileOpen(semaphore, added);
|
||||
assertEquals(1, added.size());
|
||||
assertTrue(removed.size() > 0);
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when no data received.
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testCloseCleanupNoData() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
converter.setMaxMessageSize(1024);
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final List<TcpConnection> added = new ArrayList<TcpConnection>();
|
||||
final List<TcpConnection> removed = new ArrayList<TcpConnection>();
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
semaphore.release();
|
||||
return false;
|
||||
}
|
||||
}, new TcpSender() {
|
||||
public void addNewConnection(TcpConnection connection) {
|
||||
added.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
public void removeDeadConnection(TcpConnection connection) {
|
||||
removed.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.close();
|
||||
whileOpen(semaphore, added);
|
||||
assertEquals(1, added.size());
|
||||
assertTrue(removed.size() > 0);
|
||||
scf.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when mid-message
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
@Test
|
||||
public void testCloseCleanupCrLf() throws Exception {
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
testClosureMidMessageGuts(converter, "xx");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when mid-message
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testCloseCleanupStxEtx() throws Exception {
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
testClosureMidMessageGuts(converter, ByteArrayStxEtxConverter.STX + "xx");
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests socket closure when mid-message
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
|
||||
@Test
|
||||
public void testCloseCleanupLengthHeader() throws Exception {
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
testClosureMidMessageGuts(converter, "\u0000\u0000\u0000\u0003xx");
|
||||
}
|
||||
|
||||
private void testClosureMidMessageGuts(AbstractByteArrayStreamingConverter converter, String shortMessage)
|
||||
throws Exception, IOException, UnknownHostException,
|
||||
InterruptedException {
|
||||
final int port = SocketUtils.findAvailableServerSocket();
|
||||
final List<Message<?>> responses = new ArrayList<Message<?>>();
|
||||
final Semaphore semaphore = new Semaphore(0);
|
||||
final List<TcpConnection> added = new ArrayList<TcpConnection>();
|
||||
final List<TcpConnection> removed = new ArrayList<TcpConnection>();
|
||||
AbstractServerConnectionFactory scf = getConnectionFactory(port, converter,new TcpListener() {
|
||||
public boolean onMessage(Message<?> message) {
|
||||
responses.add(message);
|
||||
return false;
|
||||
}
|
||||
}, new TcpSender() {
|
||||
public void addNewConnection(TcpConnection connection) {
|
||||
added.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
public void removeDeadConnection(TcpConnection connection) {
|
||||
removed.add(connection);
|
||||
semaphore.release();
|
||||
}
|
||||
});
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
socket.getOutputStream().write(shortMessage.getBytes());
|
||||
socket.close();
|
||||
whileOpen(semaphore, added);
|
||||
assertEquals(1, added.size());
|
||||
assertTrue(removed.size() > 0);
|
||||
scf.close();
|
||||
}
|
||||
|
||||
private void whileOpen(Semaphore semaphore, final List<TcpConnection> added)
|
||||
throws InterruptedException {
|
||||
int n = 0;
|
||||
assertTrue(semaphore.tryAcquire(10000, TimeUnit.MILLISECONDS));
|
||||
while (added.get(0).isOpen()) {
|
||||
Thread.sleep(50);
|
||||
if (n++ > 200) {
|
||||
fail("Failed to close socket");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import java.net.SocketTimeoutException;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
@@ -57,7 +58,6 @@ public class TcpNioConnectionTests {
|
||||
// block so we fill the buffer
|
||||
server.accept();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -90,7 +90,6 @@ public class TcpNioConnectionTests {
|
||||
// block to cause timeout on read.
|
||||
server.accept();
|
||||
} catch (Exception e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,102 +13,41 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.ip.tcp;
|
||||
package org.springframework.integration.ip.tcp.connection;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.nio.Buffer;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.channels.SocketChannel;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.tcp.converter.AbstractByteArrayStreamingConverter;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayCrLfConverter;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayLengthHeaderConverter;
|
||||
import org.springframework.integration.ip.tcp.converter.ByteArrayStxEtxConverter;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class NioSocketWriterTests {
|
||||
public class TcpNioConnectionWriteTests {
|
||||
|
||||
@Test
|
||||
public void testBuffersNoWait() throws Exception {
|
||||
NioSocketWriter writer = new NioSocketWriter(null, 2, 2048);
|
||||
ByteBuffer b1 = writer.getBuffer();
|
||||
ByteBuffer b2 = writer.getBuffer();
|
||||
writer.returnBuffer(b2);
|
||||
ByteBuffer b3 = writer.getBuffer();
|
||||
assertEquals(b2, b3);
|
||||
writer.returnBuffer(b3);
|
||||
writer.returnBuffer(b1);
|
||||
b3 = writer.getBuffer();
|
||||
assertEquals(b2, b3);
|
||||
writer.returnBuffer(b3);
|
||||
b3 = writer.getBuffer();
|
||||
assertEquals(b1, b3);
|
||||
writer.returnBuffer(b3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuffersWait() throws Exception {
|
||||
final NioSocketWriter writer = new NioSocketWriter(null, 2, 2048);
|
||||
ByteBuffer b1 = writer.getBuffer();
|
||||
ByteBuffer b2 = writer.getBuffer();
|
||||
final CountDownLatch latch1 = new CountDownLatch(1);
|
||||
final CountDownLatch latch2 = new CountDownLatch(1);
|
||||
final ByteBuffer b2a = b2;
|
||||
new Thread(new Runnable(){
|
||||
public void run() {
|
||||
latch1.countDown();
|
||||
try {
|
||||
ByteBuffer b = writer.getBuffer();
|
||||
assertEquals(b2a, b);
|
||||
writer.returnBuffer(b);
|
||||
latch2.countDown();
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
}).start();
|
||||
latch1.await();
|
||||
Thread.sleep(2000);
|
||||
writer.returnBuffer(b2);
|
||||
latch2.await();
|
||||
ByteBuffer b3 = writer.getBuffer();
|
||||
assertEquals(b2, b3);
|
||||
writer.returnBuffer(b3);
|
||||
writer.returnBuffer(b1);
|
||||
b3 = writer.getBuffer();
|
||||
assertEquals(b2, b3);
|
||||
writer.returnBuffer(b3);
|
||||
b3 = writer.getBuffer();
|
||||
assertEquals(b1, b3);
|
||||
writer.returnBuffer(b3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBuffersClear() throws Exception {
|
||||
NioSocketWriter writer = new NioSocketWriter(null, 2, 2048);
|
||||
ByteBuffer b1 = writer.getBuffer();
|
||||
b1.putInt(1);
|
||||
assertEquals(4, b1.position());
|
||||
b1.flip();
|
||||
assertEquals(0, b1.position());
|
||||
assertEquals(4, b1.limit());
|
||||
writer.returnBuffer(b1);
|
||||
Buffer b2 = writer.getBuffer();
|
||||
assertEquals(b1, b2);
|
||||
assertEquals(0, b2.position());
|
||||
assertEquals(2048, b2.limit());
|
||||
|
||||
private AbstractConnectionFactory getClientConnectionFactory(boolean direct,
|
||||
final int port, AbstractByteArrayStreamingConverter converter) {
|
||||
TcpNioClientConnectionFactory ccf = new TcpNioClientConnectionFactory("localhost", port);
|
||||
ccf.setInputConverter(converter);
|
||||
ccf.setOutputConverter(converter);
|
||||
ccf.setSoTimeout(10000);
|
||||
ccf.setUsingDirectBuffers(direct);
|
||||
ccf.start();
|
||||
return ccf;
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -121,16 +60,10 @@ public class NioSocketWriterTests {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer
|
||||
.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(new InetSocketAddress("localhost", port));
|
||||
NioSocketWriter writer = new NioSocketWriter(channel, 2,
|
||||
2048);
|
||||
writer
|
||||
.setMessageFormat(MessageFormats.FORMAT_LENGTH_HEADER);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
AbstractConnectionFactory ccf = getClientConnectionFactory(false, port, converter);
|
||||
TcpConnection connection = ccf.getConnection();
|
||||
connection.send(MessageBuilder.withPayload(testString.getBytes()).build());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -160,15 +93,10 @@ public class NioSocketWriterTests {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer
|
||||
.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(new InetSocketAddress("localhost", port));
|
||||
NioSocketWriter writer = new NioSocketWriter(channel, 2,
|
||||
2048);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
AbstractConnectionFactory ccf = getClientConnectionFactory(false, port, converter);
|
||||
TcpConnection connection = ccf.getConnection();
|
||||
connection.send(MessageBuilder.withPayload(testString.getBytes()).build());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -182,9 +110,9 @@ public class NioSocketWriterTests {
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[testString.length() + 2];
|
||||
readFully(is, buff);
|
||||
assertEquals(MessageFormats.STX, buff[0]);
|
||||
assertEquals(ByteArrayStxEtxConverter.STX, buff[0]);
|
||||
assertEquals(testString, new String(buff, 1, testString.length()));
|
||||
assertEquals(MessageFormats.ETX, buff[testString.length() + 1]);
|
||||
assertEquals(ByteArrayStxEtxConverter.ETX, buff[testString.length() + 1]);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@@ -198,15 +126,10 @@ public class NioSocketWriterTests {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer
|
||||
.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(new InetSocketAddress("localhost", port));
|
||||
NioSocketWriter writer = new NioSocketWriter(channel, 2,
|
||||
2048);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
AbstractConnectionFactory ccf = getClientConnectionFactory(false, port, converter);
|
||||
TcpConnection connection = ccf.getConnection();
|
||||
connection.send(MessageBuilder.withPayload(testString.getBytes()).build());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -236,17 +159,10 @@ public class NioSocketWriterTests {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer
|
||||
.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(new InetSocketAddress("localhost", port));
|
||||
NioSocketWriter writer = new NioSocketWriter(channel, 2,
|
||||
2048);
|
||||
writer
|
||||
.setMessageFormat(MessageFormats.FORMAT_LENGTH_HEADER);
|
||||
writer.setUsingDirectBuffers(true);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
AbstractConnectionFactory ccf = getClientConnectionFactory(true, port, converter);
|
||||
TcpConnection connection = ccf.getConnection();
|
||||
connection.send(MessageBuilder.withPayload(testString.getBytes()).build());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -276,16 +192,11 @@ public class NioSocketWriterTests {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer
|
||||
.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(new InetSocketAddress("localhost", port));
|
||||
NioSocketWriter writer = new NioSocketWriter(channel, 2,
|
||||
2048);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
writer.setUsingDirectBuffers(true);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
AbstractConnectionFactory ccf = getClientConnectionFactory(true, port, converter);
|
||||
TcpConnection connection = ccf.getConnection();
|
||||
connection.send(MessageBuilder.withPayload(testString.getBytes()).build());
|
||||
Thread.sleep(1000000000L);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -299,9 +210,9 @@ public class NioSocketWriterTests {
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[testString.length() + 2];
|
||||
readFully(is, buff);
|
||||
assertEquals(MessageFormats.STX, buff[0]);
|
||||
assertEquals(ByteArrayStxEtxConverter.STX, buff[0]);
|
||||
assertEquals(testString, new String(buff, 1, testString.length()));
|
||||
assertEquals(MessageFormats.ETX, buff[testString.length() + 1]);
|
||||
assertEquals(ByteArrayStxEtxConverter.ETX, buff[testString.length() + 1]);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@@ -315,16 +226,11 @@ public class NioSocketWriterTests {
|
||||
Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
ByteBuffer buffer = ByteBuffer
|
||||
.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
SocketChannel channel = SocketChannel
|
||||
.open(new InetSocketAddress("localhost", port));
|
||||
NioSocketWriter writer = new NioSocketWriter(channel, 2,
|
||||
2048);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
writer.setUsingDirectBuffers(true);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
AbstractConnectionFactory ccf = getClientConnectionFactory(true, port, converter);
|
||||
TcpConnection connection = ccf.getConnection();
|
||||
connection.send(MessageBuilder.withPayload(testString.getBytes()).build());
|
||||
Thread.sleep(1000000000L);
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* 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.converter;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.commons.serializer.java.JavaStreamingConverter;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class InputConverterTests {
|
||||
|
||||
@Test
|
||||
public void testReadLength() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendLength(port, null);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
byte[] out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(out));
|
||||
out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(out));
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadStxEtx() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendStxEtx(port, null);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
byte[] out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(out));
|
||||
out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(out));
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCrLf() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendCrLf(port, null);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
byte[] out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(out));
|
||||
out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING + SocketUtils.TEST_STRING,
|
||||
new String(out));
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadSerialized() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendSerialized(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
JavaStreamingConverter converter = new JavaStreamingConverter();
|
||||
Object out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING, out);
|
||||
out = converter.convert(socket.getInputStream());
|
||||
assertEquals("Data", SocketUtils.TEST_STRING, out);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadLengthOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendLengthOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
try {
|
||||
converter.convert(socket.getInputStream());
|
||||
fail("Expected message length exceeded exception");
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Message length")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadStxEtxTimeout() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendStxEtxOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(500);
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
try {
|
||||
converter.convert(socket.getInputStream());
|
||||
fail("Expected timeout exception");
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Read timed out")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadStxEtxOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendStxEtxOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
converter.setMaxMessageSize(1024);
|
||||
try {
|
||||
converter.convert(socket.getInputStream());
|
||||
fail("Expected message length exceeded exception");
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("ETX not found")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCrLfTimeout() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendCrLfOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(500);
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
try {
|
||||
converter.convert(socket.getInputStream());
|
||||
fail("Expected timout exception");
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("Read timed out")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReadCrLfOverflow() throws Exception {
|
||||
int port = SocketUtils.findAvailableServerSocket();
|
||||
ServerSocket server = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
server.setSoTimeout(10000);
|
||||
SocketUtils.testSendCrLfOverflow(port);
|
||||
Socket socket = server.accept();
|
||||
socket.setSoTimeout(5000);
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
converter.setMaxMessageSize(1024);
|
||||
try {
|
||||
converter.convert(socket.getInputStream());
|
||||
fail("Expected message length exceeded exception");
|
||||
} catch (IOException e) {
|
||||
if (!e.getMessage().startsWith("CRLF not found")) {
|
||||
e.printStackTrace();
|
||||
fail("Unexpected IO Error:" + e.getMessage());
|
||||
}
|
||||
}
|
||||
server.close();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,9 +13,9 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.ip.tcp;
|
||||
package org.springframework.integration.ip.tcp.converter;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
@@ -28,13 +28,14 @@ import javax.net.ServerSocketFactory;
|
||||
import javax.net.SocketFactory;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.springframework.commons.serializer.java.JavaStreamingConverter;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class NetSocketWriterTests {
|
||||
public class OutputConverterTests {
|
||||
|
||||
@Test
|
||||
public void testWriteLengthHeader() throws Exception {
|
||||
@@ -48,9 +49,8 @@ public class NetSocketWriterTests {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
NetSocketWriter writer = new NetSocketWriter(socket);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_LENGTH_HEADER);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayLengthHeaderConverter converter = new ByteArrayLengthHeaderConverter();
|
||||
converter.convert(buffer.array(), socket.getOutputStream());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -82,9 +82,8 @@ public class NetSocketWriterTests {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
NetSocketWriter writer = new NetSocketWriter(socket);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_STX_ETX);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayStxEtxConverter converter = new ByteArrayStxEtxConverter();
|
||||
converter.convert(buffer.array(), socket.getOutputStream());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -98,9 +97,9 @@ public class NetSocketWriterTests {
|
||||
InputStream is = socket.getInputStream();
|
||||
byte[] buff = new byte[testString.length() + 2];
|
||||
readFully(is, buff);
|
||||
assertEquals(MessageFormats.STX, buff[0]);
|
||||
assertEquals(ByteArrayStxEtxConverter.STX, buff[0]);
|
||||
assertEquals(testString, new String(buff, 1, testString.length()));
|
||||
assertEquals(MessageFormats.ETX, buff[testString.length() + 1]);
|
||||
assertEquals(ByteArrayStxEtxConverter.ETX, buff[testString.length() + 1]);
|
||||
server.close();
|
||||
}
|
||||
|
||||
@@ -116,9 +115,8 @@ public class NetSocketWriterTests {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
ByteBuffer buffer = ByteBuffer.allocate(testString.length());
|
||||
buffer.put(testString.getBytes());
|
||||
NetSocketWriter writer = new NetSocketWriter(socket);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_CRLF);
|
||||
writer.write(buffer.array());
|
||||
ByteArrayCrLfConverter converter = new ByteArrayCrLfConverter();
|
||||
converter.convert(buffer.array(), socket.getOutputStream());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -148,10 +146,9 @@ public class NetSocketWriterTests {
|
||||
public void run() {
|
||||
try {
|
||||
Socket socket = SocketFactory.getDefault().createSocket("localhost", port);
|
||||
NetSocketWriter writer = new NetSocketWriter(socket);
|
||||
writer.setMessageFormat(MessageFormats.FORMAT_JAVA_SERIALIZED);
|
||||
writer.write(testString);
|
||||
writer.write(testString);
|
||||
JavaStreamingConverter converter = new JavaStreamingConverter();
|
||||
converter.convert(testString, socket.getOutputStream());
|
||||
converter.convert(testString, socket.getOutputStream());
|
||||
Thread.sleep(1000000000L);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -165,6 +162,7 @@ public class NetSocketWriterTests {
|
||||
InputStream is = socket.getInputStream();
|
||||
ObjectInputStream ois = new ObjectInputStream(is);
|
||||
assertEquals(testString, ois.readObject());
|
||||
ois = new ObjectInputStream(is);
|
||||
assertEquals(testString, ois.readObject());
|
||||
server.close();
|
||||
}
|
||||
@@ -25,11 +25,9 @@ import java.net.InetSocketAddress;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.IpHeaders;
|
||||
import org.springframework.integration.ip.udp.DatagramPacketMessageMapper;
|
||||
import org.springframework.integration.mapping.MessageMappingException;
|
||||
|
||||
/**
|
||||
|
||||
@@ -32,13 +32,9 @@ import java.util.concurrent.TimeUnit;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.junit.Ignore;
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.Message;
|
||||
import org.springframework.integration.core.MessageBuilder;
|
||||
import org.springframework.integration.ip.IpHeaders;
|
||||
import org.springframework.integration.ip.udp.DatagramPacketMessageMapper;
|
||||
import org.springframework.integration.ip.udp.MulticastSendingMessageHandler;
|
||||
import org.springframework.integration.ip.udp.UnicastSendingMessageHandler;
|
||||
import org.springframework.integration.ip.util.SocketUtils;
|
||||
|
||||
/**
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
Play with the buffer size to force errors. If the checkLength property is
|
||||
set and this buffer is too small, we'll throw an exception.
|
||||
-->
|
||||
<ip:inbound-channel-adapter id="udpReceiver"
|
||||
<ip:udp-inbound-channel-adapter id="udpReceiver"
|
||||
channel="udpOutChannel"
|
||||
protocol="udp"
|
||||
port="11111"
|
||||
receive-buffer-size="500"
|
||||
multicast="false"
|
||||
|
||||
@@ -17,9 +17,8 @@
|
||||
Play with the buffer size to force errors. If the checkLength property is
|
||||
set and this buffer is too small, we'll throw an exception.
|
||||
-->
|
||||
<ip:inbound-channel-adapter id="mcUdpReceiver"
|
||||
<ip:udp-inbound-channel-adapter id="mcUdpReceiver"
|
||||
channel="udpOutChannel"
|
||||
protocol="udp"
|
||||
port="11112"
|
||||
receive-buffer-size="500"
|
||||
multicast="true"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
ref="testIp"
|
||||
method="testIp"/>
|
||||
|
||||
<ip:outbound-channel-adapter id="udpSender" protocol="udp"
|
||||
<ip:udp-outbound-channel-adapter id="udpSender"
|
||||
host="localhost"
|
||||
port="11111"
|
||||
check-length="true"
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
ref="testIp"
|
||||
method="testIp"/>
|
||||
|
||||
<ip:outbound-channel-adapter id="mcUdpSender" protocol="udp"
|
||||
<ip:udp-outbound-channel-adapter id="mcUdpSender"
|
||||
multicast="true"
|
||||
time-to-live="2"
|
||||
host="225.6.7.8"
|
||||
|
||||
@@ -20,7 +20,6 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.springframework.integration.ip.util.RegexUtils.escapeRegExSpecials;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import org.springframework.integration.MessageHeaders;
|
||||
|
||||
/**
|
||||
|
||||
@@ -19,12 +19,10 @@ import java.io.ObjectOutputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.DatagramSocket;
|
||||
import java.net.InetAddress;
|
||||
import java.net.NetworkInterface;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.util.Enumeration;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
@@ -263,6 +261,7 @@ public class SocketUtils {
|
||||
ObjectOutputStream oos = new ObjectOutputStream(outputStream);
|
||||
oos.writeObject(TEST_STRING);
|
||||
oos.flush();
|
||||
oos = new ObjectOutputStream(outputStream);
|
||||
oos.writeObject(TEST_STRING);
|
||||
oos.flush();
|
||||
Thread.sleep(1000000000L); // wait forever, but we're a daemon
|
||||
|
||||
@@ -28,9 +28,8 @@
|
||||
|
||||
<channel id="sharkOutChannel" />
|
||||
|
||||
<int-ip:outbound-channel-adapter id="udpOut"
|
||||
<int-ip:udp-outbound-channel-adapter id="udpOut"
|
||||
channel="sharkOutChannel"
|
||||
protocol="udp"
|
||||
host="225.6.7.8"
|
||||
multicast="true"
|
||||
port="11111"/>
|
||||
|
||||
@@ -7,10 +7,9 @@
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd
|
||||
http://www.springframework.org/schema/integration/ip http://www.springframework.org/schema/integration/ip/spring-integration-ip.xsd">
|
||||
|
||||
<int-ip:inbound-channel-adapter id="udpIn"
|
||||
<int-ip:udp-inbound-channel-adapter id="udpIn"
|
||||
channel="channel"
|
||||
multicast="true"
|
||||
protocol="udp"
|
||||
multicast-address="225.6.7.8"
|
||||
port="11111"/>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user