INT-1279 Namespace Updates For New Gateways; Remove Old Gateways/Adapters; Migrate All Tests to New Gateways/Adapters

This commit is contained in:
Gary Russell
2010-08-13 22:05:59 +00:00
parent 64624490bf
commit a54c7ed5f1
78 changed files with 1827 additions and 6784 deletions

View File

@@ -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).

View File

@@ -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());

View File

@@ -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,

View File

@@ -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); }
}

View File

@@ -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;
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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 '&lt;length&gt;&lt;message&gt;'.
*/
public static final int FORMAT_LENGTH_HEADER = 1;
/**
* Message has format 'STX&lt;message&gt;ETX'.
*/
public static final int FORMAT_STX_ETX = 2;
/**
* Message has format '&lt;message&gt;\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;
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}
}

View File

@@ -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);
}
}
}
}

View File

@@ -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;
}
}

View File

@@ -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 = "";

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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");
}
}
}
}

View File

@@ -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");
}
}

View File

@@ -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");
}
}
}

View File

@@ -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");
}
}

View File

@@ -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);
}
}

View File

@@ -40,8 +40,6 @@ public class TcpReceivingChannelAdapter
protected ServerSocket serverSocket;
protected Class<NetSocketReader> customSocketReaderClass;
protected ConnectionFactory clientConnectionFactory;
protected ConnectionFactory serverConnectionFactory;

View File

@@ -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();
}
}

View File

@@ -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;

View File

@@ -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.

View File

@@ -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);
}
}

View File

@@ -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);

View File

@@ -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>

View File

@@ -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);
// }
// }
}

View File

@@ -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" />

View File

@@ -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);

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -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()));
}
}

View File

@@ -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;
}
}

View File

@@ -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());
}
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}
}

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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());
}
}
}

View File

@@ -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;
}
}

View File

@@ -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>

View File

@@ -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");
}
}
}
}

View File

@@ -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));
}
}

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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>

View File

@@ -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();
}
}

View File

@@ -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());

View File

@@ -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();

View File

@@ -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);

View File

@@ -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>

View File

@@ -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

View File

@@ -15,7 +15,6 @@
*/
package org.springframework.integration.ip.tcp.connection;
import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactory;
/**
* @author Gary Russell

View File

@@ -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);
}
}

View File

@@ -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");
}
}
}
}

View File

@@ -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();
}
}

View File

@@ -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();

View File

@@ -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();
}
}

View File

@@ -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();
}

View File

@@ -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;
/**

View File

@@ -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;
/**

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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"

View File

@@ -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;
/**

View File

@@ -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

View File

@@ -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"/>

View File

@@ -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"/>