package org.jboss.webservice.server;
import org.jboss.axis.AxisFault;
import org.jboss.axis.MessageContext;
import org.jboss.axis.handlers.soap.SOAPService;
import org.jboss.axis.message.SOAPEnvelopeAxisImpl;
import org.jboss.axis.providers.java.RPCInvocation;
import org.jboss.axis.providers.java.RPCProvider;
import org.jboss.axis.transport.http.HTTPConstants;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.logging.Logger;
import org.jboss.mx.util.MBeanServerLocator;
import org.jboss.webservice.AxisServiceMBean;
import org.jboss.webservice.PortComponentInfo;
import org.jboss.webservice.handler.ServerHandlerChain;
import org.jboss.webservice.metadata.HandlerMetaData;
import org.jboss.webservice.metadata.InitParamMetaData;
import org.jboss.webservice.metadata.PortComponentMetaData;
import org.jboss.webservice.metadata.WebserviceDescriptionMetaData;
import org.w3c.dom.Document;
import javax.management.MBeanServer;
import javax.servlet.http.HttpServletRequest;
import javax.xml.namespace.QName;
import javax.xml.rpc.handler.HandlerInfo;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
public abstract class InvokerProvider extends RPCProvider
{
static final long serialVersionUID = 3036485550614460123L;
private Logger log = Logger.getLogger(InvokerProvider.class);
protected MBeanServer server;
protected PortComponentInfo portComponentInfo;
protected ServerHandlerChain handlerChain;
public void initServiceDesc(SOAPService service, MessageContext msgContext)
throws AxisFault
{
log.debug("initServiceDesc: service=" + service.getName());
try
{
server = MBeanServerLocator.locateJBoss();
String wsID = (String)service.getOption(PortComponentMetaData.PARAMETER_WEBSERVICE_ID);
portComponentInfo = (PortComponentInfo)server.invoke(AxisServiceMBean.OBJECT_NAME,
"getPortComponentInfo", new Object[]{wsID}, new String[]{String.class.getName()});
if (portComponentInfo == null)
throw new ServiceException("Cannot obtain port component info for: " + wsID);
initHandlerChain();
}
catch (Exception e)
{
throw new ServiceException("Cannot initialize webservice", e);
}
super.initServiceDesc(service, msgContext);
}
private void initHandlerChain() throws Exception
{
ClassLoader cl = getContextClassLoader();
HashSet handlerRoles = new HashSet();
ArrayList handlerInfos = new ArrayList();
HandlerMetaData[] handlers = portComponentInfo.getPortComponentMetaData().getHandlers();
for (int i = 0; i < handlers.length; i++)
{
HandlerMetaData hMetaData = handlers[i];
handlerRoles.addAll(Arrays.asList(hMetaData.getSoapRoles()));
Class hClass = cl.loadClass(hMetaData.getHandlerClass());
HashMap hConfig = new HashMap();
InitParamMetaData[] params = hMetaData.getInitParams();
for (int j = 0; j < params.length; j++)
{
InitParamMetaData param = params[j];
hConfig.put(param.getParamName(), param.getParamValue());
}
QName[] hHeaders = hMetaData.getSoapHeaders();
HandlerInfo info = new HandlerInfo(hClass, hConfig, hHeaders);
String serviceName = portComponentInfo.getPortComponentMetaData().getPortComponentName();
log.debug("Adding server side handler to service '" + serviceName + "': " + info);
handlerInfos.add(info);
}
handlerChain = new ServerHandlerChain(handlerInfos, handlerRoles);
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader(getContextClassLoader());
if (handlerChain.getState() == ServerHandlerChain.STATE_CREATED)
{
handlerChain.init(null);
}
}
finally
{
Thread.currentThread().setContextClassLoader(ccl);
}
}
abstract protected ClassLoader getContextClassLoader();
public void generateWSDL(MessageContext msgContext) throws AxisFault
{
HttpServletRequest req = (HttpServletRequest)msgContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST);
if (req == null)
throw new IllegalStateException("Cannot obtain HttpServletRequest from msg context");
try
{
String resourcePath = (String)msgContext.getProperty(MessageContext.WSDLGEN_RESOURCE);
String requestURI = req.getRequestURI();
WebserviceDescriptionMetaData webserviceDescription = portComponentInfo.getPortComponentMetaData().getWebserviceDescription();
DeploymentInfo di = portComponentInfo.getDeploymentInfo();
WSDLRequestHandler wsdlRequestHandler = new WSDLRequestHandler(webserviceDescription, di);
Document document = wsdlRequestHandler.getDocumentForPath(requestURI, resourcePath);
msgContext.setProperty("WSDL", document);
}
catch (Exception e)
{
log.error("Cannot process WSDL document", e);
}
}
public RPCInvocation createRPCInvocation(MessageContext msgContext, SOAPEnvelopeAxisImpl reqEnv, SOAPEnvelopeAxisImpl resEnv, Object obj)
{
RPCInvocation invocation = new JBossRPCInvocation(this, msgContext, reqEnv, resEnv, obj);
return invocation;
}
public PortComponentInfo getPortComponentInfo()
{
return portComponentInfo;
}
protected Class getServiceClass(String clsName, SOAPService service, MessageContext msgContext)
throws AxisFault
{
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader(getContextClassLoader());
String seiName = portComponentInfo.getPortComponentMetaData().getServiceEndpointInterface();
return super.getServiceClass(seiName, service, msgContext);
}
finally
{
Thread.currentThread().setContextClassLoader(ccl);
}
}
protected String getServiceClassName(org.jboss.axis.Handler handler)
{
return portComponentInfo.getPortComponentMetaData().getServiceEndpointInterface();
}
protected final Object invokeMethod(MessageContext msgContext, Method method, Object obj, Object[] argValues) throws Exception
{
ClassLoader ccl = Thread.currentThread().getContextClassLoader();
try
{
Thread.currentThread().setContextClassLoader(getContextClassLoader());
return invokeServiceEndpoint(msgContext, method, obj, argValues);
}
finally
{
Thread.currentThread().setContextClassLoader(ccl);
}
}
protected abstract Object invokeServiceEndpoint(MessageContext msgContext, Method method, Object obj, Object[] argValues) throws Exception;
}