package org.jboss.webservice;
import org.dom4j.Document;
import org.dom4j.DocumentFactory;
import org.dom4j.Element;
import org.dom4j.io.OutputFormat;
import org.dom4j.io.XMLWriter;
import org.jboss.deployment.DeploymentException;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.logging.Logger;
import org.jboss.metadata.ApplicationMetaData;
import org.jboss.metadata.BeanMetaData;
import org.jboss.metadata.EjbPortComponentMetaData;
import org.jboss.system.server.ServerConfig;
import org.jboss.system.server.ServerConfigLocator;
import org.jboss.webservice.metadata.PortComponentMetaData;
import org.jboss.webservice.metadata.WebserviceDescriptionMetaData;
import org.jboss.webservice.metadata.WebservicesMetaData;
import org.jboss.webservice.server.ServiceEndpointServletEJB;
import javax.management.ObjectName;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
public class ServiceDeployerEJB extends ServiceDeployer
implements ServiceDeployerEJBMBean
{
private final Logger log = Logger.getLogger(ServiceDeployer.class);
public static final String EJB_ENDPOINT_WEBAPP_URL = "ejb-endpoint-webapp-url";
private ObjectName ejbDeployer;
private ObjectName mainDeployer;
public void setEJBDeployer(ObjectName deployerName)
{
this.ejbDeployer = deployerName;
}
public void setMainDeployer(ObjectName deployerName)
{
this.mainDeployer = deployerName;
}
protected void startService() throws Exception
{
super.startService();
registerNotificationListener(ejbDeployer);
}
protected void stopService() throws Exception
{
unregisterNotificationListener(ejbDeployer);
super.stopService();
}
protected void deployWebservices(DeploymentInfo di, WebservicesMetaData webservices)
throws DeploymentException
{
super.deployWebservices(di, webservices);
Document webDoc = createWebXML(di, webservices);
Document jbossDoc = createJBossWebXML(di);
ServerConfig config = ServerConfigLocator.locate();
File tmpWar = null;
try
{
File tmpdir = new File(config.getServerTempDir().getCanonicalPath() + "/deploy");
String deploymentName = di.getCanonicalName().replace('/', '-') + "-ws";
tmpWar = File.createTempFile(deploymentName, ".war", tmpdir);
tmpWar.delete();
File webInf = new File(tmpWar, "WEB-INF");
webInf.mkdirs();
File webXml = new File(webInf, "web.xml");
FileWriter fw = new FileWriter(webXml);
OutputFormat fmt = OutputFormat.createPrettyPrint();
XMLWriter writer = new XMLWriter(fw, fmt);
writer.write(webDoc);
writer.close();
fw.close();
File jbossWebXml = new File(webInf, "jboss-web.xml");
fw = new FileWriter(jbossWebXml);
writer = new XMLWriter(fw, fmt);
writer.write(jbossDoc);
writer.close();
fw.close();
}
catch (IOException e)
{
throw new DeploymentException("Failed to create webservice.war", e);
}
try
{
URL warURL = tmpWar.toURL();
Object[] args = {warURL};
String[] sig = {"java.net.URL"};
server.invoke(mainDeployer, "deploy", args, sig);
di.context.put(EJB_ENDPOINT_WEBAPP_URL, warURL);
}
catch (Exception e)
{
throw new DeploymentException("Failed to deploy webservice.war", e);
}
}
private Document createWebXML(DeploymentInfo di, WebservicesMetaData webservices)
throws DeploymentException
{
ApplicationMetaData applMetaData = (ApplicationMetaData)di.metaData;
DocumentFactory factory = DocumentFactory.getInstance();
Document webDoc = factory.createDocument();
Element webApp = webDoc.addElement("web-app");
WebserviceDescriptionMetaData[] wsDescriptions = webservices.getWebserviceDescriptions();
for (int i = 0; i < wsDescriptions.length; i++)
{
WebserviceDescriptionMetaData wsDescription = wsDescriptions[i];
PortComponentMetaData[] portComponents = wsDescription.getPortComponents();
for (int j = 0; j < portComponents.length; j++)
{
PortComponentMetaData pc = portComponents[j];
String ejbLink = pc.getEjbLink();
if (ejbLink == null)
throw new DeploymentException("Cannot find ejb-link in port-component: " + pc.getPortComponentName());
Element servlet = webApp.addElement("servlet");
Element servletName = servlet.addElement("servlet-name");
servletName.addText(ejbLink);
Element servletClass = servlet.addElement("servlet-class");
servletClass.addText(ServiceEndpointServletEJB.class.getName());
}
}
ArrayList urlPatters = new ArrayList();
for (int i = 0; i < wsDescriptions.length; i++)
{
WebserviceDescriptionMetaData wsDescription = wsDescriptions[i];
PortComponentMetaData[] portComponents = wsDescription.getPortComponents();
for (int j = 0; j < portComponents.length; j++)
{
PortComponentMetaData pc = portComponents[j];
String ejbLink = pc.getEjbLink();
Element servletMapping = webApp.addElement("servlet-mapping");
Element servletName = servletMapping.addElement("servlet-name");
servletName.addText(ejbLink);
Element urlPatternElement = servletMapping.addElement("url-pattern");
String urlPattern = "/*";
BeanMetaData ejbMetaData = (BeanMetaData)applMetaData.getBeanByEjbName(ejbLink);
EjbPortComponentMetaData pcMetaData = ejbMetaData.getPortComponent();
if (pcMetaData != null)
{
urlPattern = pcMetaData.getURLPattern();
}
if (urlPatters.contains(urlPattern))
throw new IllegalArgumentException("Cannot use the same url-pattern with different endpoints, " +
"check your <port-component-uri> in jboss.xml");
urlPatternElement.addText(urlPattern);
urlPatters.add(urlPattern);
}
}
String authMethod = null;
for (int i = 0; i < wsDescriptions.length; i++)
{
WebserviceDescriptionMetaData wdmd = wsDescriptions[i];
PortComponentMetaData[] ports = wdmd.getPortComponents();
for (int j = 0; j < ports.length; j++)
{
PortComponentMetaData port = ports[j];
String portName = port.getPortComponentName();
String ejbLink = port.getEjbLink();
BeanMetaData smd = (BeanMetaData)applMetaData.getBeanByEjbName(ejbLink);
EjbPortComponentMetaData portMetaData = smd.getPortComponent();
if (portMetaData != null)
{
Element securityConstraint = webApp.addElement("security-constraint");
Element wrc = securityConstraint.addElement("web-resource-collection");
Element wrName = wrc.addElement("web-resource-name");
wrName.addText(portName);
Element pattern = wrc.addElement("url-pattern");
String uri = portMetaData.getURLPattern();
pattern.addText(uri);
if (portMetaData.getAuthMethod() != null)
{
if (authMethod == null)
authMethod = portMetaData.getAuthMethod();
Element authConstraint = securityConstraint.addElement("auth-constraint");
Element roleName = authConstraint.addElement("role-name");
roleName.addText("*");
}
if (portMetaData.getTransportGuarantee() != null)
{
Element userData = securityConstraint.addElement("user-data-constraint");
Element transport = userData.addElement("transport-guarantee");
transport.addText(portMetaData.getTransportGuarantee());
}
}
}
}
if (authMethod != null)
{
Element loginConfig = webApp.addElement("login-config");
Element method = loginConfig.addElement("auth-method");
method.addText(authMethod);
Element realm = loginConfig.addElement("realm-name");
realm.addText("EJBServiceEndpointServlet Realm");
}
for (int i = 0; i < wsDescriptions.length; i++)
{
WebserviceDescriptionMetaData wsDescription = wsDescriptions[i];
PortComponentMetaData[] portComponents = wsDescription.getPortComponents();
for (int j = 0; j < portComponents.length; j++)
{
PortComponentMetaData pcMetaData = portComponents[j];
String ejbLink = pcMetaData.getEjbLink();
PortComponentInfo pcInfo = new PortComponentInfo(di, pcMetaData);
modifyServletConfig(webDoc, ejbLink, pcInfo);
}
}
return webDoc;
}
private Document createJBossWebXML(DeploymentInfo di)
{
ApplicationMetaData amd = (ApplicationMetaData)di.metaData;
DocumentFactory factory = DocumentFactory.getInstance();
Document jbossDoc = factory.createDocument();
Element jbossWeb = jbossDoc.addElement("jboss-web");
String securityDomain = amd.getSecurityDomain();
if (securityDomain != null)
{
Element secDomain = jbossWeb.addElement("security-domain");
secDomain.addText(securityDomain);
}
String contextRoot = (String)di.context.get(WEBSERVICE_CONTEXT_ROOT);
Element root = jbossWeb.addElement("context-root");
root.addText(contextRoot);
return jbossDoc;
}
protected void undeployWebservices(DeploymentInfo di, WebservicesMetaData webservices)
{
try
{
URL warURL = (URL)di.context.get(EJB_ENDPOINT_WEBAPP_URL);
if (warURL != null)
{
Object[] args = {warURL};
String[] sig = {"java.net.URL"};
server.invoke(mainDeployer, "undeploy", args, sig);
}
}
catch (Exception e)
{
log.error("Failed to undeploy webservice.war", e);
}
super.undeployWebservices(di, webservices);
}
protected URL getWebservicesDescriptor(DeploymentInfo di)
{
return di.localCl.findResource("META-INF/webservices.xml");
}
protected String getServiceEndpointServletName()
{
return ServiceEndpointServletEJB.class.getName();
}
}