/* * 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.config; import java.util.concurrent.Executor; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryAware; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.config.AbstractFactoryBean; import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisherAware; import org.springframework.context.Lifecycle; import org.springframework.core.serializer.Deserializer; import org.springframework.core.serializer.Serializer; import org.springframework.integration.ip.tcp.connection.AbstractClientConnectionFactory; import org.springframework.integration.ip.tcp.connection.AbstractConnectionFactory; import org.springframework.integration.ip.tcp.connection.AbstractServerConnectionFactory; import org.springframework.integration.ip.tcp.connection.DefaultTcpNetSSLSocketFactorySupport; import org.springframework.integration.ip.tcp.connection.DefaultTcpNetSocketFactorySupport; import org.springframework.integration.ip.tcp.connection.DefaultTcpNioConnectionSupport; import org.springframework.integration.ip.tcp.connection.DefaultTcpNioSSLConnectionSupport; import org.springframework.integration.ip.tcp.connection.DefaultTcpSocketSupport; import org.springframework.integration.ip.tcp.connection.TcpConnectionInterceptorFactoryChain; import org.springframework.integration.ip.tcp.connection.TcpMessageMapper; 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.TcpNioConnectionSupport; import org.springframework.integration.ip.tcp.connection.TcpNioServerConnectionFactory; import org.springframework.integration.ip.tcp.connection.TcpSSLContextSupport; import org.springframework.integration.ip.tcp.connection.TcpSocketFactorySupport; import org.springframework.integration.ip.tcp.connection.TcpSocketSupport; import org.springframework.integration.ip.tcp.serializer.ByteArrayCrLfSerializer; import org.springframework.util.Assert; /** * Instantiates a TcpN(et|io)(Server|Client)ConnectionFactory, depending * on type and using-nio attributes. * * @author Gary Russell * @since 2.0.5 */ public class TcpConnectionFactoryFactoryBean extends AbstractFactoryBean<AbstractConnectionFactory> implements Lifecycle, BeanNameAware, BeanFactoryAware, ApplicationEventPublisherAware { private volatile AbstractConnectionFactory connectionFactory; private volatile String type; private volatile String host; private volatile int port; private volatile int soTimeout; private volatile int soSendBufferSize; private volatile int soReceiveBufferSize; private volatile boolean soTcpNoDelay; private volatile int soLinger = -1; // don't set by default private volatile boolean soKeepAlive; private volatile int soTrafficClass = -1; // don't set by default private volatile Executor taskExecutor; private volatile Deserializer<?> deserializer = new ByteArrayCrLfSerializer(); private volatile Serializer<?> serializer = new ByteArrayCrLfSerializer(); private volatile TcpMessageMapper mapper = new TcpMessageMapper(); private volatile boolean mapperSet; private volatile boolean singleUse; private volatile int backlog = 5; private volatile TcpConnectionInterceptorFactoryChain interceptorFactoryChain; private volatile boolean lookupHost = true; private volatile String localAddress; private volatile boolean usingNio; private volatile boolean usingDirectBuffers; private volatile String beanName; private volatile boolean applySequence; private volatile Long readDelay; private volatile TcpSSLContextSupport sslContextSupport; private volatile Integer sslHandshakeTimeout; private volatile TcpSocketSupport socketSupport = new DefaultTcpSocketSupport(); private volatile TcpNioConnectionSupport nioConnectionSupport; private volatile TcpSocketFactorySupport socketFactorySupport; private volatile ApplicationEventPublisher applicationEventPublisher; private volatile BeanFactory beanFactory; public TcpConnectionFactoryFactoryBean() { } public TcpConnectionFactoryFactoryBean(String type) { setType(type); } @Override public final void setBeanFactory(BeanFactory beanFactory) { this.beanFactory = beanFactory; } @Override public Class<?> getObjectType() { return this.connectionFactory != null ? this.connectionFactory.getClass() : this.type == null ? AbstractConnectionFactory.class : isServer() ? AbstractServerConnectionFactory.class : isClient() ? AbstractClientConnectionFactory.class : AbstractConnectionFactory.class; } @Override protected AbstractConnectionFactory createInstance() throws Exception { if (!this.mapperSet) { this.mapper.setBeanFactory(this.beanFactory); } if (this.usingNio) { if (isServer()) { TcpNioServerConnectionFactory connectionFactory = new TcpNioServerConnectionFactory(this.port); this.setCommonAttributes(connectionFactory); this.setServerAttributes(connectionFactory); connectionFactory.setUsingDirectBuffers(this.usingDirectBuffers); connectionFactory.setTcpNioConnectionSupport(this.obtainNioConnectionSupport()); this.connectionFactory = connectionFactory; } else { TcpNioClientConnectionFactory connectionFactory = new TcpNioClientConnectionFactory( this.host, this.port); this.setCommonAttributes(connectionFactory); connectionFactory.setUsingDirectBuffers(this.usingDirectBuffers); connectionFactory.setTcpNioConnectionSupport(this.obtainNioConnectionSupport()); this.connectionFactory = connectionFactory; } if (this.sslHandshakeTimeout != null) { this.connectionFactory.setSslHandshakeTimeout(this.sslHandshakeTimeout); } } else { if (isServer()) { TcpNetServerConnectionFactory connectionFactory = new TcpNetServerConnectionFactory(this.port); this.setCommonAttributes(connectionFactory); this.setServerAttributes(connectionFactory); connectionFactory.setTcpSocketFactorySupport(this.obtainSocketFactorySupport()); this.connectionFactory = connectionFactory; } else { TcpNetClientConnectionFactory connectionFactory = new TcpNetClientConnectionFactory( this.host, this.port); this.setCommonAttributes(connectionFactory); connectionFactory.setTcpSocketFactorySupport(this.obtainSocketFactorySupport()); this.connectionFactory = connectionFactory; } } return this.connectionFactory; } private void setCommonAttributes(AbstractConnectionFactory factory) { factory.setDeserializer(this.deserializer); factory.setInterceptorFactoryChain(this.interceptorFactoryChain); factory.setLookupHost(this.lookupHost); this.mapper.setApplySequence(this.applySequence); factory.setMapper(this.mapper); factory.setSerializer(this.serializer); factory.setSingleUse(this.singleUse); factory.setSoKeepAlive(this.soKeepAlive); factory.setSoLinger(this.soLinger); factory.setSoReceiveBufferSize(this.soReceiveBufferSize); factory.setSoSendBufferSize(this.soSendBufferSize); factory.setSoTcpNoDelay(this.soTcpNoDelay); factory.setSoTimeout(this.soTimeout); factory.setSoTrafficClass(this.soTrafficClass); factory.setTaskExecutor(this.taskExecutor); factory.setBeanName(this.beanName); factory.setTcpSocketSupport(this.socketSupport); factory.setApplicationEventPublisher(this.applicationEventPublisher); if (this.readDelay != null) { factory.setReadDelay(this.readDelay); } } private void setServerAttributes(AbstractServerConnectionFactory factory) { factory.setLocalAddress(this.localAddress); factory.setBacklog(this.backlog); } private TcpSocketFactorySupport obtainSocketFactorySupport() { if (this.socketFactorySupport != null) { return this.socketFactorySupport; } if (this.sslContextSupport == null) { return new DefaultTcpNetSocketFactorySupport(); } else { return new DefaultTcpNetSSLSocketFactorySupport(this.sslContextSupport); } } private TcpNioConnectionSupport obtainNioConnectionSupport() { if (this.nioConnectionSupport != null) { return this.nioConnectionSupport; } if (this.sslContextSupport == null) { return new DefaultTcpNioConnectionSupport(); } else { return new DefaultTcpNioSSLConnectionSupport(this.sslContextSupport); } } /** * @param port the port to set */ public void setPort(int port) { this.port = port; } /** * @param host the host to set */ public void setHost(String host) { Assert.notNull(host, "Host may not be null"); this.host = host; } /** * @param type the type to set */ public final void setType(String type) { this.type = type; Assert.isTrue(isServer() || isClient(), "type must be 'server' or 'client'"); } /** * @param localAddress The local address. * @see AbstractServerConnectionFactory#setLocalAddress(java.lang.String) */ public void setLocalAddress(String localAddress) { Assert.notNull(localAddress, "LocalAddress may not be null"); this.localAddress = localAddress; } /** * @param soTimeout The timeout. * @see AbstractConnectionFactory#setSoTimeout(int) */ public void setSoTimeout(int soTimeout) { this.soTimeout = soTimeout; } /** * @param soReceiveBufferSize The receive buffer size. * @see AbstractConnectionFactory#setSoReceiveBufferSize(int) */ public void setSoReceiveBufferSize(int soReceiveBufferSize) { this.soReceiveBufferSize = soReceiveBufferSize; } /** * @param soSendBufferSize The send buffer size. * @see AbstractConnectionFactory#setSoSendBufferSize(int) */ public void setSoSendBufferSize(int soSendBufferSize) { this.soSendBufferSize = soSendBufferSize; } /** * @param soTcpNoDelay The TCP no delay to set. * @see AbstractConnectionFactory#setSoTcpNoDelay(boolean) */ public void setSoTcpNoDelay(boolean soTcpNoDelay) { this.soTcpNoDelay = soTcpNoDelay; } /** * @param soLinger The SO Linger to set. * @see AbstractConnectionFactory#setSoLinger(int) */ public void setSoLinger(int soLinger) { this.soLinger = soLinger; } /** * @param soKeepAlive The SO keepalive to set. * @see AbstractConnectionFactory#setSoKeepAlive(boolean) */ public void setSoKeepAlive(boolean soKeepAlive) { this.soKeepAlive = soKeepAlive; } /** * @param soTrafficClass The SO traffic class to set. * @see AbstractConnectionFactory#setSoTrafficClass(int) */ public void setSoTrafficClass(int soTrafficClass) { this.soTrafficClass = soTrafficClass; } /** * @param usingNio the usingNio to set */ public void setUsingNio(boolean usingNio) { this.usingNio = usingNio; } /** * @param usingDirectBuffers the usingDirectBuffers to set. * @see TcpNioServerConnectionFactory#setUsingDirectBuffers(boolean) */ public void setUsingDirectBuffers(boolean usingDirectBuffers) { this.usingDirectBuffers = usingDirectBuffers; } /** * @param taskExecutor The task executor. * @see AbstractConnectionFactory#setTaskExecutor(java.util.concurrent.Executor) */ public void setTaskExecutor(Executor taskExecutor) { Assert.notNull(taskExecutor, "Executor may not be null"); this.taskExecutor = taskExecutor; } /** * @param deserializer The deserializer. * @see AbstractConnectionFactory#setDeserializer(org.springframework.core.serializer.Deserializer) */ public void setDeserializer(Deserializer<?> deserializer) { Assert.notNull(deserializer, "Deserializer may not be null"); this.deserializer = deserializer; } /** * @param serializer The serializer. * @see AbstractConnectionFactory#setSerializer(org.springframework.core.serializer.Serializer) */ public void setSerializer(Serializer<?> serializer) { Assert.notNull(serializer, "Serializer may not be null"); this.serializer = serializer; } /** * @param mapper The mapper. * @see AbstractConnectionFactory#setMapper(TcpMessageMapper) */ public void setMapper(TcpMessageMapper mapper) { Assert.notNull(mapper, "TcpMessageMapper may not be null"); this.mapper = mapper; this.mapperSet = true; } /** * @param singleUse The singleUse to set. * @see AbstractConnectionFactory#setSingleUse(boolean) */ public void setSingleUse(boolean singleUse) { this.singleUse = singleUse; } /** * @param backlog The backlog. * @see AbstractServerConnectionFactory#setBacklog(int) */ public void setBacklog(int backlog) { this.backlog = backlog; } /** * @param interceptorFactoryChain The interceptor factory chain. * @see AbstractConnectionFactory#setInterceptorFactoryChain(TcpConnectionInterceptorFactoryChain) */ public void setInterceptorFactoryChain( TcpConnectionInterceptorFactoryChain interceptorFactoryChain) { Assert.notNull(interceptorFactoryChain, "InterceptorFactoryChain may not be null"); this.interceptorFactoryChain = interceptorFactoryChain; } /** * @param lookupHost The lookupHost to set. * @see AbstractConnectionFactory#setLookupHost(boolean) */ public void setLookupHost(boolean lookupHost) { this.lookupHost = lookupHost; } /** * * @see AbstractConnectionFactory#start() */ @Override public void start() { this.connectionFactory.start(); } /** * * @see AbstractConnectionFactory#stop() */ @Override public void stop() { this.connectionFactory.stop(); } @Override public boolean isRunning() { return this.connectionFactory.isRunning(); } @Override public void setBeanName(String name) { this.beanName = name; } /** * @param applySequence the applySequence to set */ public void setApplySequence(boolean applySequence) { this.applySequence = applySequence; } public void setReadDelay(long readDelay) { this.readDelay = readDelay; } public void setSslContextSupport(TcpSSLContextSupport sslContextSupport) { Assert.notNull(sslContextSupport, "TcpSSLContextSupport may not be null"); this.sslContextSupport = sslContextSupport; } public void setSocketSupport(TcpSocketSupport tcpSocketSupport) { Assert.notNull(tcpSocketSupport, "TcpSocketSupport may not be null"); this.socketSupport = tcpSocketSupport; } /** * Rare property - not exposed through namespace * @param tcpNioSupport The tcpNioSupport to set. */ public void setNioConnectionSupport(TcpNioConnectionSupport tcpNioSupport) { Assert.notNull(tcpNioSupport, "TcpNioConnectionSupport may not be null"); this.nioConnectionSupport = tcpNioSupport; } public void setSocketFactorySupport( TcpSocketFactorySupport tcpSocketFactorySupport) { Assert.notNull(tcpSocketFactorySupport, "TcpSocketFactorySupport may not be null"); this.socketFactorySupport = tcpSocketFactorySupport; } @Override public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) { this.applicationEventPublisher = applicationEventPublisher; } /** * Set the SSL handshake timeout (only used with SSL and NIO). * @param sslHandshakeTimeout the timeout. * @since 4.3.6 */ public void setSslHandshakeTimeout(Integer sslHandshakeTimeout) { this.sslHandshakeTimeout = sslHandshakeTimeout; } private boolean isClient() { return "client".equals(this.type); } private boolean isServer() { return "server".equals(this.type); } }