package org.jboss.webservice;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.io.DOMReader;
import org.dom4j.io.SAXReader;
import org.jboss.deployment.DeploymentException;
import org.jboss.deployment.DeploymentInfo;
import org.jboss.logging.Logger;
import org.jboss.system.server.ServerConfig;
import org.jboss.webservice.metadata.WebserviceDescriptionMetaData;
import org.jboss.webservice.metadata.WebservicesMetaData;
import org.jboss.util.xml.JBossEntityResolver;
import javax.wsdl.Definition;
import javax.wsdl.Import;
import javax.wsdl.factory.WSDLFactory;
import javax.wsdl.xml.WSDLWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Iterator;
import java.util.List;
public class WSDLFilePublisher
{
private static final Logger log = Logger.getLogger(WSDLFilePublisher.class);
private DeploymentInfo di;
private String expLocation;
public WSDLFilePublisher(DeploymentInfo di)
{
this.di = di;
String archiveName = di.shortName;
if (archiveName.endsWith(".jar"))
expLocation = "META-INF/wsdl/";
if (archiveName.endsWith(".war"))
expLocation = "WEB-INF/wsdl/";
if (expLocation == null)
throw new IllegalStateException("Can only publish wsdl from WAR or JAR deployment");
}
public void publishWsdlFile(WebservicesMetaData webservices) throws DeploymentException
{
String deploymentName = di.getCanonicalName();
WebserviceDescriptionMetaData[] wsdArray = webservices.getWebserviceDescriptions();
for (int i = 0; i < wsdArray.length; i++)
{
WebserviceDescriptionMetaData wsd = wsdArray[i];
File targetFile = getPublishLocation(deploymentName, wsd);
targetFile.getParentFile().mkdirs();
try
{
Definition wsdlDefinition = wsd.getWsdlDefinition();
WSDLFactory wsdlFactory = WSDLFactory.newInstance();
WSDLWriter wsdlWriter = wsdlFactory.newWSDLWriter();
FileWriter fw = new FileWriter(targetFile);
wsdlWriter.writeWSDL(wsdlDefinition, fw);
fw.close();
wsd.setWsdlPublishLocation(targetFile.getCanonicalPath());
log.info("WSDL published to: " + targetFile.toURL());
publishWsdlImports(targetFile.toURL(), wsdlDefinition);
Document document = new DOMReader().read(wsdlWriter.getDocument(wsdlDefinition));
publishSchemaImports(targetFile.toURL(), document.getRootElement());
}
catch (Exception e)
{
throw new DeploymentException("Cannot publish wsdl to: " + targetFile, e);
}
}
}
private void publishWsdlImports(URL parentURL, Definition parentDefinition) throws Exception
{
String baseURI = parentURL.toExternalForm();
Iterator it = parentDefinition.getImports().values().iterator();
while (it.hasNext())
{
List list = (List)it.next();
for (int j = 0; j < list.size(); j++)
{
Import wsdlImport = (Import)list.get(j);
String locationURI = wsdlImport.getLocationURI();
Definition subdef = wsdlImport.getDefinition();
if (locationURI.startsWith("http://") == false)
{
URL wsdlURL = new URL(baseURI.substring(0, baseURI.lastIndexOf("/") + 1) + locationURI);
File targetFile = new File(wsdlURL.getPath());
targetFile.getParentFile().mkdirs();
WSDLFactory wsdlFactory = WSDLFactory.newInstance();
WSDLWriter wsdlWriter = wsdlFactory.newWSDLWriter();
FileWriter fw = new FileWriter(targetFile);
wsdlWriter.writeWSDL(subdef, fw);
fw.close();
log.debug("WSDL import published to: " + wsdlURL);
publishWsdlImports(wsdlURL, subdef);
Document document = new DOMReader().read(wsdlWriter.getDocument(subdef));
publishSchemaImports(wsdlURL, document.getRootElement());
}
}
}
}
private void publishSchemaImports(URL parentURL, Element element) throws Exception
{
String baseURI = parentURL.toExternalForm();
Iterator it = element.elementIterator();
while (it.hasNext())
{
Element childElement = (Element)it.next();
if ("import".equals(childElement.getQName().getName()) || "include".equals(childElement.getQName().getName()))
{
if (childElement.attribute("schemaLocation") != null)
{
String locationURI = childElement.attribute("schemaLocation").getText();
if (locationURI.startsWith("http://") == false)
{
URL xsdURL = new URL(baseURI.substring(0, baseURI.lastIndexOf("/") + 1) + locationURI);
File targetFile = new File(xsdURL.getPath());
targetFile.getParentFile().mkdirs();
String deploymentName = di.getCanonicalName();
int index = baseURI.indexOf(deploymentName);
String resourcePath = baseURI.substring(index + deploymentName.length());
resourcePath = resourcePath.substring(0, resourcePath.lastIndexOf("/"));
if (resourcePath.length() > 0)
resourcePath = resourcePath + "/";
resourcePath = expLocation + resourcePath + locationURI;
InputStream is = di.localCl.getResourceAsStream(resourcePath);
if (is == null)
throw new IllegalArgumentException("Cannot find schema import in deployment: " + resourcePath);
FileOutputStream fos = new FileOutputStream(targetFile);
copyStream(fos, is);
fos.close();
is.close();
log.debug("XMLSchema import published to: " + xsdURL);
SAXReader saxReader = new SAXReader();
saxReader.setEntityResolver(new JBossEntityResolver());
Document subdoc = saxReader.read(xsdURL);
publishSchemaImports(xsdURL, subdoc.getRootElement());
}
}
}
else
{
publishSchemaImports(parentURL, childElement);
}
}
}
public void unpublishWsdlFile()
{
String deploymentDir = (di.parent != null ? di.parent.shortName : di.shortName);
String dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
File serviceDir = new File(dataDir + "/wsdl/" + deploymentDir);
deleteWsdlPublishDirectory(serviceDir);
}
private void deleteWsdlPublishDirectory(File dir)
{
String[] files = dir.list();
for (int i = 0; files != null && i < files.length; i++)
{
String fileName = files[i];
File file = new File(dir + "/" + fileName);
if (file.isDirectory())
{
deleteWsdlPublishDirectory(file);
}
else
{
if (file.delete() == false)
log.warn("Cannot delete published wsdl document: " + file);
}
}
dir.delete();
}
private File getPublishLocation(String archiveName, WebserviceDescriptionMetaData wsd)
{
boolean predefinedLocation = wsd.getWsdlPublishLocation() != null && wsd.getWsdlPublishLocation().startsWith("file:");
File publishLocation = null;
if (predefinedLocation == false)
{
String dataDir = System.getProperty(ServerConfig.SERVER_DATA_DIR);
publishLocation = new File(dataDir + "/wsdl/" + archiveName);
}
else
{
try
{
publishLocation = new File(new URL(wsd.getWsdlPublishLocation()).getPath());
}
catch (MalformedURLException e)
{
throw new IllegalArgumentException("Invalid publish location: " + e.getMessage());
}
}
String wsdlFile = wsd.getWsdlFile();
if (wsdlFile.startsWith("/"))
wsdlFile = wsdlFile.substring(1);
if (wsdlFile.startsWith(expLocation) == false)
throw new IllegalArgumentException("The wsdl file should be located in: " + expLocation);
wsdlFile = wsdlFile.substring(expLocation.length());
File wsdlLocation = new File(publishLocation + "/" + wsdlFile);
return wsdlLocation;
}
private void copyStream(OutputStream outputStream, InputStream inputStream) throws IOException
{
byte[] bytes = new byte[4096];
int read = inputStream.read(bytes, 0, 4096);
while (read > 0)
{
outputStream.write(bytes, 0, read);
read = inputStream.read(bytes, 0, 4096);
}
}
}