/* * JBoss, Home of Professional Open Source. * Copyright 2015, Red Hat Middleware LLC, and individual contributors * as indicated by the @author tags. See the copyright.txt file in the * distribution for a full listing of individual contributors. * * This is free software; you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as * published by the Free Software Foundation; either version 2.1 of * the License, or (at your option) any later version. * * This software is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this software; if not, write to the Free * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA, or see the FSF site: http://www.fsf.org. */ package org.jboss.wsf.stack.cxf.deployment; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.UnsupportedEncodingException; import java.net.URL; import java.net.URLDecoder; import java.net.URLEncoder; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; import java.util.StringTokenizer; import javax.wsdl.Definition; import javax.wsdl.WSDLException; import javax.wsdl.xml.WSDLWriter; import javax.xml.namespace.QName; import javax.xml.stream.XMLStreamException; import javax.xml.stream.XMLStreamWriter; import org.apache.cxf.Bus; import org.apache.cxf.helpers.FileUtils; import org.apache.cxf.service.model.ServiceInfo; import org.apache.cxf.staxutils.StaxUtils; import org.apache.cxf.wsdl.WSDLManager; import org.apache.cxf.wsdl11.ServiceWSDLBuilder; import org.jboss.ws.common.utils.AbstractWSDLFilePublisher; import org.jboss.wsf.spi.deployment.ArchiveDeployment; import org.jboss.wsf.stack.cxf.Loggers; import org.jboss.wsf.stack.cxf.Messages; import org.w3c.dom.Document; import org.jboss.logging.Logger; /** * A WSDL file publisher for CXF based stack * * @author alessio.soldano@jboss.com * @since 25-Mar-2010 * */ public class WSDLFilePublisher extends AbstractWSDLFilePublisher { private static final String[] wsdlLocationPrefixes = {"vfsfile:", "file:", "jar:", "vfszip:"}; public WSDLFilePublisher(ArchiveDeployment dep) { super(dep); } /** Publish the deployed wsdl file to the data directory */ public void publishWsdlFiles(QName serviceName, String wsdlLocation, Bus bus, List<ServiceInfo> serviceInfos) throws IOException { String deploymentName = dep.getCanonicalName(); File wsdlFile = getPublishLocation(serviceName.getLocalPart(), deploymentName, wsdlLocation); if (wsdlFile == null) return; createParentDir(wsdlFile); try { // Write the wsdl def to file ServiceWSDLBuilder builder = new ServiceWSDLBuilder(bus, serviceInfos); Definition def = builder.build(); Document doc = getWsdlDocument(bus, def); writeDocument(doc, wsdlFile); URL wsdlPublishURL = new URL(URLDecoder.decode(wsdlFile.toURI().toURL().toExternalForm(), "UTF-8")); Loggers.DEPLOYMENT_LOGGER.wsdlFilePublished(wsdlPublishURL); // Process the wsdl imports if (def != null) { List<String> published = new LinkedList<String>(); String expLocation = getExpLocation(wsdlLocation); publishWsdlImports(wsdlPublishURL, def, published, expLocation); // Publish XMLSchema imports publishSchemaImports(wsdlPublishURL, doc.getDocumentElement(), published, expLocation); dep.addAttachment(WSDLFilePublisher.class, this); } else { throw Messages.MESSAGES.wsdl20NotSupported(); } } catch (RuntimeException rte) { throw rte; } catch (Exception e) { throw Messages.MESSAGES.cannotPublishWSDLTo(serviceName, wsdlFile, e); } } public void unpublishWsdlFiles() { try { File parentDir = new File(serverConfig.getServerDataDir().getCanonicalPath() + "/wsdl"); ArchiveDeployment deployment = dep; while (deployment.getParent() != null) { deployment = deployment.getParent(); } String deploymentName = deployment.getCanonicalName(); if (deploymentName.startsWith("http://")) { deploymentName = deploymentName.replace("http://", "http-"); } File targetDir = new File(parentDir, deploymentName); FileUtils.removeDir(targetDir); } catch (IOException e) { Loggers.DEPLOYMENT_LOGGER.couldNotCreateWsdlDataPath(); } } private static Document getWsdlDocument(Bus bus, Definition def) throws WSDLException { WSDLWriter wsdlWriter = bus.getExtension(WSDLManager.class).getWSDLFactory().newWSDLWriter(); def.setExtensionRegistry(bus.getExtension(WSDLManager.class).getExtensionRegistry()); return wsdlWriter.getDocument(def); } private static void writeDocument(Document doc, File file) throws IOException, XMLStreamException { String enc = null; try { enc = doc.getXmlEncoding(); } catch (Exception ex) { //ignore - not dom level 3 Logger.getLogger(WSDLFilePublisher.class).trace(ex); } if (enc == null) { enc = "utf-8"; } FileOutputStream fos = new FileOutputStream(new File(file.toURI())); try { XMLStreamWriter writer = StaxUtils.createXMLStreamWriter(fos, enc); StaxUtils.writeNode(doc, writer, true); writer.flush(); } finally { fos.close(); } } /** * Get the file publish location */ private File getPublishLocation(String serviceName, String archiveName, String wsdlLocation) throws IOException { if (wsdlLocation == null && serviceName == null) { Loggers.DEPLOYMENT_LOGGER.cannotGetWsdlPublishLocation(); return null; } //JBWS-2829: windows issue if (archiveName.startsWith("http://")) { archiveName = archiveName.replace("http://", "http-"); } File locationFile = new File(serverConfig.getServerDataDir().getCanonicalPath() + "/wsdl/" + archiveName); if (wsdlLocation != null && wsdlLocation.indexOf(expLocation) >= 0) { wsdlLocation = wsdlLocation.substring(wsdlLocation.indexOf(expLocation) + expLocation.length()); return new File(locationFile + "/" + wsdlLocation); } else if (wsdlLocation != null && !wsdlLocation.startsWith("vfs:")) { for (String wsdlLocationPrefix : wsdlLocationPrefixes) { if (wsdlLocation.startsWith(wsdlLocationPrefix)) { return new File(locationFile, encodeLocation(wsdlLocation.substring(wsdlLocationPrefix.length(), wsdlLocation.lastIndexOf("/") + 1))); } } return new File(locationFile, encodeLocation(wsdlLocation)); } else { return new File(locationFile + "/" + serviceName + ".wsdl"); } } private String encodeLocation(String location) throws UnsupportedEncodingException { StringBuilder sb = new StringBuilder(); StringTokenizer st = new StringTokenizer(location, "/", false); List<String> l = new ArrayList<String>(); while (st.hasMoreTokens()) { l.add(URLEncoder.encode(st.nextToken(), "UTF-8")); } final int size = l.size(); for (int i = 0; i < size; i++) { sb.append(l.get(i)); if (i < size - 1) { sb.append("/"); } } return sb.toString(); } private String getExpLocation(String wsdlLocation) { if (wsdlLocation == null || wsdlLocation.indexOf(expLocation) >= 0) { return expLocation; } else { //JBWS-3540 return wsdlLocation.startsWith("vfs:") && wsdlLocation.contains("/") ? wsdlLocation.substring(0, wsdlLocation.lastIndexOf("/") + 1) : ""; } } }