/** * */ package vnet.sms.gateway.nettysupport.test; import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; import java.util.concurrent.Executors; import java.util.concurrent.atomic.AtomicInteger; import org.jboss.netty.bootstrap.ServerBootstrap; import org.jboss.netty.channel.ChannelHandlerContext; import org.jboss.netty.channel.ChannelPipeline; import org.jboss.netty.channel.ChannelPipelineFactory; import org.jboss.netty.channel.ChannelStateEvent; import org.jboss.netty.channel.Channels; import org.jboss.netty.channel.SimpleChannelUpstreamHandler; import org.jboss.netty.channel.group.ChannelGroup; import org.jboss.netty.channel.group.DefaultChannelGroup; import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory; import org.jboss.netty.handler.codec.serialization.ClassResolvers; import org.jboss.netty.handler.codec.serialization.ObjectDecoder; import org.jboss.netty.handler.codec.serialization.ObjectEncoder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * @author obergner * */ public class ReceivedMessagesPublishingServer { private final Logger log = LoggerFactory .getLogger(getClass()); private final AtomicInteger port = new AtomicInteger( -1); private final ServerBootstrap serverBootstrap; private final ReceivedMessagesPublishingServerHandler messagesPublishingHandler = new ReceivedMessagesPublishingServerHandler(); private final ChannelGroup allConnectedChannels = new DefaultChannelGroup( "ReceivedMessagesPublishingServer"); private final class ChannelRecorder extends SimpleChannelUpstreamHandler { /** * @see org.jboss.netty.channel.SimpleChannelUpstreamHandler#channelConnected(org.jboss.netty.channel.ChannelHandlerContext, * org.jboss.netty.channel.ChannelStateEvent) */ @Override public void channelConnected(final ChannelHandlerContext ctx, final ChannelStateEvent e) throws Exception { ReceivedMessagesPublishingServer.this.log.info( "Channel {} has been connected", e.getChannel()); ReceivedMessagesPublishingServer.this.allConnectedChannels.add(e .getChannel()); super.channelConnected(ctx, e); } } /** * @param port */ public ReceivedMessagesPublishingServer() { this.serverBootstrap = new ServerBootstrap( new NioServerSocketChannelFactory( Executors.newCachedThreadPool(), Executors.newCachedThreadPool())); } public void addListener(final ReceivedMessagesListener listener) { this.messagesPublishingHandler.addListener(listener); } public void clearListeners() { this.messagesPublishingHandler.clear(); } public int getPort() { final int listenPort = this.port.get(); if (listenPort == -1) { throw new IllegalStateException("Not yet connected"); } return listenPort; } public void start() throws IOException { this.port.set(getNextAvailablePort()); this.log.info("Starting server on port {} ...", this.port); this.serverBootstrap.setPipelineFactory(new ChannelPipelineFactory() { @Override public ChannelPipeline getPipeline() throws Exception { return Channels .pipeline( new ChannelRecorder(), new ObjectDecoder(ClassResolvers .cacheDisabled(null)), new ObjectEncoder(), ReceivedMessagesPublishingServer.this.messagesPublishingHandler); } }); this.serverBootstrap.bind(new InetSocketAddress(this.port.get())); this.log.info("Server started on port {}", this.port); } private int getNextAvailablePort() throws IOException { final ServerSocket socket = new ServerSocket(0); final int unusedPort = socket.getLocalPort(); socket.close(); this.log.info("Will use as yet unused port {}", unusedPort); return unusedPort; } public void stop() { clearListeners(); this.allConnectedChannels.close().awaitUninterruptibly(); this.serverBootstrap.releaseExternalResources(); } }