package org.jboss.webservice;
import org.jboss.axis.MessageContext;
import org.jboss.axis.server.AxisServer;
import org.jboss.axis.utils.Admin;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.logging.Logger;
import org.jboss.metadata.WebMetaData;
import org.jboss.system.ServiceMBeanSupport;
import org.jboss.system.server.ServerConfig;
import org.jboss.webservice.deployment.MetaDataRegistry;
import org.jboss.webservice.deployment.ServiceDescription;
import org.jboss.webservice.deployment.TypeMappingDescription;
import org.jboss.webservice.deployment.WSDDGenerator;
import org.jboss.webservice.metadata.PortComponentMetaData;
import org.jboss.webservice.metadata.WebserviceDescriptionMetaData;
import org.jboss.webservice.metadata.jaxrpcmapping.JavaWsdlMapping;
import org.jboss.webservice.server.InvokerProviderJMX;
import org.jboss.webservice.server.JMXInvokerEndpoint;
import org.jboss.webservice.server.ServerEngine;
import org.w3c.dom.Document;
import javax.management.ObjectName;
import javax.wsdl.Definition;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileWriter;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.InetAddress;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class AxisService extends ServiceMBeanSupport
implements AxisServiceMBean
{
private static final Logger log = Logger.getLogger(AxisService.class);
private Map wsRegistry = new HashMap();
private ServerEngine axisServer;
private MetaDataRegistry metaDataRegistry = new MetaDataRegistry();
private String webServiceHost;
private int webServicePort;
private int webServiceSecurePort;
private boolean alwaysModifySOAPAddress;
private String invokerProviderEJB;
private String invokerProviderJSE;
protected void startService() throws Exception
{
super.startService();
}
protected void stopService() throws Exception
{
super.stopService();
}
public String getWebServiceHost()
{
return webServiceHost;
}
public int getWebServicePort()
{
return webServicePort;
}
public int getWebServiceSecurePort()
{
return webServiceSecurePort;
}
public boolean isAlwaysModifySOAPAddress()
{
return alwaysModifySOAPAddress;
}
public void setWebServiceHost(String host)
{
if ("0.0.0.0".equals(host))
{
try
{
InetAddress localHost = InetAddress.getLocalHost();
host = localHost.getHostName();
}
catch (UnknownHostException e)
{
log.error("Cannot map host: " + host, e);
}
}
this.webServiceHost = host;
}
public void setWebServicePort(int port)
{
this.webServicePort = port;
}
public void setWebServiceSecurePort(int port)
{
this.webServiceSecurePort = port;
}
public void setAlwaysModifySOAPAddress(boolean modify)
{
this.alwaysModifySOAPAddress = modify;
}
public String getInvokerProviderEJB()
{
return invokerProviderEJB;
}
public void setInvokerProviderEJB(String invokerProviderEJB)
{
this.invokerProviderEJB = invokerProviderEJB;
}
public String getInvokerProviderJSE()
{
return invokerProviderJSE;
}
public void setInvokerProviderJSE(String invokerProviderJSE)
{
this.invokerProviderJSE = invokerProviderJSE;
}
public AxisServer getAxisServer()
{
if (axisServer == null)
axisServer = new ServerEngine(EngineConfigurationFinder.getServerEngineConfiguration());
return axisServer;
}
public MetaDataRegistry getMetaDataRegistry()
{
return metaDataRegistry;
}
public PortComponentInfo getPortComponentInfo(String wsID)
{
PortComponentInfo pcInfo = (PortComponentInfo)wsRegistry.get(wsID);
if (pcInfo == null)
{
log.debug("No PortComponentInfo found for serviceID: " + wsID);
PortComponentInfo singleMatch = null;
Iterator it = wsRegistry.keySet().iterator();
while (it.hasNext())
{
String key = (String)it.next();
if (key.endsWith(wsID) && singleMatch != null)
{
log.warn("Too many possible serviceID matches: " + key);
return null;
}
if (key.endsWith(wsID) && singleMatch == null)
{
log.debug("Found possible match: " + key);
singleMatch = (PortComponentInfo)wsRegistry.get(key);
}
}
pcInfo = singleMatch;
}
return pcInfo;
}
public PortComponentInfo[] listServiceEndpointInfos()
{
PortComponentInfo[] arr = new PortComponentInfo[wsRegistry.size()];
wsRegistry.values().toArray(arr);
return arr;
}
public String listServiceEndpoints()
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
pw.println("<table>");
pw.println("<tr><th>ID</th><th>Address</th></tr>");
PortComponentInfo[] pcInfoArr = listServiceEndpointInfos();
for (int i = 0; i < pcInfoArr.length; i++)
{
PortComponentInfo pcInfo = pcInfoArr[i];
String wsID = pcInfo.getServiceID();
PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
pw.println("<tr><td>" + wsID + "</td><td>" + pcMetaData.getServiceEndpointURL() + "</td></tr>");
}
pw.println("</table>");
pw.close();
return sw.toString();
}
public void deployService(PortComponentInfo pcInfo) throws Exception
{
DeploymentInfo di = pcInfo.getDeploymentInfo();
PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
ObjectName oname = pcInfo.getObjectName();
if (server.isRegistered(oname))
throw new IllegalStateException("Service already registerd, maybe the port-component-name is not unique: " + oname);
String serviceID = pcInfo.getServiceID();
log.debug("deployService: " + serviceID);
ServiceDescription serviceDesc = getServiceDescription(pcInfo);
pcInfo.setServiceDesc(serviceDesc);
String wsdd = generateDeploymentWSDD(pcInfo);
Document genDoc = getDocumentBuilder().parse(new ByteArrayInputStream(wsdd.getBytes()));
String deploymentName = di.getCanonicalName();
String dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
File wsddFile = new File(dataDir + "/wsdl/" + deploymentName + "/" + pcMetaData.getPortComponentName() + ".wsdd");
wsddFile.getParentFile().mkdirs();
FileWriter out = new FileWriter(wsddFile);
out.write(wsdd);
out.close();
log.info("WSDD published to: " + wsddFile.getCanonicalPath());
ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();
try
{
ClassLoader deploymentCL = (di.metaData instanceof WebMetaData ? ((WebMetaData)di.metaData).getContextLoader() : di.ucl);
Thread.currentThread().setContextClassLoader(deploymentCL);
MessageContext msgContext = new MessageContext(getAxisServer());
new Admin().process(msgContext, genDoc.getDocumentElement());
registerBeanMetaData(serviceDesc);
}
finally
{
Thread.currentThread().setContextClassLoader(ctxClassLoader);
}
PortComponent pc = new PortComponent(pcInfo);
server.registerMBean(pc, oname);
wsRegistry.put(serviceID, pcInfo);
String endpointURL = pcInfo.getServiceEndpointURL();
log.info("Web Service deployed: " + endpointURL);
}
private void registerBeanMetaData(ServiceDescription serviceDesc)
{
Iterator it = serviceDesc.getTypMappings();
while (it.hasNext())
{
TypeMappingDescription typeMapping = (TypeMappingDescription)it.next();
if (typeMapping.getMetaData() != null)
metaDataRegistry.registerTypeMappingMetaData(typeMapping);
}
}
private URL findTypeMappingMetaData(DeploymentInfo di)
{
URL resourceURL = null;
String dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
File resourceFile = new File(dataDir + "/wsdl/ws4ee-deployment.xml");
if (resourceFile.exists())
{
try
{
resourceURL = resourceFile.toURL();
}
catch (MalformedURLException e)
{
log.warn("Could not get url to ws4ee-deployment.xml.", e);
}
}
if (resourceURL == null)
{
String infDir = (di.shortName.endsWith(".war") ? "WEB-INF" : "META-INF");
String resName = infDir + "/ws4ee-deployment.xml";
resourceURL = di.localCl.findResource(resName);
}
return resourceURL;
}
public void undeployService(String serviceID) throws Exception
{
PortComponentInfo pcInfo = getPortComponentInfo(serviceID);
if (pcInfo == null)
throw new IllegalStateException("Cannot find port component info for: " + serviceID);
StringBuffer buffer = new StringBuffer();
buffer.append("<undeployment");
buffer.append(" xmlns='http://xml.apache.org/axis/wsdd/'");
buffer.append(" xmlns:java='http://xml.apache.org/axis/wsdd/providers/java'");
buffer.append(" xmlns:xsi='http://www.w3.org/2000/10/XMLSchema-instance'>");
buffer.append(" <service name='" + serviceID + "'/>");
buffer.append("</undeployment>");
try
{
DocumentBuilder builder = getDocumentBuilder();
Document doc = builder.parse(new ByteArrayInputStream(buffer.toString().getBytes()));
MessageContext msgContext = new MessageContext(getAxisServer());
new Admin().process(msgContext, doc.getDocumentElement());
}
catch (Exception e)
{
log.error("Cannot unregister Axis service: " + serviceID);
}
try
{
server.unregisterMBean(pcInfo.getObjectName());
}
catch (Exception e)
{
log.error("Cannot unregister port component MBean: " + serviceID);
}
unregisterBeanMetaData(pcInfo.getServiceDescription());
wsRegistry.remove(serviceID);
log.info("WebService undeployed: " + pcInfo.getServiceEndpointURL());
}
private void unregisterBeanMetaData(ServiceDescription serviceDesc)
{
Iterator it = serviceDesc.getTypMappings();
while (it.hasNext())
{
TypeMappingDescription typeMapping = (TypeMappingDescription)it.next();
if (typeMapping.getMetaData() != null)
metaDataRegistry.unregisterTypeMappingMetaData(typeMapping.getTypeQName());
}
}
private ServiceDescription getServiceDescription(PortComponentInfo pcInfo) throws Exception
{
DeploymentInfo di = pcInfo.getDeploymentInfo();
PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
WebserviceDescriptionMetaData wsdMetaData = pcMetaData.getWebserviceDescription();
JavaWsdlMapping javaWsdlMapping = wsdMetaData.getJavaWsdlMapping();
String portName = pcMetaData.getWsdlPort().getLocalPart();
Definition wsdlDefinition = wsdMetaData.getWsdlDefinition();
URL ws4eeMetaData = findTypeMappingMetaData(di);
ServiceDescription serviceDesc = new ServiceDescription(wsdlDefinition, javaWsdlMapping, ws4eeMetaData, portName);
return serviceDesc;
}
private String generateDeploymentWSDD(PortComponentInfo pcInfo) throws Exception
{
StringWriter strWriter = new StringWriter(1024);
PrintWriter out = new PrintWriter(strWriter);
DeploymentInfo di = pcInfo.getDeploymentInfo();
PortComponentMetaData pcMetaData = pcInfo.getPortComponentMetaData();
ServiceDescription serviceDesc = pcInfo.getServiceDescription();
String serviceID = pcInfo.getServiceID();
WSDDGenerator wsddGenerator = new WSDDGenerator(serviceDesc);
wsddGenerator.appendHeader(out);
wsddGenerator.appendServiceElement(out, serviceID, "Handler");
String wsID = pcInfo.getServiceID();
out.println(" <parameter name='" + PortComponentMetaData.PARAMETER_WEBSERVICE_ID + "' value='" + wsID + "' />");
String ejbLink = pcMetaData.getEjbLink();
String servletLink = pcMetaData.getServletLink();
if (ejbLink != null)
{
out.println(" <parameter name='handlerClass' value='" + invokerProviderEJB + "' />");
}
else if (servletLink != null)
{
if (servletLink.equals(JMXInvokerEndpoint.class.getName()))
out.println(" <parameter name='handlerClass' value='" + InvokerProviderJMX.class.getName() + "' />");
else
out.println(" <parameter name='handlerClass' value='" + invokerProviderJSE + "' />");
}
else
{
throw new IllegalArgumentException("Cannot find <ejb-link> nor <servlet-link> in webservices.xml");
}
out.println();
wsddGenerator.appendOperations(out);
ClassLoader ctxClassLoader = Thread.currentThread().getContextClassLoader();
try
{
ClassLoader deploymentCL = (di.metaData instanceof WebMetaData ? ((WebMetaData)di.metaData).getContextLoader() : di.ucl);
Thread.currentThread().setContextClassLoader(deploymentCL);
wsddGenerator.appendTypeMappings(out);
}
finally
{
Thread.currentThread().setContextClassLoader(ctxClassLoader);
}
wsddGenerator.appendFooter(out);
out.close();
return strWriter.toString();
}
private DocumentBuilder getDocumentBuilder()
throws ParserConfigurationException
{
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
factory.setNamespaceAware(true);
DocumentBuilder builder = factory.newDocumentBuilder();
return builder;
}
}