/*
* JBoss, Home of Professional Open Source
* Copyright 2008, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jboss.xnio.metadata;
import java.net.SocketAddress;
import java.util.List;
import java.util.ArrayList;
import java.util.Random;
import java.util.concurrent.Executor;
import java.util.concurrent.atomic.AtomicInteger;
import java.io.Closeable;
import org.jboss.beans.metadata.spi.BeanMetaData;
import org.jboss.beans.metadata.spi.ValueMetaData;
import org.jboss.beans.metadata.spi.builder.BeanMetaDataBuilder;
import org.jboss.xnio.Xnio;
import org.jboss.xnio.IoHandlerFactory;
import org.jboss.xnio.TcpChannelSource;
import org.jboss.xnio.channels.BoundServer;
import org.jboss.xnio.helpers.XnioController;
/**
*
*/
public final class XnioMetaDataHelper {
private static final String DEFAULT_PROVIDER_BEAN_NAME = "XnioProvider";
private static final AtomicInteger PRIVATE_SEQ = new AtomicInteger(new Random().nextInt());
private XnioMetaDataHelper() {}
public static SocketAddress[] getBindAddresses(List<InetSocketAddressMetaData> inetSocketAddressMetaDataList) {
final int bindCount = inetSocketAddressMetaDataList.size();
SocketAddress[] addresses = new SocketAddress[bindCount];
int i = 0;
for (InetSocketAddressMetaData metaData : inetSocketAddressMetaDataList) {
addresses[i++] = metaData.getSocketAddress();
}
return addresses;
}
public static ValueMetaData createInject(BeanMetaDataBuilder builder, NamedBeanMetaData namedBeanMetaData) {
return builder.createInject(namedBeanMetaData.getName());
}
public static void addConfigProperties(BeanMetaDataBuilder builder, AbstractConfigurableMetaData configData) {
final Integer backlog = configData.getBacklog();
if (backlog != null) builder.addPropertyMetaData("backlog", backlog);
final Boolean broadcast = configData.getBroadcast();
if (broadcast != null) builder.addPropertyMetaData("broadcast", broadcast);
final Boolean closeAbort = configData.getCloseAbort();
if (closeAbort != null) builder.addPropertyMetaData("closeAbort", closeAbort);
final Integer ipTrafficClass = configData.getIpTrafficClass();
if (ipTrafficClass != null) builder.addPropertyMetaData("ipTrafficClass", ipTrafficClass);
final Integer ipTos = configData.getIpTos();
if (ipTos != null) builder.addPropertyMetaData("ipTos", ipTos);
final Boolean keepAlive = configData.getKeepAlive();
if (keepAlive != null) builder.addPropertyMetaData("keepAlive", keepAlive);
final Boolean manageConnections = configData.getManageConnections();
if (manageConnections != null) builder.addPropertyMetaData("manageConnections", manageConnections);
final Integer multicastTtl = configData.getMulticastTtl();
if (multicastTtl != null) builder.addPropertyMetaData("multicastTtl", multicastTtl);
final Boolean oobInline = configData.getOobInline();
if (oobInline != null) builder.addPropertyMetaData("oobInline", oobInline);
final Integer receiveBufferSize = configData.getReceiveBufferSize();
if (receiveBufferSize != null) builder.addPropertyMetaData("receiveBufferSize", receiveBufferSize);
final Boolean reuseAddress = configData.getReuseAddress();
if (reuseAddress != null) builder.addPropertyMetaData("reuseAddress", reuseAddress);
final Integer sendBufferSize = configData.getSendBufferSize();
if (sendBufferSize != null) builder.addPropertyMetaData("sendBufferSize", sendBufferSize);
final Boolean tcpNoDelay = configData.getTcpNoDelay();
if (tcpNoDelay != null) builder.addPropertyMetaData("tcpNoDelay", tcpNoDelay);
}
public static void add(final List<BeanMetaData> list, final String provider, final PipeConnectorMetaData pipeConnectorMetaData, final String createMethodName) {
// pipe connectors are not configurable
final String name = pipeConnectorMetaData.getName();
final NamedBeanMetaData executorBean = pipeConnectorMetaData.getExecutorBean();
final NamedBeanMetaData handlerFactoryBean = pipeConnectorMetaData.getHandlerFactoryBean();
final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, Closeable.class.getName());
if (provider != null) {
builder.setFactory(builder.createInject(provider));
} else {
// todo: createInject auto-wired based on class
builder.setFactory(builder.createInject(DEFAULT_PROVIDER_BEAN_NAME));
}
builder.setFactoryMethod(createMethodName);
if (executorBean != null) {
builder.addConstructorParameter(Executor.class.getName(), builder.createInject(executorBean.getName()));
}
builder.addConstructorParameter(IoHandlerFactory.class.getName(), builder.createInject(handlerFactoryBean.getName()));
builder.setStop("close");
list.add(builder.getBeanMetaData());
}
private static BeanMetaDataBuilder getConfigurableBeanMetaDataBuilder(final String provider, final AbstractConfigurableMetaData configurableMetaData) {
final String name = configurableMetaData.getName();
final String privateName = name + ":Xnio-private:" + Integer.toHexString(name.hashCode()) + ":" + Integer.toHexString(PRIVATE_SEQ.getAndIncrement());
final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(privateName, XnioController.class.getName());
if (provider != null) {
builder.addConstructorParameter(Xnio.class.getName(), builder.createInject(provider));
} else {
// todo: createInject auto-wired based on class
builder.addConstructorParameter(Xnio.class.getName(), builder.createInject(DEFAULT_PROVIDER_BEAN_NAME));
}
addConfigProperties(builder, configurableMetaData);
return builder;
}
private static void addPublicAndPrivate(final List<BeanMetaData> list, final String name, final BeanMetaDataBuilder builder) {
final BeanMetaData privateBeanMetaData = builder.getBeanMetaData();
list.add(privateBeanMetaData);
final BeanMetaDataBuilder publicBuilder = BeanMetaDataBuilder.createBuilder(name, BoundServer.class.getName());
publicBuilder.setFactory(privateBeanMetaData);
publicBuilder.setFactoryMethod("getHandle");
list.add(publicBuilder.getBeanMetaData());
}
public static void add(final List<BeanMetaData> list, final String provider, final TcpServerMetaData tcpServerMetaData) {
final String name = tcpServerMetaData.getName();
final NamedBeanMetaData handlerFactoryBean = tcpServerMetaData.getHandlerFactoryBean();
final NamedBeanMetaData executorBean = tcpServerMetaData.getExecutorBean();
final BeanMetaDataBuilder builder = getConfigurableBeanMetaDataBuilder(provider, tcpServerMetaData);
builder.setFactoryMethod("tcpServer");
if (executorBean != null) {
builder.addConstructorParameter(Executor.class.getName(), builder.createInject(executorBean.getName()));
}
builder.addConstructorParameter(IoHandlerFactory.class.getName(), builder.createInject(handlerFactoryBean.getName()));
final List<SocketAddress> socketAddresses = new ArrayList<SocketAddress>();
for (InetSocketAddressMetaData metaData : tcpServerMetaData.getBindAddresses()) {
socketAddresses.add(metaData.getSocketAddress());
}
builder.addConstructorParameter(SocketAddress[].class.getName(), builder.createValue(socketAddresses.toArray(new SocketAddress[socketAddresses.size()])));
addPublicAndPrivate(list, name, builder);
}
public static void add(final List<BeanMetaData> list, final String provider, final TcpConnectorMetaData tcpConnectorMetaData) {
final String name = tcpConnectorMetaData.getName();
final NamedBeanMetaData executorBean = tcpConnectorMetaData.getExecutorBean();
final BeanMetaDataBuilder builder = getConfigurableBeanMetaDataBuilder(provider, tcpConnectorMetaData);
builder.setFactoryMethod("tcpConnector");
if (executorBean != null) {
builder.addConstructorParameter(Executor.class.getName(), builder.createInject(executorBean.getName()));
}
addPublicAndPrivate(list, name, builder);
}
public static void add(final List<BeanMetaData> list, final String provider, final UdpServerMetaData udpServerMetaData) {
final String name = udpServerMetaData.getName();
final NamedBeanMetaData handlerFactoryBean = udpServerMetaData.getHandlerFactoryBean();
final NamedBeanMetaData executorBean = udpServerMetaData.getExecutorBean();
final BeanMetaDataBuilder builder = getConfigurableBeanMetaDataBuilder(provider, udpServerMetaData);
builder.setFactoryMethod("udpServer");
if (executorBean != null) {
builder.addConstructorParameter(Executor.class.getName(), builder.createInject(executorBean.getName()));
}
final Boolean multicast = udpServerMetaData.getMulticast();
builder.addConstructorParameter(boolean.class.getName(), builder.createValue(multicast == null ? Boolean.FALSE : multicast));
builder.addConstructorParameter(IoHandlerFactory.class.getName(), builder.createInject(handlerFactoryBean.getName()));
final List<SocketAddress> socketAddresses = new ArrayList<SocketAddress>();
for (InetSocketAddressMetaData metaData : udpServerMetaData.getBindAddresses()) {
socketAddresses.add(metaData.getSocketAddress());
}
builder.addConstructorParameter(SocketAddress[].class.getName(), builder.createValue(socketAddresses.toArray(new SocketAddress[socketAddresses.size()])));
addPublicAndPrivate(list, name, builder);
}
public static void add(final List<BeanMetaData> list, final TcpChannelSourceMetaData tcpChannelSourceMetaData) {
final String name = tcpChannelSourceMetaData.getName();
final DestinationMetaData destination = tcpChannelSourceMetaData.getDestination();
final NamedBeanMetaData connectorBean = tcpChannelSourceMetaData.getTcpConnectorBean();
final BeanMetaDataBuilder builder = BeanMetaDataBuilder.createBuilder(name, TcpChannelSource.class.getName());
builder.setFactory(builder.createInject(connectorBean.getName()));
builder.setFactoryMethod("createChannelSource");
final InetSocketAddressMetaData src = destination.getBindAddress();
final InetSocketAddressMetaData dest = destination.getConnectAddress();
if (src != null) {
builder.addConstructorParameter(SocketAddress.class.getName(), src.getSocketAddress());
}
builder.addConstructorParameter(SocketAddress.class.getName(), dest.getSocketAddress());
list.add(builder.getBeanMetaData());
}
}