/*
* Copyright 2002-2016 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.ip.tcp.connection;
import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import javax.net.SocketFactory;
import javax.net.ssl.SSLSession;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.serializer.DefaultDeserializer;
import org.springframework.core.serializer.DefaultSerializer;
import org.springframework.integration.IntegrationMessageHeaderAccessor;
import org.springframework.integration.codec.Codec;
import org.springframework.integration.codec.CodecMessageConverter;
import org.springframework.integration.codec.CompositeCodec;
import org.springframework.integration.codec.kryo.MessageCodec;
import org.springframework.integration.ip.IpHeaders;
import org.springframework.integration.ip.tcp.serializer.MapJsonSerializer;
import org.springframework.integration.support.MessageBuilder;
import org.springframework.integration.support.converter.MapMessageConverter;
import org.springframework.messaging.Message;
import org.springframework.messaging.MessageHeaders;
import org.springframework.messaging.converter.MessageConverter;
import org.springframework.util.MimeType;
/**
* @author Gary Russell
* @since 2.0
*
*/
public class TcpMessageMapperTests {
private static final String TEST_PAYLOAD = "abcdefghijkl";
private Codec codec;
@Before
public void setup() {
Map<Class<?>, Codec> codecs = new HashMap<Class<?>, Codec>();
this.codec = new CompositeCodec(codecs, new MessageCodec());
}
@Test
public void testToMessage() throws Exception {
TcpMessageMapper mapper = new TcpMessageMapper();
TcpConnection connection = mock(TcpConnection.class);
Socket socket = mock(Socket.class);
InetAddress local = mock(InetAddress.class);
SocketInfo info = new SocketInfo(socket);
when(socket.getLocalAddress()).thenReturn(local);
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);
when(connection.getSocketInfo()).thenReturn(info);
Message<?> message = mapper.toMessage(connection);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message.getHeaders().get(IpHeaders.REMOTE_PORT));
assertSame(local, message.getHeaders().get(IpHeaders.LOCAL_ADDRESS));
assertNull(message.getHeaders().get(MessageHeaders.CONTENT_TYPE));
}
@Test
public void testToMessageWithContentType() throws Exception {
TcpMessageMapper mapper = new TcpMessageMapper();
mapper.setAddContentTypeHeader(true);
TcpConnection connection = mock(TcpConnection.class);
Socket socket = mock(Socket.class);
InetAddress local = mock(InetAddress.class);
SocketInfo info = new SocketInfo(socket);
when(socket.getLocalAddress()).thenReturn(local);
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);
when(connection.getSocketInfo()).thenReturn(info);
Message<?> message = mapper.toMessage(connection);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message.getHeaders().get(IpHeaders.REMOTE_PORT));
assertSame(local, message.getHeaders().get(IpHeaders.LOCAL_ADDRESS));
assertEquals("application/octet-stream;charset=UTF-8", message.getHeaders().get(MessageHeaders.CONTENT_TYPE));
MimeType parseOk = MimeType.valueOf((String) message.getHeaders().get(MessageHeaders.CONTENT_TYPE));
assertEquals(message.getHeaders().get(MessageHeaders.CONTENT_TYPE), parseOk.toString());
}
@Test
public void testToMessageWithCustomContentType() throws Exception {
TcpMessageMapper mapper = new TcpMessageMapper();
mapper.setAddContentTypeHeader(true);
mapper.setContentType("application/octet-stream;charset=ISO-8859-1");
TcpConnection connection = mock(TcpConnection.class);
Socket socket = mock(Socket.class);
InetAddress local = mock(InetAddress.class);
SocketInfo info = new SocketInfo(socket);
when(socket.getLocalAddress()).thenReturn(local);
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);
when(connection.getSocketInfo()).thenReturn(info);
Message<?> message = mapper.toMessage(connection);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message.getHeaders().get(IpHeaders.REMOTE_PORT));
assertSame(local, message.getHeaders().get(IpHeaders.LOCAL_ADDRESS));
assertEquals("application/octet-stream;charset=ISO-8859-1", message.getHeaders().get(MessageHeaders.CONTENT_TYPE));
MimeType parseOk = MimeType.valueOf((String) message.getHeaders().get(MessageHeaders.CONTENT_TYPE));
assertEquals(message.getHeaders().get(MessageHeaders.CONTENT_TYPE), parseOk.toString());
}
@Test(expected = IllegalArgumentException.class)
public void testToMessageWithBadContentType() throws Exception {
TcpMessageMapper mapper = new TcpMessageMapper();
mapper.setAddContentTypeHeader(true);
try {
mapper.setContentType("");
}
catch (IllegalArgumentException e) {
assertThat(e.getMessage(), containsString("'contentType' could not be parsed"));
throw e;
}
}
@Test
public void testToMessageSequence() throws Exception {
TcpMessageMapper mapper = new TcpMessageMapper();
Socket socket = SocketFactory.getDefault().createSocket();
TcpConnection connection = new TcpConnectionSupport(socket, false, false, null, null) {
@Override
public void run() {
}
@Override
public void send(Message<?> message) throws Exception {
}
@Override
public boolean isOpen() {
return false;
}
@Override
public int getPort() {
return 1234;
}
@Override
public Object getPayload() throws Exception {
return TEST_PAYLOAD.getBytes();
}
@Override
public String getHostName() {
return "MyHost";
}
@Override
public String getHostAddress() {
return "1.1.1.1";
}
@Override
public String getConnectionId() {
return "anId";
}
@Override
public Object getDeserializerStateKey() {
return null;
}
@Override
public SSLSession getSslSession() {
return null;
}
};
Message<?> message = mapper.toMessage(connection);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message
.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message
.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message
.getHeaders().get(IpHeaders.REMOTE_PORT));
assertEquals(Integer.valueOf(0), new IntegrationMessageHeaderAccessor(message).getSequenceNumber());
message = mapper.toMessage(connection);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message
.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message
.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message
.getHeaders().get(IpHeaders.REMOTE_PORT));
assertEquals(Integer.valueOf(0), new IntegrationMessageHeaderAccessor(message).getSequenceNumber());
}
@Test
public void testToMessageSequenceNewWithCustomHeader() throws Exception {
TcpMessageMapper mapper = new TcpMessageMapper() {
@Override
protected Map<String, ?> supplyCustomHeaders(TcpConnection connection) {
return Collections.singletonMap("foo", "bar");
}
};
mapper.setApplySequence(true);
Socket socket = SocketFactory.getDefault().createSocket();
TcpConnection connection = new TcpConnectionSupport(socket, false, false, null, null) {
@Override
public void run() {
}
@Override
public void send(Message<?> message) throws Exception {
}
@Override
public boolean isOpen() {
return false;
}
@Override
public int getPort() {
return 1234;
}
@Override
public Object getPayload() throws Exception {
return TEST_PAYLOAD.getBytes();
}
@Override
public String getHostName() {
return "MyHost";
}
@Override
public String getHostAddress() {
return "1.1.1.1";
}
@Override
public String getConnectionId() {
return "anId";
}
@Override
public Object getDeserializerStateKey() {
return null;
}
@Override
public SSLSession getSslSession() {
return null;
}
};
Message<?> message = mapper.toMessage(connection);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message
.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message
.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message
.getHeaders().get(IpHeaders.REMOTE_PORT));
IntegrationMessageHeaderAccessor headerAccessor = new IntegrationMessageHeaderAccessor(message);
assertEquals(Integer.valueOf(1), headerAccessor.getSequenceNumber());
assertEquals(message.getHeaders().get(IpHeaders.CONNECTION_ID), headerAccessor.getCorrelationId());
message = mapper.toMessage(connection);
headerAccessor = new IntegrationMessageHeaderAccessor(message);
assertEquals(TEST_PAYLOAD, new String((byte[]) message.getPayload()));
assertEquals("MyHost", message
.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message
.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message
.getHeaders().get(IpHeaders.REMOTE_PORT));
assertEquals(Integer.valueOf(2), headerAccessor.getSequenceNumber());
assertEquals(message.getHeaders().get(IpHeaders.CONNECTION_ID), headerAccessor.getCorrelationId());
assertNotNull(message.getHeaders().get("foo"));
assertEquals("bar", message.getHeaders().get("foo"));
}
@Test
public void testFromMessageBytes() throws Exception {
String s = "test";
Message<String> message = MessageBuilder.withPayload(s).build();
TcpMessageMapper mapper = new TcpMessageMapper();
mapper.setStringToBytes(true);
byte[] bArray = (byte[]) mapper.fromMessage(message);
assertEquals(s, new String(bArray));
}
@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);
}
@Test
public void testMapMessageConvertingOutboundJson() throws Exception {
Message<String> message = MessageBuilder.withPayload("foo")
.setHeader("bar", "baz")
.build();
MapMessageConverter converter = new MapMessageConverter();
converter.setHeaderNames("bar");
MessageConvertingTcpMessageMapper mapper = new MessageConvertingTcpMessageMapper(converter);
Map<?, ?> map = (Map<?, ?>) mapper.fromMessage(message);
MapJsonSerializer serializer = new MapJsonSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.serialize(map, baos);
assertEquals("{\"headers\":{\"bar\":\"baz\"},\"payload\":\"foo\"}\n", new String(baos.toByteArray(), "UTF-8"));
}
@Test
public void testMapMessageConvertingInboundJson() throws Exception {
String json = "{\"headers\":{\"bar\":\"baz\"},\"payload\":\"foo\"}\n";
MapMessageConverter converter = new MapMessageConverter();
MessageConvertingTcpMessageMapper mapper = new MessageConvertingTcpMessageMapper(converter);
MapJsonSerializer deserializer = new MapJsonSerializer();
Map<?, ?> map = deserializer.deserialize(new ByteArrayInputStream(json.getBytes("UTF-8")));
TcpConnection connection = mock(TcpConnection.class);
when(connection.getPayload()).thenReturn(map);
when(connection.getHostName()).thenReturn("someHost");
when(connection.getHostAddress()).thenReturn("1.1.1.1");
when(connection.getPort()).thenReturn(1234);
when(connection.getConnectionId()).thenReturn("someId");
Message<?> message = mapper.toMessage(connection);
assertEquals("foo", message.getPayload());
assertEquals("baz", message.getHeaders().get("bar"));
assertEquals("someHost", message.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message.getHeaders().get(IpHeaders.REMOTE_PORT));
assertEquals("someId", message.getHeaders().get(IpHeaders.CONNECTION_ID));
}
@Test
public void testMapMessageConvertingBothWaysJava() throws Exception {
Message<String> outMessage = MessageBuilder.withPayload("foo")
.setHeader("bar", "baz")
.build();
MapMessageConverter converter = new MapMessageConverter();
converter.setHeaderNames("bar");
MessageConvertingTcpMessageMapper mapper = new MessageConvertingTcpMessageMapper(converter);
Map<?, ?> map = (Map<?, ?>) mapper.fromMessage(outMessage);
DefaultSerializer serializer = new DefaultSerializer();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
serializer.serialize(map, baos);
DefaultDeserializer deserializer = new DefaultDeserializer();
map = (Map<?, ?>) deserializer.deserialize(new ByteArrayInputStream(baos.toByteArray()));
TcpConnection connection = mock(TcpConnection.class);
when(connection.getPayload()).thenReturn(map);
when(connection.getHostName()).thenReturn("someHost");
when(connection.getHostAddress()).thenReturn("1.1.1.1");
when(connection.getPort()).thenReturn(1234);
when(connection.getConnectionId()).thenReturn("someId");
Message<?> message = mapper.toMessage(connection);
assertEquals("foo", message.getPayload());
assertEquals("baz", message.getHeaders().get("bar"));
assertEquals("someHost", message.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message.getHeaders().get(IpHeaders.REMOTE_PORT));
assertEquals("someId", message.getHeaders().get(IpHeaders.CONNECTION_ID));
}
@Test
public void testCodecMessageConvertingBothWaysJava() throws Exception {
Message<String> outMessage = MessageBuilder.withPayload("foo")
.setHeader("bar", "baz")
.build();
MessageConverter converter = new CodecMessageConverter(this.codec);
MessageConvertingTcpMessageMapper mapper = new MessageConvertingTcpMessageMapper(converter);
byte[] bytes = (byte[]) mapper.fromMessage(outMessage);
TcpConnection connection = mock(TcpConnection.class);
when(connection.getPayload()).thenReturn(bytes);
when(connection.getHostName()).thenReturn("someHost");
when(connection.getHostAddress()).thenReturn("1.1.1.1");
when(connection.getPort()).thenReturn(1234);
when(connection.getConnectionId()).thenReturn("someId");
Message<?> message = mapper.toMessage(connection);
assertEquals("foo", message.getPayload());
assertEquals("baz", message.getHeaders().get("bar"));
assertEquals("someHost", message.getHeaders().get(IpHeaders.HOSTNAME));
assertEquals("1.1.1.1", message.getHeaders().get(IpHeaders.IP_ADDRESS));
assertEquals(1234, message.getHeaders().get(IpHeaders.REMOTE_PORT));
assertEquals("someId", message.getHeaders().get(IpHeaders.CONNECTION_ID));
}
}