/**
* Copyright 2007-2015, Kaazing Corporation. All rights reserved.
*
* 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.kaazing.k3po.driver.internal.netty.bootstrap.tcp;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.net.URI;
import java.util.Collection;
import java.util.concurrent.ConcurrentLinkedDeque;
import java.util.concurrent.Executor;
import javax.annotation.Resource;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.ClientSocketChannelFactory;
import org.jboss.netty.channel.socket.ServerSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioClientBossPool;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioServerBossPool;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.channel.socket.nio.NioWorkerPool;
import org.jboss.netty.util.ExternalResourceReleasable;
import org.kaazing.k3po.driver.internal.executor.ExecutorServiceFactory;
import org.kaazing.k3po.driver.internal.netty.bootstrap.BootstrapFactorySpi;
import org.kaazing.k3po.driver.internal.netty.bootstrap.ClientBootstrap;
import org.kaazing.k3po.driver.internal.netty.bootstrap.ServerBootstrap;
import org.kaazing.k3po.driver.internal.netty.channel.ChannelAddress;
import static org.kaazing.k3po.driver.internal.channel.Channels.toInetSocketAddress;
public final class TcpBootstrapFactorySpi extends BootstrapFactorySpi implements ExternalResourceReleasable {
private final Collection<ChannelFactory> channelFactories;
private ExecutorServiceFactory executorServiceFactory;
private NioClientSocketChannelFactory clientChannelFactory;
private NioServerSocketChannelFactory serverChannelFactory;
public TcpBootstrapFactorySpi() {
channelFactories = new ConcurrentLinkedDeque<>();
}
@Resource
public void setExecutorServiceFactory(ExecutorServiceFactory executorServiceFactory) {
this.executorServiceFactory = executorServiceFactory;
}
@Resource
public void setNioClientSocketChannelFactory(NioClientSocketChannelFactory clientChannelFactory) {
this.clientChannelFactory = clientChannelFactory;
}
@Resource
public void setNioServerSocketChannelFactory(NioServerSocketChannelFactory serverChannelFactory) {
this.serverChannelFactory = serverChannelFactory;
}
/**
* Returns the name of the transport provided by factories using this service provider.
*/
@Override
public String getTransportName() {
return "tcp";
}
@Override
public void shutdown() {
for (ChannelFactory channelFactory : channelFactories) {
channelFactory.shutdown();
}
}
@Override
public void releaseExternalResources() {
for (ChannelFactory channelFactory : channelFactories) {
channelFactory.releaseExternalResources();
}
}
/**
* Returns a {@link ClientBootstrap} instance for the named transport.
*/
@Override
public synchronized ClientBootstrap newClientBootstrap() throws Exception {
ClientSocketChannelFactory clientChannelFactory = this.clientChannelFactory;
if (clientChannelFactory == null) {
Executor bossExecutor = executorServiceFactory.newExecutorService("boss.client");
NioClientBossPool bossPool = new NioClientBossPool(bossExecutor, 1);
Executor workerExecutor = executorServiceFactory.newExecutorService("worker.client");
NioWorkerPool workerPool = new NioWorkerPool(workerExecutor, 1);
clientChannelFactory = new NioClientSocketChannelFactory(bossPool, workerPool);
// unshared
channelFactories.add(clientChannelFactory);
}
return new ClientBootstrap(clientChannelFactory) {
@Override
public ChannelFuture connect(final SocketAddress localAddress, final SocketAddress remoteAddress) {
final InetSocketAddress localChannelAddress = toInetSocketAddress((ChannelAddress) localAddress);
final InetSocketAddress remoteChannelAddress = toInetSocketAddress((ChannelAddress) remoteAddress);
return super.connect(localChannelAddress, remoteChannelAddress);
}
};
}
/**
* Returns a {@link ServerBootstrap} instance for the named transport.
*/
@Override
public synchronized ServerBootstrap newServerBootstrap() throws Exception {
ServerSocketChannelFactory serverChannelFactory = this.serverChannelFactory;
if (serverChannelFactory == null) {
Executor bossExecutor = executorServiceFactory.newExecutorService("boss.server");
NioServerBossPool bossPool = new NioServerBossPool(bossExecutor, 1);
Executor workerExecutor = executorServiceFactory.newExecutorService("worker.server");
NioWorkerPool workerPool = new NioWorkerPool(workerExecutor, 1);
serverChannelFactory = new NioServerSocketChannelFactory(bossPool, workerPool);
// unshared
channelFactories.add(serverChannelFactory);
}
return new ServerBootstrap(serverChannelFactory) {
@Override
public ChannelFuture bindAsync(SocketAddress localAddress) {
return super.bindAsync(toInetSocketAddress(localAddress));
}
};
}
}