All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.glassfish.webservices.WebServicesDeployer Maven / Gradle / Ivy

The newest version!
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2006-2013 Oracle and/or its affiliates. All rights reserved.
 *
 * The contents of this file are subject to the terms of either the GNU
 * General Public License Version 2 only ("GPL") or the Common Development
 * and Distribution License("CDDL") (collectively, the "License").  You
 * may not use this file except in compliance with the License.  You can
 * obtain a copy of the License at
 * https://glassfish.dev.java.net/public/CDDL+GPL_1_1.html
 * or packager/legal/LICENSE.txt.  See the License for the specific
 * language governing permissions and limitations under the License.
 *
 * When distributing the software, include this License Header Notice in each
 * file and include the License file at packager/legal/LICENSE.txt.
 *
 * GPL Classpath Exception:
 * Oracle designates this particular file as subject to the "Classpath"
 * exception as provided by Oracle in the GPL Version 2 section of the License
 * file that accompanied this code.
 *
 * Modifications:
 * If applicable, add the following below the License Header, with the fields
 * enclosed by brackets [] replaced by your own identifying information:
 * "Portions Copyright [year] [name of copyright owner]"
 *
 * Contributor(s):
 * If you wish your version of this file to be governed by only the CDDL or
 * only the GPL Version 2, indicate your decision by adding "[Contributor]
 * elects to include this software in this distribution under the [CDDL or GPL
 * Version 2] license."  If you don't indicate a single choice of license, a
 * recipient has the option to distribute your version of this file under
 * either the CDDL, the GPL Version 2 or to extend the choice of license to
 * its licensees as provided above.  However, if you add GPL Version 2 code
 * and therefore, elected the GPL Version 2 license, then the option applies
 * only if the new code is made subject to such option by the copyright
 * holder.
 */
// Portions Copyright [2018-2022] [Payara Foundation and/or its affiliates]
package org.glassfish.webservices;

import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deploy.shared.FileArchive;
import com.sun.enterprise.deployment.*;
import com.sun.enterprise.deployment.archivist.Archivist;
import com.sun.enterprise.deployment.util.DOLUtils;
import com.sun.enterprise.deployment.web.AppListenerDescriptor;
import com.sun.enterprise.util.io.FileUtils;
import com.sun.tools.ws.util.xml.XmlUtil;
import org.glassfish.api.container.RequestDispatcher;
import org.glassfish.api.deployment.DeploymentContext;
import org.glassfish.api.deployment.MetaData;
import org.glassfish.api.deployment.UndeployCommandParameters;
import org.glassfish.api.deployment.archive.ArchiveType;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.glassfish.api.deployment.archive.WritableArchive;
import org.glassfish.deployment.common.DeploymentException;
import org.glassfish.internal.api.JAXRPCCodeGenFacade;
import org.glassfish.javaee.core.deployment.JavaEEDeployer;
import org.glassfish.loader.util.ASClassLoaderUtil;
import org.glassfish.web.deployment.descriptor.AppListenerDescriptorImpl;
import org.glassfish.web.deployment.util.WebServerInfo;
import org.glassfish.webservices.deployment.WebServicesDeploymentMBean;
import org.jvnet.hk2.annotations.Service;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;

import jakarta.inject.Inject;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.net.*;
import java.nio.channels.FileChannel;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.text.MessageFormat;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * Webservices module deployer. This is loaded from WebservicesContainer
 *
 * @author Bhakti Mehta
 * @author Rama Pulavarthi
 */
@Service
public class WebServicesDeployer extends JavaEEDeployer {

    private static final Logger logger = LogUtils.getLogger();

    public static final WebServiceDeploymentNotifier deploymentNotifier = new WebServiceDeploymentNotifierImpl();

    private ResourceBundle resourceBundle = logger.getResourceBundle();

    @Inject
    private RequestDispatcher dispatcher;

    @Inject
    private ArchiveFactory archiveFactory;

    public static WebServiceDeploymentNotifier getDeploymentNotifier() {
        return deploymentNotifier;
    }

    /**
     * Constructor
     */
    public WebServicesDeployer() {
    }

    /**
     * Prepares the application bits for running in the application server. For certain cases, this is
     * exploding the jar file to a format the ContractProvider instance is expecting, generating non
     * portable artifacts and other application specific tasks. Failure to prepare should throw an
     * exception which will cause the overall deployment to fail.
     *
     * @param dc deployment context
     * @return true if the prepare phase was successful
     *
     */
    @Override
    public boolean prepare(DeploymentContext dc) {
        try {

            Application app = dc.getModuleMetaData(Application.class);
            if (app == null) {
                // hopefully the DOL gave a good message of the failure...
                logger.log(Level.SEVERE, LogUtils.FAILED_LOADING_DD);
                return false;
            }
            BundleDescriptor bundle = DOLUtils.getCurrentBundleForContext(dc);
            if (bundle == null) {
                logger.log(Level.SEVERE, LogUtils.FAILED_LOADING_DD);
                return false;
            }

            String moduleCP = getModuleClassPath(dc);
            final List moduleCPUrls = ASClassLoaderUtil.getURLsFromClasspath(moduleCP, File.pathSeparator, null);
            final ClassLoader oldCl = Thread.currentThread().getContextClassLoader();
            URLClassLoader newCl = AccessController.doPrivileged(
                (PrivilegedAction) () -> new URLClassLoader(ASClassLoaderUtil.convertURLListToArray(moduleCPUrls), oldCl)
            );

            Thread.currentThread().setContextClassLoader(newCl);
            WebServicesDescriptor wsDesc = bundle.getWebServices();
            for (WebService ws : wsDesc.getWebServices()) {
                if ((new WsUtil()).isJAXWSbasedService(ws)) {
                    setupJaxWSServiceForDeployment(dc, ws);
                } else {
                    JAXRPCCodeGenFacade facade = habitat.getService(JAXRPCCodeGenFacade.class);
                    if (facade != null) {
                        facade.run(habitat, dc, moduleCP, false);
                    } else {
                        throw new DeploymentException(resourceBundle.getString(LogUtils.JAXRPC_CODEGEN_FAIL));
                    }
                }
            }
            doWebServicesDeployment(app, dc);
            Thread.currentThread().setContextClassLoader(oldCl);
            WebServicesContainer container = habitat.getService(WebServicesContainer.class);
            WebServicesDeploymentMBean bean = container.getDeploymentBean();
            WebServiceDeploymentNotifier notifier = getDeploymentNotifier();
            bean.deploy(wsDesc, notifier);
            return true;
        } catch (Exception ex) {
            RuntimeException re = new RuntimeException(ex.getMessage());
            re.initCause(ex);
            throw re;
        }
    }

    protected void cleanArtifacts(DeploymentContext deploymentContext) throws DeploymentException {

    }

    protected void setupJaxWSServiceForDeployment(DeploymentContext dc, WebService ws) throws DeploymentException {

        BundleDescriptor bundle = dc.getModuleMetaData(BundleDescriptor.class);

        // for modules this is domains//j2ee-modules/
        // for apps this is domains//j2ee-apps// (in case of embedded wars)
        // or domains//j2ee-apps// (in case of embedded jars)
        File moduleDir = dc.getSourceDir();

        // For modules this is domains//generated/xml
        // Check with Hong about j2ee-modules
        File wsdlDir = dc.getScratchDir("xml");
        mkDirs(wsdlDir);

        // For modules this is domains//generated/xml
        // Check with Hong about j2ee-modules
        File stubsDir = dc.getScratchDir("ejb");
        mkDirs(stubsDir);

        if (!DOLUtils.warType().equals(bundle.getModuleType()) && !DOLUtils.ejbType().equals(bundle.getModuleType())) {
            // unknown module type with @WebService, just ignore...
            return;
        }

        wsdlDir = new File(wsdlDir, bundle.getWsdlDir().replaceAll("/", "\\" + File.separator));

        // Check if catalog file is present, if so get mapped WSDLs
        String wsdlFileUri;
        File wsdlFile;
        try {
            checkCatalog(bundle, ws, moduleDir);
        } catch (DeploymentException e) {
            logger.log(Level.SEVERE, LogUtils.ERROR_RESOLVING_CATALOG);
        }
        if (ws.hasWsdlFile()) {
            // If wsdl file is an http URL, download that WSDL and all embedded relative wsdls, schemas
            if (ws.getWsdlFileUri().startsWith("http")) {
                try {
                    wsdlFileUri = downloadWsdlsAndSchemas(new URL(ws.getWsdlFileUri()), wsdlDir);
                } catch (Exception e) {
                    throw new DeploymentException(e.toString(), e);
                }
                wsdlFile = new File(wsdlDir, wsdlFileUri);
            } else {
                wsdlFileUri = ws.getWsdlFileUri();
                File wsdlFileAbs = new File(wsdlFileUri);
                wsdlFile = wsdlFileAbs.isAbsolute() ? wsdlFileAbs : new File(moduleDir, wsdlFileUri);
            }

            if (!wsdlFile.exists()) {
                String errorMessage = format(logger.getResourceBundle().getString(LogUtils.WSDL_NOT_FOUND), ws.getWsdlFileUri(),
                        bundle.getModuleDescriptor().getArchiveUri());
                logger.log(Level.SEVERE, errorMessage);
                throw new DeploymentException(errorMessage);
            }
        }
    }

    /**
     * Loads the meta date associated with the application.
     *
     * @parameters type type of metadata that this deployer has declared providing.
     */
    @Override
    public Object loadMetaData(Class type, DeploymentContext dc) {
        // Moved the doWebServicesDeployment back to prepare after discussing with
        // Jerome
        // see this bug https://glassfish.dev.java.net/issues/show_bug.cgi?id=8080
        return true;
    }

    /**
     * Returns the meta data assocated with this Deployer
     *
     * @return the meta data for this Deployer
     */
    @Override
    public MetaData getMetaData() {
        return new MetaData(false, null, new Class[] { Application.class });
    }

    /**
     * This method downloads the main wsdl/schema and its imports in to the directory specified and
     * returns the name of downloaded root document.
     *
     * @param httpUrl
     * @param wsdlDir
     * @return Returns the name of the root file downloaded with the invocation.
     * @throws Exception
     */
    private String downloadWsdlsAndSchemas(URL httpUrl, File wsdlDir) throws Exception {
        // First make required directories and download this wsdl file
        mkDirs(wsdlDir);
        String fileName = httpUrl.toString().substring(httpUrl.toString().lastIndexOf("/") + 1);
        File toFile = new File(wsdlDir.getAbsolutePath() + File.separator + fileName);
        downloadFile(httpUrl, toFile);

        // Get a list of wsdl and schema relative imports in this wsdl
        HashSet wsdlRelativeImports = new HashSet();
        HashSet schemaRelativeImports = new HashSet();
        HashSet wsdlIncludes = new HashSet();
        HashSet schemaIncludes = new HashSet();
        parseRelativeImports(httpUrl, wsdlRelativeImports, wsdlIncludes, schemaRelativeImports, schemaIncludes);
        wsdlRelativeImports.addAll(wsdlIncludes);
        schemaRelativeImports.addAll(schemaIncludes);

        // Download all schema relative imports
        String urlWithoutFileName = httpUrl.toString().substring(0, httpUrl.toString().lastIndexOf("/"));
        for (Import next : schemaRelativeImports) {
            String location = next.getLocation();
            location = location.replaceAll("/", "\\" + File.separator);
            if (location.lastIndexOf(File.separator) != -1) {
                File newDir = new File(
                        wsdlDir.getAbsolutePath() + File.separator + location.substring(0, location.lastIndexOf(File.separator)));
                mkDirs(newDir);
            }
            downloadFile(new URL(urlWithoutFileName + "/" + next.getLocation()),
                    new File(wsdlDir.getAbsolutePath() + File.separator + location));
        }

        // Download all wsdl relative imports
        for (Import next : wsdlRelativeImports) {
            String newWsdlLocation = next.getLocation();
            newWsdlLocation = newWsdlLocation.replaceAll("/", "\\" + File.separator);
            File newWsdlDir;
            if (newWsdlLocation.lastIndexOf(File.separator) != -1) {
                newWsdlDir = new File(wsdlDir.getAbsolutePath() + File.separator
                        + newWsdlLocation.substring(0, newWsdlLocation.lastIndexOf(File.separator)));
            } else {
                newWsdlDir = wsdlDir;
            }
            downloadWsdlsAndSchemas(new URL(urlWithoutFileName + "/" + next.getLocation()), newWsdlDir);
        }
        return fileName;
    }

    // If catalog file is present, get the mapped WSDL for given WSDL and replace the value in
    // the given WebService object
    private void checkCatalog(BundleDescriptor bundle, WebService ws, File moduleDir) throws DeploymentException {
        // If no catalog file is present, return
        File catalogFile = new File(moduleDir, bundle.getDeploymentDescriptorDir() + File.separator + "jax-ws-catalog.xml");
        if (!catalogFile.exists()) {
            return;
        }
        resolveCatalog(catalogFile, ws.getWsdlFileUri(), ws);
    }

    public URL resolveCatalog(File catalogFile, String wsdlFile, WebService ws) throws DeploymentException {

        try {

            URL retVal = null;
            // Get an entity resolver
            org.xml.sax.EntityResolver resolver = XmlUtil.createEntityResolver(catalogFile.toURL());
            org.xml.sax.InputSource source = resolver.resolveEntity(null, wsdlFile);
            if (source != null) {
                String mappedEntry = source.getSystemId();
                // For entries with relative paths, Entity resolver always
                // return file:// webServices = new HashSet();

        // when there are multiple sub modules in ear, we only want to handle the ones local to this
        // deployment context

        // First get the web services associated with module bundle descriptor.
        WebServicesDescriptor wsDesc = dc.getModuleMetaData(WebServicesDescriptor.class);
        if (wsDesc != null && wsDesc.getWebServices().size() > 0) {
            if (logger.isLoggable(Level.FINE)) {
                logger.log(Level.FINE, LogUtils.WS_LOCAL,
                        new Object[] { wsDesc.getWebServices().size(), getWebServiceDescriptors(app).size() });
            }
            webServices.addAll(wsDesc.getWebServices());
        }
        // Now get the web services associated with extension descriptors,ex: EJB WS in war.
        WebBundleDescriptor webBundleDesc = dc.getModuleMetaData(WebBundleDescriptor.class);
        if (webBundleDesc != null) {
            Collection ejbBundleDescriptors = webBundleDesc.getExtensionsDescriptors(EjbBundleDescriptor.class);
            for (EjbBundleDescriptor ejbBundleDescriptor : ejbBundleDescriptors) {
                Collection wsInExtnDesc = ejbBundleDescriptor.getWebServices().getWebServices();
                webServices.addAll(wsInExtnDesc);
                if (logger.isLoggable(Level.FINE)) {
                    logger.log(Level.FINE, LogUtils.WS_VIA_EXT, wsInExtnDesc);
                }
            }
        }

        // swap the deployment descriptors context-root with the one
        // provided in the deployment request.
        // do not do for ejb in war case
        if (webBundleDesc != null && webBundleDesc.getExtensionsDescriptors(EjbBundleDescriptor.class).size() == 0) {
            if (dc.getAppProps().get("context-root") != null && app.isVirtual()) {

                String contextRoot = ((String) dc.getAppProps().get("context-root"));
                webBundleDesc.setContextRoot(contextRoot);
            }
        }

        // Generate final wsdls for all web services and store them in
        // the application repository directory.
        for (WebService next : webServices) {
            WsUtil wsUtil = new WsUtil();

            // For JAXWS services, we rely on JAXWS RI to do WSL gen and publishing
            // For JAXRPC we do it here in 109
            // however it is needed for file publishing for jaxws
            if (wsUtil.isJAXWSbasedService(next) && (!next.hasFilePublishing())) {
                for (WebServiceEndpoint wsep : next.getEndpoints()) {
                    URL finalWsdlURL = wsep.composeFinalWsdlUrl(wsUtil.getWebServerInfoForDAS().getWebServerRootURL(wsep.isSecure()));
                    Set serviceRefs = new HashSet();
                    if (webBundleDesc != null) {
                        serviceRefs = webBundleDesc.getServiceReferenceDescriptors();
                    } else {
                        EjbBundleDescriptor ejbBundleDesc = dc.getModuleMetaData(EjbBundleDescriptor.class);
                        if (ejbBundleDesc != null) {
                            serviceRefs = ejbBundleDesc.getEjbServiceReferenceDescriptors();
                        } else {
                            logger.log(Level.SEVERE, LogUtils.UNSUPPORTED_MODULE_TYPE,
                                    DOLUtils.getCurrentBundleForContext(dc).getModuleType());
                        }
                    }
                    // if there's service-ref to this service update its
                    // wsdl-file value to point to the just exposed URL
                    for (ServiceReferenceDescriptor srd : serviceRefs) {
                        if (srd.getServiceName().equals(wsep.getServiceName())
                                && srd.getServiceNamespaceUri().equals(wsep.getWsdlService().getNamespaceURI())) {
                            srd.setWsdlFileUri(finalWsdlURL.toExternalForm() + "?WSDL");
                        }
                    }
                }
            } else {

                // Even if deployer specified a wsdl file
                // publish location, server can't assume it can access that
                // file system. Plus, it's cleaner to depend on a file stored
                // within the application repository rather than one directly
                // exposed to the deployer. Name of final wsdl is derived based
                // on the location of its associated module. This prevents us
                // from having write the module to disk in order to store the
                // modified runtime info.
                URL url = next.getWsdlFileUrl();
                if (url == null) {
                    File f = new File(dc.getSourceDir(), next.getWsdlFileUri());
                    url = f.toURL();
                }

                // Create the generated WSDL in the generated directory; for that create the directories first
                File genXmlDir = dc.getScratchDir("xml");

                String wsdlFileDir = next.getWsdlFileUri().substring(0, next.getWsdlFileUri().lastIndexOf('/'));
                mkDirs(new File(genXmlDir, wsdlFileDir));
                File genWsdlFile = new File(genXmlDir, next.getWsdlFileUri());
                wsUtil.generateFinalWsdl(url, next, wsUtil.getWebServerInfoForDAS(), genWsdlFile);
            }
        }
        // Swap the servlet class name with a real servlet processing the SOAP requests.
        if (webBundleDesc != null) {
            doWebServiceDeployment(webBundleDesc);
        }
    }

    /**
     * Prepares the servlet based web services specified in web.xml for deployment.
     *
     * Swap the application written servlet implementation class for one provided by the container. The
     * original class is stored as runtime information since it will be used as the servant at dispatch
     * time.
     */
    private void doWebServiceDeployment(WebBundleDescriptor webBunDesc) throws DeploymentException, MalformedURLException {

        /**
         * Combining code from com.sun.enterprise.deployment.backend.WebServiceDeployer in v2
         */

        Collection endpoints = webBunDesc.getWebServices().getEndpoints();
        ClassLoader cl = webBunDesc.getClassLoader();
        WsUtil wsutil = new WsUtil();

        for (WebServiceEndpoint nextEndpoint : endpoints) {
            WebComponentDescriptor webComp = nextEndpoint.getWebComponentImpl();

            if (!nextEndpoint.hasServletImplClass()) {
                throw new DeploymentException(
                        format(resourceBundle.getString(LogUtils.DEPLOYMENT_BACKEND_CANNOT_FIND_SERVLET), nextEndpoint.getEndpointName()));
            }

            if (nextEndpoint.hasEndpointAddressUri()) {
                webComp.getUrlPatternsSet().clear();
                webComp.addUrlPattern(nextEndpoint.getEndpointAddressUri());
            }

            if (!nextEndpoint.getWebService().hasFilePublishing()) {
                String publishingUri = nextEndpoint.getPublishingUri();
                String publishingUrlPattern = (publishingUri.charAt(0) == '/') ? publishingUri : "/" + publishingUri + "/*";
                webComp.addUrlPattern(publishingUrlPattern);

            }

            String containerServlet = "org.glassfish.webservices.JAXWSServlet";
            addWSServletContextListener(webBunDesc);
            webComp.setWebComponentImplementation(containerServlet);

            /**
             * Now trying to figure the address from com.sun.enterprise.webservice.WsUtil.java
             */
            // Get a URL for the root of the webserver, where the host portion
            // is a canonical host name. Since this will be used to compose the
            // endpoint address that is written into WSDL, it's better to use
            // hostname as opposed to IP address.
            // The protocol and port will be based on whether the endpoint
            // has a transport guarantee of INTEGRAL or CONFIDENTIAL.
            // If yes, https will be used. Otherwise, http will be used.
            WebServerInfo wsi = new WsUtil().getWebServerInfoForDAS();
            URL rootURL = wsi.getWebServerRootURL(nextEndpoint.isSecure());
            String contextRoot = webBunDesc.getContextRoot();
            URL actualAddress = nextEndpoint.composeEndpointAddress(rootURL, contextRoot);
            if (wsi.getHttpVS() != null && wsi.getHttpVS().getPort() != 0) {
                logger.log(Level.INFO, LogUtils.ENDPOINT_REGISTRATION, new Object[] { nextEndpoint.getEndpointName(), actualAddress });
            }
        }
    }

    private void addWSServletContextListener(WebBundleDescriptor webBunDesc) {
        for (AppListenerDescriptor appListner : webBunDesc.getAppListenerDescriptors()) {
            if (appListner.getListener().equals(WSServletContextListener.class.getName())) {
                // already registered
                return;
            }
        }
        webBunDesc.addAppListenerDescriptor(new AppListenerDescriptorImpl(WSServletContextListener.class.getName()));
    }

    private String format(String key, String... values) {
        return MessageFormat.format(key, (Object[]) values);
    }

    public static void moveFile(String sourceFile, String destFile) throws IOException {
        FileUtils.copy(sourceFile, destFile);
        FileUtils.deleteFile(new File(sourceFile));
    }

    @Override
    public void unload(WebServicesApplication container, DeploymentContext context) {
        final WebServiceDeploymentNotifier notifier = getDeploymentNotifier();
        deletePublishedFiles(container.getPublishedFiles());
        Application app = container.getApplication();
        if (app == null) {
            // load uses context.getModuleMetaData(Application.class) to get the Application. If there's a
            // deployment
            // failure then "container" may not have initialized the application and container.getApplication()
            // returns
            // null and we get NPE. So use context.getModuleMetaData(Application.class) always.
            app = context.getModuleMetaData(Application.class);
        }
        if (app != null) {
            for (WebService svc : getWebServiceDescriptors(app)) {
                for (WebServiceEndpoint endpoint : svc.getEndpoints()) {
                    if (notifier != null) {
                        notifier.notifyUndeployed(endpoint);
                    }
                }
            }
        }
    }

    @Override
    public void clean(DeploymentContext dc) {
        super.clean(dc);

        WebServicesContainer container = habitat.getService(WebServicesContainer.class);
        WebServicesDeploymentMBean bean = container.getDeploymentBean();
        UndeployCommandParameters params = dc.getCommandParameters(UndeployCommandParameters.class);
        if (params != null) {
            bean.undeploy(params.name);
        }
    }

    @Override
    public WebServicesApplication load(WebServicesContainer container, DeploymentContext context) {
        Set publishedFiles = null;
        Application app = context.getModuleMetaData(Application.class);
        try {
            publishedFiles = populateWsdlFilesForPublish(context, getWebServiceDescriptors(app));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }

        return new WebServicesApplication(context, dispatcher, publishedFiles);
    }

    /**
     * Populate the wsdl files entries to download (if any) (Only for webservices which use file
     * publishing).
     *
     * TODO File publishing currently works only for wsdls packaged in the application for jax-ws. Need
     * to publish the dynamically generated wsdls as well. Lazy creation of WSEndpoint objects prohibits
     * it now.
     */
    private Set populateWsdlFilesForPublish(DeploymentContext dc, Set webservices) throws IOException {

        Set publishedFiles = new HashSet();
        for (WebService webService : webservices) {
            if (!webService.hasFilePublishing()) {
                continue;
            }

            copyExtraFilesToGeneratedFolder(dc);
            BundleDescriptor bundle = webService.getBundleDescriptor();

            ArchiveType moduleType = bundle.getModuleType();
            // only EAR, WAR and EJB archives could contain wsdl files for publish
            if (moduleType == null || !(moduleType.equals(DOLUtils.earType()) || moduleType.equals(DOLUtils.warType())
                    || moduleType.equals(DOLUtils.ejbType()))) {
                return publishedFiles;
            }

            File sourceDir = dc.getScratchDir("xml");

            File parent;
            try {
                URI clientPublishURI = webService.getClientPublishUrl().toURI();
                if (!clientPublishURI.isOpaque()) {
                    parent = new File(clientPublishURI);
                } else {
                    parent = new File(webService.getClientPublishUrl().getPath());
                }
            } catch (URISyntaxException e) {
                logger.log(Level.WARNING, LogUtils.EXCEPTION_THROWN, e);
                parent = new File(webService.getClientPublishUrl().getPath());
            }

            // Collect the names of all entries in or below the
            // dedicated wsdl directory.
            FileArchive archive = new FileArchive();
            archive.open(sourceDir.toURI());

            Enumeration entries = archive.entries(bundle.getWsdlDir());

            while (entries.hasMoreElements()) {
                String name = (String) entries.nextElement();
                String wsdlName = stripWsdlDir(name, bundle);
                File clientwsdl = new File(parent, wsdlName);
                File fulluriFile = new File(sourceDir, name);
                if (!fulluriFile.isDirectory()) {
                    publishFile(fulluriFile, clientwsdl);
                    publishedFiles.add(clientwsdl.getAbsolutePath());
                }
            }

        }
        return publishedFiles;
    }

    private void publishFile(File file, File publishLocation) throws IOException {
        copyFile(file, publishLocation);
    }

    private void deletePublishedFiles(Set publishedFiles) {
        if (publishedFiles != null) {
            for (String path : publishedFiles) {
                File f = new File(path);
                if (f.exists()) {
                    FileUtils.deleteFile(f);
                }
            }
        }
    }

    /**
     * This is to be used for file publishing only. In case of wsdlImports and wsdlIncludes we need to
     * copy the nested wsdls from applications folder to the generated/xml folder
     *
     */
    private void copyExtraFilesToGeneratedFolder(DeploymentContext context) throws IOException {
        Archivist archivist = habitat.getService(Archivist.class);

        ReadableArchive archive = archiveFactory.openArchive(context.getSourceDir());

        WritableArchive archive2 = archiveFactory.createArchive(context.getScratchDir("xml"));

        // copy the additional webservice elements etc
        archivist.copyExtraElements(archive, archive2);

    }

    /**
     * Return the entry name without "WEB-INF/wsdl" or "META-INF/wsdl".
     */
    private String stripWsdlDir(String entry, BundleDescriptor bundle) {
        String wsdlDir = bundle.getWsdlDir();
        return entry.substring(wsdlDir.length() + 1);
    }

    /**
     * Return a set of all com.sun.enterprise.deployment.WebService descriptors in the application.
     */
    private Set getWebServiceDescriptors(Application app) {
        Set webServiceDescriptors = new HashSet();
        for (BundleDescriptor next : app.getBundleDescriptors()) {
            WebServicesDescriptor webServicesDesc = next.getWebServices();
            webServiceDescriptors.addAll(webServicesDesc.getWebServices());
        }
        return webServiceDescriptors;
    }

    private static void mkDirs(File f) {
        if (!f.mkdirs() && logger.isLoggable(Level.FINE)) {
            logger.log(Level.FINE, LogUtils.DIR_EXISTS, f);
        }
    }

    private static void mkFile(File f) throws IOException {
        if (!f.createNewFile() && logger.isLoggable(Level.FINE)) {
            logger.log(Level.FINE, LogUtils.FILE_EXISTS, f);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy