package org.jboss.webservice.client;
import org.jboss.logging.Logger;
import org.jboss.webservice.metadata.jaxrpcmapping.JavaWsdlMapping;
import org.jboss.webservice.util.WSDLUtilities;
import javax.wsdl.Definition;
import javax.xml.rpc.JAXRPCException;
import javax.xml.rpc.Service;
import javax.xml.rpc.ServiceException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.rmi.Remote;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ServiceProxy implements InvocationHandler
{
private static final Logger log = Logger.getLogger(ServiceProxy.class);
private ServiceImpl jaxrpcService;
private List objectMethods = new ArrayList();
private List jaxrpcServiceMethods = new ArrayList();
private List serviceInterfaceMethods = new ArrayList();
private List endorsedServiceEndpointClasses = new ArrayList();
private Method getPortMethod;
public ServiceProxy(ServiceImpl service, Class siClass)
{
this.jaxrpcService = service;
objectMethods.addAll(Arrays.asList(java.lang.Object.class.getMethods()));
jaxrpcServiceMethods.addAll(Arrays.asList(javax.xml.rpc.Service.class.getMethods()));
if (siClass.getName().equals("javax.xml.rpc.Service") == false)
serviceInterfaceMethods.addAll(Arrays.asList(siClass.getDeclaredMethods()));
try
{
getPortMethod = Service.class.getMethod("getPort", new Class[]{Class.class});
}
catch (NoSuchMethodException e)
{
throw new JAXRPCException(e.toString());
}
}
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable
{
String methodName = method.getName();
try
{
Object retObj = null;
if (jaxrpcServiceMethods.contains(method))
{
log.debug("Invoke on jaxrpc service: " + methodName);
if (method.getName().equals("getPort"))
{
Class seiClass = (Class)(args.length == 1 ? args[0] : args[1]);
endorseServiceEndpointClass(seiClass);
Remote port = (Remote)method.invoke(jaxrpcService, args);
return port;
}
else
{
retObj = method.invoke(jaxrpcService, args);
return retObj;
}
}
if (serviceInterfaceMethods.contains(method))
{
log.debug("Invoke on service interface: " + methodName);
Class seiClass = method.getReturnType();
retObj = getPortMethod.invoke(jaxrpcService, new Object[]{seiClass});
return retObj;
}
if (objectMethods.contains(method))
{
log.debug("Invoke on object: " + methodName);
retObj = method.invoke(jaxrpcService, args);
return retObj;
}
throw new JAXRPCException("Don't know how to invoke: " + method);
}
catch (Exception e)
{
handleException(e);
return null;
}
}
private void handleException(Exception ex) throws Throwable
{
Throwable th = ex;
if (ex instanceof InvocationTargetException)
th = ((InvocationTargetException)ex).getTargetException();
log.error("Service error", th);
throw th;
}
private void endorseServiceEndpointClass(Class seiClass) throws ServiceException
{
if (endorsedServiceEndpointClasses.contains(seiClass))
return;
Definition wsdlDefinition = jaxrpcService.getWsdlDefinition();
JavaWsdlMapping jaxrpcMapping = jaxrpcService.getJavaWsdlMapping();
WSDLUtilities.endorseServiceEndpointInterface(wsdlDefinition, seiClass, jaxrpcMapping);
endorsedServiceEndpointClasses.add(seiClass);
}
}