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.jboss.netty.bootstrap.ConnectionlessBootstrap;
026 import org.jboss.netty.bootstrap.ServerBootstrap;
027 import org.jboss.netty.channel.Channel;
028 import org.jboss.netty.channel.ChannelFactory;
029 import org.jboss.netty.channel.FixedReceiveBufferSizePredictorFactory;
030 import org.jboss.netty.channel.group.ChannelGroup;
031 import org.jboss.netty.channel.group.ChannelGroupFuture;
032 import org.jboss.netty.channel.group.DefaultChannelGroup;
033 import org.jboss.netty.channel.socket.DatagramChannelFactory;
034 import org.jboss.netty.channel.socket.nio.NioDatagramChannelFactory;
035 import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
036 import org.slf4j.Logger;
037 import org.slf4j.LoggerFactory;
038
039 public class NettyConsumer extends DefaultConsumer {
040 private static final transient Logger LOG = LoggerFactory.getLogger(NettyConsumer.class);
041 private final ChannelGroup allChannels;
042 private CamelContext context;
043 private NettyConfiguration configuration;
044 private ChannelFactory channelFactory;
045 private DatagramChannelFactory datagramChannelFactory;
046 private ServerBootstrap serverBootstrap;
047 private ConnectionlessBootstrap connectionlessServerBootstrap;
048 private Channel channel;
049
050 public NettyConsumer(NettyEndpoint nettyEndpoint, Processor processor, NettyConfiguration configuration) {
051 super(nettyEndpoint, processor);
052 this.context = this.getEndpoint().getCamelContext();
053 this.configuration = configuration;
054 this.allChannels = new DefaultChannelGroup("NettyProducer-" + nettyEndpoint.getEndpointUri());
055 }
056
057 @Override
058 public NettyEndpoint getEndpoint() {
059 return (NettyEndpoint) super.getEndpoint();
060 }
061
062 @Override
063 protected void doStart() throws Exception {
064 LOG.debug("Netty consumer binding to: {}", configuration.getAddress());
065
066 super.doStart();
067 if (isTcp()) {
068 initializeTCPServerSocketCommunicationLayer();
069 } else {
070 initializeUDPServerSocketCommunicationLayer();
071 }
072
073 LOG.info("Netty consumer bound to: " + configuration.getAddress());
074 }
075
076 @Override
077 protected void doStop() throws Exception {
078 LOG.debug("Netty consumer unbinding from: {}", configuration.getAddress());
079
080 // close all channels
081 ChannelGroupFuture future = allChannels.close();
082 future.awaitUninterruptibly();
083
084 // and then release other resources
085 if (channelFactory != null) {
086 channelFactory.releaseExternalResources();
087 }
088
089 super.doStop();
090
091 LOG.info("Netty consumer unbound from: " + configuration.getAddress());
092 }
093
094 public CamelContext getContext() {
095 return context;
096 }
097
098 public ChannelGroup getAllChannels() {
099 return allChannels;
100 }
101
102 public NettyConfiguration getConfiguration() {
103 return configuration;
104 }
105
106 public void setConfiguration(NettyConfiguration configuration) {
107 this.configuration = configuration;
108 }
109
110 public ChannelFactory getChannelFactory() {
111 return channelFactory;
112 }
113
114 public void setChannelFactory(ChannelFactory channelFactory) {
115 this.channelFactory = channelFactory;
116 }
117
118 public DatagramChannelFactory getDatagramChannelFactory() {
119 return datagramChannelFactory;
120 }
121
122 public void setDatagramChannelFactory(DatagramChannelFactory datagramChannelFactory) {
123 this.datagramChannelFactory = datagramChannelFactory;
124 }
125
126 public ServerBootstrap getServerBootstrap() {
127 return serverBootstrap;
128 }
129
130 public void setServerBootstrap(ServerBootstrap serverBootstrap) {
131 this.serverBootstrap = serverBootstrap;
132 }
133
134 public ConnectionlessBootstrap getConnectionlessServerBootstrap() {
135 return connectionlessServerBootstrap;
136 }
137
138 public void setConnectionlessServerBootstrap(ConnectionlessBootstrap connectionlessServerBootstrap) {
139 this.connectionlessServerBootstrap = connectionlessServerBootstrap;
140 }
141
142 protected boolean isTcp() {
143 return configuration.getProtocol().equalsIgnoreCase("tcp");
144 }
145
146 private void initializeTCPServerSocketCommunicationLayer() throws Exception {
147 ExecutorService bossExecutor = context.getExecutorServiceStrategy().newThreadPool(this, "NettyTCPBoss",
148 configuration.getCorePoolSize(), configuration.getMaxPoolSize());
149 ExecutorService workerExecutor = context.getExecutorServiceStrategy().newThreadPool(this, "NettyTCPWorker",
150 configuration.getCorePoolSize(), configuration.getMaxPoolSize());
151
152 if (configuration.getWorkerCount() == 0) {
153 channelFactory = new NioServerSocketChannelFactory(bossExecutor, workerExecutor);
154 } else {
155 channelFactory = new NioServerSocketChannelFactory(bossExecutor, workerExecutor,
156 configuration.getWorkerCount());
157 }
158 serverBootstrap = new ServerBootstrap(channelFactory);
159 if (configuration.getServerPipelineFactory() != null) {
160 configuration.getServerPipelineFactory().setConsumer(this);
161 serverBootstrap.setPipelineFactory(configuration.getServerPipelineFactory());
162 } else {
163 serverBootstrap.setPipelineFactory(new DefaultServerPipelineFactory(this));
164 }
165 serverBootstrap.setOption("child.keepAlive", configuration.isKeepAlive());
166 serverBootstrap.setOption("child.tcpNoDelay", configuration.isTcpNoDelay());
167 serverBootstrap.setOption("child.reuseAddress", configuration.isReuseAddress());
168 serverBootstrap.setOption("child.connectTimeoutMillis", configuration.getConnectTimeout());
169
170 channel = serverBootstrap.bind(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
171 // to keep track of all channels in use
172 allChannels.add(channel);
173 }
174
175 private void initializeUDPServerSocketCommunicationLayer() throws Exception {
176 ExecutorService workerExecutor = context.getExecutorServiceStrategy().newThreadPool(this, "NettyUDPWorker",
177 configuration.getCorePoolSize(), configuration.getMaxPoolSize());
178
179 datagramChannelFactory = new NioDatagramChannelFactory(workerExecutor);
180 connectionlessServerBootstrap = new ConnectionlessBootstrap(datagramChannelFactory);
181 if (configuration.getServerPipelineFactory() != null) {
182 configuration.getServerPipelineFactory().setConsumer(this);
183 connectionlessServerBootstrap.setPipelineFactory(configuration.getServerPipelineFactory());
184 } else {
185 connectionlessServerBootstrap.setPipelineFactory(new DefaultServerPipelineFactory(this));
186 }
187 connectionlessServerBootstrap.setOption("child.keepAlive", configuration.isKeepAlive());
188 connectionlessServerBootstrap.setOption("child.tcpNoDelay", configuration.isTcpNoDelay());
189 connectionlessServerBootstrap.setOption("child.reuseAddress", configuration.isReuseAddress());
190 connectionlessServerBootstrap.setOption("child.connectTimeoutMillis", configuration.getConnectTimeout());
191 connectionlessServerBootstrap.setOption("child.broadcast", configuration.isBroadcast());
192 connectionlessServerBootstrap.setOption("sendBufferSize", configuration.getSendBufferSize());
193 connectionlessServerBootstrap.setOption("receiveBufferSize", configuration.getReceiveBufferSize());
194 // only set this if user has specified
195 if (configuration.getReceiveBufferSizePredictor() > 0) {
196 connectionlessServerBootstrap.setOption("receiveBufferSizePredictorFactory",
197 new FixedReceiveBufferSizePredictorFactory(configuration.getReceiveBufferSizePredictor()));
198 }
199
200 channel = connectionlessServerBootstrap.bind(new InetSocketAddress(configuration.getHost(), configuration.getPort()));
201 // to keep track of all channels in use
202 allChannels.add(channel);
203 }
204
205 }