/*
* 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.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.juddi.v3.client.config.UDDIClerkManager;
import org.apache.juddi.v3.client.config.UDDIClientContainer;
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.soa.esb.util.ClassUtil;
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;
/**
* InVM server side (usually scoped) transport that can be exposed through a client delegation layer.
*
* There is no interface for this service so we extend the jUDDI transport class
* and delegate to another implementation.
*/
public class JuddiInVMServerTransport extends Transport
{
/**
* The current transport manager name.
*/
private final String managerName ;
/**
* The current transport node name.
*/
private final String nodeName ;
/**
* Our class loader.
*/
private final ClassLoader classLoader = getClass().getClassLoader() ;
/**
* The juddi api port type instance.
*/
private final AtomicReference<JUDDIApiPortType> juddiApiPortTypeRef = new AtomicReference<JUDDIApiPortType>() ;
/**
* The uddi custody transfer port type instance.
*/
private final AtomicReference<UDDICustodyTransferPortType> uddiCustodyTransferPortTypeRef = new AtomicReference<UDDICustodyTransferPortType>() ;
/**
* The uddi inquiry port type instance.
*/
private final AtomicReference<UDDIInquiryPortType> uddiInquiryPortTypeRef = new AtomicReference<UDDIInquiryPortType>() ;
/**
* The uddi publication port type instance.
*/
private final AtomicReference<UDDIPublicationPortType> uddiPublicationPortTypeRef = new AtomicReference<UDDIPublicationPortType>() ;
/**
* The uddi security port type instance.
*/
private final AtomicReference<UDDISecurityPortType> uddiSecurityPortTypeRef = new AtomicReference<UDDISecurityPortType>() ;
/**
* The uddi subscription listener port type instance.
*/
private final AtomicReference<UDDISubscriptionListenerPortType> uddiSubscriptionListenerPortTypeRef = new AtomicReference<UDDISubscriptionListenerPortType>() ;
/**
* The uddi subscription port type instance.
*/
private final AtomicReference<UDDISubscriptionPortType> uddiSubscriptionPortTypeRef = new AtomicReference<UDDISubscriptionPortType>() ;
/**
* The executor service.
*/
private final AtomicReference<ExecutorService> executorServiceReference ;
/**
* Construct the InVM server transport instance with the delegated instance.
* @param managerName The manager name of the transport.
* @param nodeName The node name of the transport.
* @param executorServiceReference The task executor.
*/
public JuddiInVMServerTransport(final String managerName, final String nodeName, final AtomicReference<ExecutorService> executorServiceReference)
{
this.managerName = managerName ;
this.nodeName = nodeName ;
this.executorServiceReference = executorServiceReference ;
}
@Override
public JUDDIApiPortType getJUDDIApiService(final String endpointURL)
throws TransportException
{
final JUDDIApiPortType current = juddiApiPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String juddiApiUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
juddiApiUrl = manager.getClientConfig().getUDDINode(nodeName).getJuddiApiUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover juddiApiUrl for node " + nodeName, ce) ;
}
}
else
{
juddiApiUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(juddiApiUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final JUDDIApiPortType juddiApiPortType = (JUDDIApiPortType) Proxy.newProxyInstance(classLoader,
new Class[] {JUDDIApiPortType.class}, handler) ;
if (juddiApiPortTypeRef.compareAndSet(null, juddiApiPortType))
{
return juddiApiPortType ;
}
else
{
return juddiApiPortTypeRef.get() ;
}
}
@Override
public UDDICustodyTransferPortType getUDDICustodyTransferService(final String endpointURL)
throws TransportException
{
final UDDICustodyTransferPortType current = uddiCustodyTransferPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String custodyTransferUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
custodyTransferUrl = manager.getClientConfig().getUDDINode(nodeName).getCustodyTransferUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover custodyTransferUrl for node " + nodeName, ce) ;
}
}
else
{
custodyTransferUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(custodyTransferUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final UDDICustodyTransferPortType uddiCustodyTransferPortType = (UDDICustodyTransferPortType) Proxy.newProxyInstance(classLoader,
new Class[] {UDDICustodyTransferPortType.class}, handler) ;
if (uddiCustodyTransferPortTypeRef.compareAndSet(null, uddiCustodyTransferPortType))
{
return uddiCustodyTransferPortType ;
}
else
{
return uddiCustodyTransferPortTypeRef.get() ;
}
}
@Override
public UDDIInquiryPortType getUDDIInquiryService(final String endpointURL)
throws TransportException
{
final UDDIInquiryPortType current = uddiInquiryPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String inquiryUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
inquiryUrl = manager.getClientConfig().getUDDINode(nodeName).getInquiryUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover inquiryUrl for node " + nodeName, ce) ;
}
}
else
{
inquiryUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(inquiryUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final UDDIInquiryPortType uddiInquiryPortType = (UDDIInquiryPortType) Proxy.newProxyInstance(classLoader,
new Class[] {UDDIInquiryPortType.class}, handler) ;
if (uddiInquiryPortTypeRef.compareAndSet(null, uddiInquiryPortType))
{
return uddiInquiryPortType ;
}
else
{
return uddiInquiryPortTypeRef.get() ;
}
}
@Override
public UDDIPublicationPortType getUDDIPublishService(final String endpointURL)
throws TransportException
{
final UDDIPublicationPortType current = uddiPublicationPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String publishUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
publishUrl = manager.getClientConfig().getUDDINode(nodeName).getPublishUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover publishUrl for node " + nodeName, ce) ;
}
}
else
{
publishUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(publishUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final UDDIPublicationPortType uddiPublicationPortType = (UDDIPublicationPortType) Proxy.newProxyInstance(classLoader,
new Class[] {UDDIPublicationPortType.class}, handler) ;
if (uddiPublicationPortTypeRef.compareAndSet(null, uddiPublicationPortType))
{
return uddiPublicationPortType ;
}
else
{
return uddiPublicationPortTypeRef.get() ;
}
}
@Override
public UDDISecurityPortType getUDDISecurityService(final String endpointURL)
throws TransportException
{
final UDDISecurityPortType current = uddiSecurityPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String securityUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
securityUrl = manager.getClientConfig().getUDDINode(nodeName).getSecurityUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover securityUrl for node " + nodeName, ce) ;
}
}
else
{
securityUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(securityUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final UDDISecurityPortType uddiSecurityPortType = (UDDISecurityPortType) Proxy.newProxyInstance(classLoader,
new Class[] {UDDISecurityPortType.class}, handler) ;
if (uddiSecurityPortTypeRef.compareAndSet(null, uddiSecurityPortType))
{
return uddiSecurityPortType ;
}
else
{
return uddiSecurityPortTypeRef.get() ;
}
}
@Override
public UDDISubscriptionListenerPortType getUDDISubscriptionListenerService(final String endpointURL)
throws TransportException
{
final UDDISubscriptionListenerPortType current = uddiSubscriptionListenerPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String subscriptionListenerUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
subscriptionListenerUrl = manager.getClientConfig().getUDDINode(nodeName).getSubscriptionListenerUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover subscriptionListenerUrl for node " + nodeName, ce) ;
}
}
else
{
subscriptionListenerUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(subscriptionListenerUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final UDDISubscriptionListenerPortType uddiSubscriptionListenerPortType = (UDDISubscriptionListenerPortType) Proxy.newProxyInstance(classLoader,
new Class[] {UDDISubscriptionListenerPortType.class}, handler) ;
if (uddiSubscriptionListenerPortTypeRef.compareAndSet(null, uddiSubscriptionListenerPortType))
{
return uddiSubscriptionListenerPortType ;
}
else
{
return uddiSubscriptionListenerPortTypeRef.get() ;
}
}
@Override
public UDDISubscriptionPortType getUDDISubscriptionService(final String endpointURL)
throws TransportException
{
final UDDISubscriptionPortType current = uddiSubscriptionPortTypeRef.get() ;
if (current != null)
{
return current ;
}
final String subscriptionUrl ;
if (endpointURL == null)
{
try
{
final UDDIClerkManager manager = UDDIClientContainer.getUDDIClerkManager(managerName) ;
subscriptionUrl = manager.getClientConfig().getUDDINode(nodeName).getSubscriptionUrl() ;
}
catch (final ConfigurationException ce)
{
throw new TransportException("Could not discover subscriptionUrl for node " + nodeName, ce) ;
}
}
else
{
subscriptionUrl = endpointURL ;
}
final Object delegatePortType = createDelegate(subscriptionUrl) ;
final InvocationHandler handler = new TaskHandler(delegatePortType) ;
final UDDISubscriptionPortType uddiSubscriptionPortType = (UDDISubscriptionPortType) Proxy.newProxyInstance(classLoader,
new Class[] {UDDISubscriptionPortType.class}, handler) ;
if (uddiSubscriptionPortTypeRef.compareAndSet(null, uddiSubscriptionPortType))
{
return uddiSubscriptionPortType ;
}
else
{
return uddiSubscriptionPortTypeRef.get() ;
}
}
/**
* Create an instance of the delegate class.
* @param delegate The name of the delegate class.
* @return The delegate class instance.
* @throws TransportException For errors during loading/instantiation.
*/
private Object createDelegate(final String delegate)
throws TransportException
{
try
{
final Class<?> delegateClass = ClassUtil.forName(delegate, getClass()) ;
return delegateClass.newInstance() ;
}
catch (final ClassNotFoundException cnfe)
{
throw new TransportException("Failed to locate delegate class " + delegate, cnfe) ;
}
catch (final InstantiationException ie)
{
throw new TransportException("Failed to instantiate delegate class " + delegate, ie) ;
}
catch (final IllegalAccessException iae)
{
throw new TransportException("Failed to instantiate delegate class " + delegate, iae) ;
}
}
/**
* Task handler responsible for executing juddi requests on the executor service.
* @author kevin
*/
private final class TaskHandler implements InvocationHandler
{
private final Object target ;
/**
* Construct the task handler for the specified target instance.
* @param target The target instance.
*/
TaskHandler(final Object target)
{
this.target = target ;
}
/**
* Handle the proxy invocation using the executor.
* @param proxy The proxy instance.
* @param method The method being invoked.
* @param args The arguments for the method invocation.
*/
public Object invoke(final Object proxy, final Method method, final Object[] args)
throws Throwable
{
final ExecutorService executorService = executorServiceReference.get() ;
if (executorService == null)
{
throw new TransportException("InVM Server executor service not initialised") ;
}
else
{
final Callable<Object> task = new Callable<Object>() {
public Object call() throws Exception {
return method.invoke(target, args) ;
}
};
final Future<Object> future = executorService.submit(task) ;
return future.get() ;
}
}
}
}