/*
* JBoss, Home of Professional Open Source
* Copyright 2006, 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.internal.soa.esb.registry.server;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.juddi.v3.client.transport.Transport;
import org.apache.juddi.v3.client.transport.TransportException;
import org.apache.juddi.v3_service.JUDDIApiPortType;
import org.jboss.internal.soa.esb.registry.client.ESBInVMTransport;
import org.jboss.internal.soa.esb.registry.client.JuddiInVMTransport;
import org.uddi.v3_service.UDDICustodyTransferPortType;
import org.uddi.v3_service.UDDIInquiryPortType;
import org.uddi.v3_service.UDDIPublicationPortType;
import org.uddi.v3_service.UDDISecurityPortType;
import org.uddi.v3_service.UDDISubscriptionListenerPortType;
import org.uddi.v3_service.UDDISubscriptionPortType;
/**
* ESB InVM server side delegating to node specific transports.
*
* @author <a href='Kevin.Conner@jboss.com'>Kevin Conner</a>
*/
public class ESBInVMServerTransport implements ESBInVMTransport
{
/**
* Our class loader.
*/
private final ClassLoader classLoader = getClass().getClassLoader() ;
/**
* Default key for null managers.
*/
private static final byte[] DEFAULT_KEY = new byte[0] ;
/**
* The configured transports.
*/
private final ConcurrentHashMap<Object, ConcurrentHashMap<String, Transport>> managerTransports = new ConcurrentHashMap<Object, ConcurrentHashMap<String, Transport>>() ;
/**
* The executor service.
*/
private final AtomicReference<ExecutorService> executorServiceReference = new AtomicReference<ExecutorService>();
/**
* Return an API service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The API service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public JUDDIApiPortType getJUDDIApiService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getJUDDIApiService(endpointURL) ;
}
/**
* Return a Custody Transfer service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The Custody Transfer service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public UDDICustodyTransferPortType getUDDICustodyTransferService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getUDDICustodyTransferService(endpointURL) ;
}
/**
* Return an Inquiry service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The Inquiry service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public UDDIInquiryPortType getUDDIInquiryService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getUDDIInquiryService(endpointURL) ;
}
/**
* Return a Publish service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The Publish service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public UDDIPublicationPortType getUDDIPublishService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getUDDIPublishService(endpointURL) ;
}
/**
* Return a Security service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The Security service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public UDDISecurityPortType getUDDISecurityService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getUDDISecurityService(endpointURL) ;
}
/**
* Return a Subscription Listener service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The Subscription Listener service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public UDDISubscriptionListenerPortType getUDDISubscriptionListenerService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getUDDISubscriptionListenerService(endpointURL) ;
}
/**
* Return a Subscription service for the specified node name and endpoint URL.
* @param managerName The manager name.
* @param nodeName The node name.
* @param endpointURL The endpoint URL
* @return The Subscription service implementation.
* @throws TransportException For exceptions obtaining the service implementation.
*/
public UDDISubscriptionPortType getUDDISubscriptionService(final String managerName, final String nodeName, final String endpointURL)
throws TransportException
{
return getTransport(managerName, nodeName).getUDDISubscriptionService(endpointURL) ;
}
/**
* Get the transport for the specified node.
* @param managerName The manager name.
* @param nodeName The node name.
* @return The in vm transport.
*/
private Transport getTransport(final String managerName, final String nodeName)
{
final ConcurrentHashMap<String, Transport> transports = getTransports(managerName) ;
final Transport transport = transports.get(nodeName) ;
if (transport != null)
{
return transport ;
}
final JuddiInVMServerTransport juddiTransport = new JuddiInVMServerTransport(managerName, nodeName, executorServiceReference) ;
final Transport current = transports.putIfAbsent(nodeName, juddiTransport) ;
return (current != null ? current: juddiTransport) ;
}
/**
* Get the transports for the specified manager.
* @param managerName The manager name.
* @return The manager transports.
*/
private ConcurrentHashMap<String, Transport> getTransports(final String managerName)
{
final Object key = (managerName != null ? managerName : DEFAULT_KEY) ;
final ConcurrentHashMap<String, Transport> transports = managerTransports.get(key) ;
if (transports != null)
{
return transports ;
}
final ConcurrentHashMap<String, Transport> newTransports = new ConcurrentHashMap<String, Transport>() ;
final ConcurrentHashMap<String, Transport> current = managerTransports.putIfAbsent(key, newTransports) ;
return (current != null ? current: newTransports) ;
}
/**
* Start the background executor.
* @param numThreads The number of threads for the background executor.
*/
public void start(final int numThreads)
throws TransportException
{
if (!executorServiceReference.compareAndSet(null, Executors.newFixedThreadPool(numThreads, new ScopedThreadFactory())))
{
throw new TransportException("Executor service already initialised") ;
}
JuddiInVMTransport.setImplementation(this) ;
}
/**
* Stop the background executor.
* @param timeout The number of seconds to wait for the background executor to terminate.
*/
public void stop(final long timeout)
throws InterruptedException
{
final ExecutorService executorService = executorServiceReference.getAndSet(null) ;
if (executorService != null)
{
JuddiInVMTransport.setImplementation(null) ;
executorService.shutdown() ;
executorService.awaitTermination(timeout, TimeUnit.SECONDS) ;
}
}
/**
* Thread factory executing within the scoped classloader.
*
* @author kevin
*/
private final class ScopedThreadFactory implements ThreadFactory
{
/**
* The default executor factory.
*/
private final ThreadFactory defaultFactory = Executors.defaultThreadFactory() ;
/**
* Return a new daemon thread.
* @param runnable The runnable associated with the thread.
*/
public Thread newThread(final Runnable runnable)
{
final Thread thread = defaultFactory.newThread(runnable) ;
thread.setContextClassLoader(classLoader) ;
return thread ;
}
}
}