001 /**
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements. See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License. You may obtain a copy of the License at
008 *
009 * http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017 package org.apache.camel.component.netty;
018
019 import java.net.InetSocketAddress;
020 import java.util.concurrent.ExecutorService;
021
022 import org.apache.camel.CamelContext;
023 import org.apache.camel.Processor;
024 import org.apache.camel.impl.DefaultConsumer;
025 import org.apache.commons.logging.Log;
026 import org.apache.commons.logging.LogFactory;
027 import org.jboss.netty.bootstrap.ConnectionlessBootstrap;
028 import org.jboss.netty.bootstrap.ServerBootstrap;
029 import org.jboss.netty.channel.Channel;
030 import org.jboss.netty.channel.ChannelFactory;
031 import org.jboss.netty.channel.group.ChannelGroup;
032 import org.jboss.netty.channel.group.ChannelGroupFuture;
033 import org.jboss.netty.channel.group.DefaultChannelGroup;
034 import org.jboss.netty.channel.socket.DatagramChannelFactory;
035 import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
036 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
037
038 public class NettyConsumer extends DefaultConsumer {
039 private static final transient Log LOG = LogFactory.getLog(NettyConsumer.class);
040 private final ChannelGroup allChannels;
041 private CamelContext context;
042 private NettyConfiguration configuration;
043 private ChannelFactory channelFactory;
044 private DatagramChannelFactory datagramChannelFactory;
045 private ServerBootstrap serverBootstrap;
046 private ConnectionlessBootstrap connectionlessServerBootstrap;
047 private Channel channel;
048
049 public NettyConsumer(NettyEndpoint nettyEndpoint, Processor processor, NettyConfiguration configuration) {
050 super(nettyEndpoint, processor);
051 this.context = this.getEndpoint().getCamelContext();
052 this.configuration = configuration;
053 this.allChannels = new DefaultChannelGroup("NettyProducer-" + nettyEndpoint.getEndpointUri());
054 }
055
056 @Override
057 public NettyEndpoint getEndpoint() {
058 return (NettyEndpoint) super.getEndpoint();
059 }
060
061 @Override
062 protected void doStart() throws Exception {
063 if (LOG.isDebugEnabled()) {
064 LOG.debug("Netty consumer binding to: " + configuration.getAddress());
065 }
066
067 super.doStart();
068 if (isTcp()) {
069 initializeTCPServerSocketCommunicationLayer();
070 } else {
071 initializeUDPServerSocketCommunicationLayer();
072 }
073
074 LOG.info("Netty consumer bound to: " + configuration.getAddress());
075 }
076
077 @Override
078 protected void doStop() throws Exception {
079 if (LOG.isDebugEnabled()) {
080 LOG.debug("Netty consumer unbinding from: " + configuration.getAddress());
081 }
082
083 // close all channels
084 ChannelGroupFuture future = allChannels.close();
085 future.awaitUninterruptibly();
086
087 // and then release other resources
088 if (channelFactory != null) {
089 channelFactory.releaseExternalResources();
090 }
091
092 super.doStop();
093
094 LOG.info("Netty consumer unbound from: " + configuration.getAddress());
095 }
096
097 public CamelContext getContext() {
098 return context;
099 }
100
101 public ChannelGroup getAllChannels() {
102 return allChannels;
103 }
104
105 public NettyConfiguration getConfiguration() {
106 return configuration;
107 }
108
109 public void setConfiguration(NettyConfiguration configuration) {
110 this.configuration = configuration;
111 }
112
113 public ChannelFactory getChannelFactory() {
114 return channelFactory;
115 }
116
117 public void setChannelFactory(ChannelFactory channelFactory) {
118 this.channelFactory = channelFactory;
119 }
120
121 public DatagramChannelFactory getDatagramChannelFactory() {
122 return datagramChannelFactory;
123 }
124
125 public void setDatagramChannelFactory(DatagramChannelFactory datagramChannelFactory) {
126 this.datagramChannelFactory = datagramChannelFactory;
127 }
128
129 public ServerBootstrap getServerBootstrap() {
130 return serverBootstrap;
131 }
132
133 public void setServerBootstrap(ServerBootstrap serverBootstrap) {
134 this.serverBootstrap = serverBootstrap;
135 }
136
137 public ConnectionlessBootstrap getConnectionlessServerBootstrap() {
138 return connectionlessServerBootstrap;
139 }
140
141 public void setConnectionlessServerBootstrap(ConnectionlessBootstrap connectionlessServerBootstrap) {
142 this.connectionlessServerBootstrap = connectionlessServerBootstrap;
143 }
144
145 protected boolean isTcp() {
146 return configuration.getProtocol().equalsIgnoreCase("tcp");
147 }
148
149 private void initializeTCPServerSocketCommunicationLayer() throws Exception {
150 ExecutorService bossExecutor = context.getExecutorServiceStrategy().newThreadPool(this, "NettyTCPBoss",
151 configuration.getCorePoolSize(), configuration.getMaxPoolSize());
152 ExecutorService workerExecutor = context.getExecutorServiceStrategy().newThreadPool(this, "NettyTCPWorker",
153 configuration.getCorePoolSize(), configuration.getMaxPoolSize());
154
155 channelFactory = new NioServerSocketChannelFactory(bossExecutor, workerExecutor);
156 serverBootstrap = new ServerBootstrap(channelFactory);
157 if (configuration.getServerPipelineFactory() != null) {
158 configuration.getServerPipelineFactory().setConsumer(this);
159 serverBootstrap.setPipelineFactory(configuration.getServerPipelineFactory());
160 } else {
161 serverBootstrap.setPipelineFactory(new DefaultServerPipelineFactory(this));
162 }
163 serverBootstrap.setOption("child.keepAlive", configuration.isKeepAlive());
164 serverBootstrap.setOption("child.tcpNoDelay", configuration.isTcpNoDelay());
165 serverBootstrap.setOption("child.reuseAddress", configuration.isReuseAddress());
166 serverBootstrap.setOption("child.connectTimeoutMillis", configuration.getConnectTimeout());
167
168 channel = serverBootstrap.bind(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
169 // to keep track of all channels in use
170 allChannels.add(channel);
171 }
172
173 private void initializeUDPServerSocketCommunicationLayer() throws Exception {
174 ExecutorService workerExecutor = context.getExecutorServiceStrategy().newThreadPool(this, "NettyUDPWorker",
175 configuration.getCorePoolSize(), configuration.getMaxPoolSize());
176
177 datagramChannelFactory = new NioDatagramChannelFactory(workerExecutor);
178 connectionlessServerBootstrap = new ConnectionlessBootstrap(datagramChannelFactory);
179 if (configuration.getServerPipelineFactory() != null) {
180 configuration.getServerPipelineFactory().setConsumer(this);
181 connectionlessServerBootstrap.setPipelineFactory(configuration.getServerPipelineFactory());
182 } else {
183 connectionlessServerBootstrap.setPipelineFactory(new DefaultServerPipelineFactory(this));
184 }
185 connectionlessServerBootstrap.setOption("child.keepAlive", configuration.isKeepAlive());
186 connectionlessServerBootstrap.setOption("child.tcpNoDelay", configuration.isTcpNoDelay());
187 connectionlessServerBootstrap.setOption("child.reuseAddress", configuration.isReuseAddress());
188 connectionlessServerBootstrap.setOption("child.connectTimeoutMillis", configuration.getConnectTimeout());
189 connectionlessServerBootstrap.setOption("child.broadcast", configuration.isBroadcast());
190 connectionlessServerBootstrap.setOption("sendBufferSize", configuration.getSendBufferSize());
191 connectionlessServerBootstrap.setOption("receiveBufferSize", configuration.getReceiveBufferSize());
192
193 channel = connectionlessServerBootstrap.bind(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
194 // to keep track of all channels in use
195 allChannels.add(channel);
196 }
197
198 }