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

org.objectweb.jonas_ws.deployment.lib.WSDeploymentDescManager Maven / Gradle / Ivy

/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: [email protected]
 *
 * This library 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 any later version.
 *
 * This library 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 library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * Initial Developer : Delplanque Xavier & Sauthier Guillaume
 * --------------------------------------------------------------------------
 * $Id: WSDeploymentDescManager.java 10290 2007-04-25 16:11:47Z durieuxp $
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas_ws.deployment.lib;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.net.URLConnection;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.Vector;

import org.objectweb.jonas_ejb.deployment.api.BeanDesc;
import org.objectweb.jonas_ejb.deployment.api.DeploymentDesc;
import org.objectweb.jonas_ejb.deployment.api.SessionStatelessDesc;
import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;

import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
import org.objectweb.jonas_lib.deployment.digester.JDigester;
import org.objectweb.jonas_lib.deployment.lib.AbsDeploymentDescManager;

import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDesc;
import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDescException;
import org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager;

import org.objectweb.jonas_ws.deployment.api.JonasWsSchemas;
import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
import org.objectweb.jonas_ws.deployment.api.ServiceDesc;
import org.objectweb.jonas_ws.deployment.api.WSDeploymentDesc;
import org.objectweb.jonas_ws.deployment.api.WSDeploymentDescException;
import org.objectweb.jonas_ws.deployment.api.WsSchemas;
import org.objectweb.jonas_ws.deployment.rules.JonasWebservicesRuleSet;
import org.objectweb.jonas_ws.deployment.rules.WebservicesRuleSet;
import org.objectweb.jonas_ws.deployment.xml.JonasWebservices;
import org.objectweb.jonas_ws.deployment.xml.Webservices;

import org.objectweb.jonas.common.Log;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
 * This class provide a way for managing the WSDeploymentDesc. Note that there
 * is 1 instance of the WSDeploymentDescManager on each JOnAS server.
 * @author Guillaume Sauthier
 * @author Xavier Delplanque
 * @author Helene Joanin
 */
public class WSDeploymentDescManager extends AbsDeploymentDescManager {

    /**
     * ejb-jar.xml filename
     */
    public static final String WS_EJBJAR_FILE_NAME = "META-INF/webservices.xml";

    /**
     * jonas-ejb-jar.xml filename
     */
    public static final String JONAS_WS_EJBJAR_FILE_NAME = "META-INF/jonas-webservices.xml";

    /**
     * ejb-jar.xml filename
     */
    public static final String WS_WEBAPP_FILE_NAME = "WEB-INF/webservices.xml";

    /**
     * jonas-ejb-jar.xml filename
     */
    public static final String JONAS_WS_WEBAPP_FILE_NAME = "WEB-INF/jonas-webservices.xml";

    /**
     * Digester used to parse webservices.xml
     */
    private static JDigester wsDigester = null;

    /**
     * Digester used to parse jonas-webservices.xml
     */
    private static JDigester jwsDigester = null;

    /**
     * Rules to parse the webservices.xml
     */
    private static WebservicesRuleSet wsRuleSet = new WebservicesRuleSet();

    /**
     * Rules to parse the jonas-webservices.xml
     */
    private static JonasWebservicesRuleSet jwsRuleSet = new JonasWebservicesRuleSet();

    /**
     * Flag for parser validation
     */
    private static boolean parsingWithValidation = true;

    /**
     * The unique instance of the WSDeploymentDescManager
     */
    private static WSDeploymentDescManager unique = null;

    /**
     * is the manager instanciated ?
     */
    private static boolean isInstanciated = false;

    /**
     * Logger for the deployment desc manager.
     */
    private static Logger logger = Log.getLogger(Log.JONAS_WS_PREFIX);

    /**
     * Associates module or webservices dd URL and a WSDeploymentDesc
     */
    private HashMap urlWsddBindings;

    /**
     * Associates a given ClassLaoder (ear/ejb/web) to a list of URL containing
     * (or not) WSDD
     */
    private Map classLoader2URLs;

    /**
     * EJB Descriptor Manager
     */
    private EjbDeploymentDescManager ejbManager = null;

    /**
     * Web Descriptor Manager
     */
    private WebDeploymentDescManager webManager = null;

    /**
     * Constructor : creates a WSDeploymentDescManager object. Used only when
     * loading files in the running JOnAS instance.
     */
    private WSDeploymentDescManager() {
        urlWsddBindings = new HashMap();
        classLoader2URLs = new Hashtable();

        ejbManager = EjbDeploymentDescManager.getInstance();
        webManager = WebDeploymentDescManager.getInstance();
    }

    /**
     * Get the unique instance of the WSDeploymentDescManager.
     * @return the instance of the WSDeploymentDescManager.
     */
    public static WSDeploymentDescManager getInstance() {
        if (!isInstanciated) {
            isInstanciated = true;
            unique = new WSDeploymentDescManager();

        }
        return unique;
    }

    /**
     * Get the specified WebService deployment descriptor. Used by WsGen.
     * @param file module (ejbjar or war). It is required that file is not a
     *        directory.
     * @param jarCL the classloader where classes are stored.
     * @return the module webservices deployment descriptor if it exists, null
     *         else.
     * @throws WSDeploymentDescException when WSDeploymentDesc cannot be created
     *         with the given files.
     */
    public static WSDeploymentDesc getDeploymentDesc(String file, ClassLoader jarCL) throws WSDeploymentDescException {

        URL fileUrl = null;
        try {
            fileUrl = new File(file).toURL();
        } catch (MalformedURLException mue) {
            throw new WSDeploymentDescException(mue);
        }

        WSDeploymentDesc wsdd = loadDeploymentDesc(fileUrl, jarCL);

        // webservices.xml not present in file, no resolution needed
        if (wsdd == null) {
            return null;

        }

        // Resolve ejb-link and servlet-link elements
        List sdl = wsdd.getServiceDescs();

        for (int i = 0; i < sdl.size(); i++) {
            List pcdl = ((ServiceDesc) sdl.get(i)).getPortComponents();

            for (int j = 0; j < pcdl.size(); j++) {
                // Resolve the ejb-link and servlet-link of each port components
                PortComponentDesc pcd = (PortComponentDesc) pcdl.get(j);
                String sibLink = pcd.getSibLink();

                // a link is defined, we resolve it
                if (pcd.hasBeanImpl()) {
                    SessionStatelessDesc desc = getBeanDesc(file, sibLink, jarCL);
                    pcd.setDesc(desc);

                } else if (pcd.hasJaxRpcImpl()) {
                    WebContainerDeploymentDesc desc = getWebDesc(file, sibLink, jarCL);
                    pcd.setDesc(desc);

                }
            }
        }

        return wsdd;
    }

    /**
     * Get the specified ws deployment descriptor and put it in the cache if it
     * is not in.
     * @param url module (ejbjar or war). It can be a directory or a jar file.
     * @param jarCL classloader used to load bean classes.
     * @param earCL the parent classloader (the ear classloader). Null when not
     *        in the case of an ear application.
     * @return the module webservices deployment descriptor if it exists, null
     *         else.
     * @throws WSDeploymentDescException when WSDeploymentDesc cannot be created
     *         with the given files.
     */
    public WSDeploymentDesc getDeploymentDesc(URL url, ClassLoader jarCL, ClassLoader earCL)
            throws WSDeploymentDescException {
        return getDeploymentDesc(url, null, jarCL, earCL);
    }

    /**
     * Get the specified ws deployment descriptor and put it in the cache if it
     * is not in.
     * @param url module (ejbjar or war). It can be a directory or a jar file.
     * @param unpackedURL Unpacked URL of the module archive
     * @param jarCL classloader used to load bean classes.
     * @param earCL the parent classloader (the ear classloader). Null when not
     *        in the case of an ear application.
     * @return the module webservices deployment descriptor if it exists, null
     *         else.
     * @throws WSDeploymentDescException when WSDeploymentDesc cannot be created
     *         with the given files.
     */
    public WSDeploymentDesc getDeploymentDesc(URL url, URL unpackedURL, ClassLoader jarCL, ClassLoader earCL)
            throws WSDeploymentDescException {

        WSDeploymentDesc wsdd = null;
        File moduleFile = new File(url.getFile());

        if (moduleFile.exists()) {
            // if the module has yet been loaded
            if (!urlWsddBindings.containsKey(url)) {
                wsdd = getDeploymentDescriptor(url, unpackedURL, jarCL, earCL);
            } else { // module already loaded
                // Can be null if no webservices.xml has been found in specified
                // module
                wsdd = (WSDeploymentDesc) urlWsddBindings.get(url);
            }
        } else {
            throw new WSDeploymentDescException("'" + moduleFile.getName() + "' doesn't exists");
        }

        // Store binding
        ClassLoader keyCL;
        if (earCL != null) {
            keyCL = earCL;
        } else {
            keyCL = jarCL;
        }
        List urls = (List) classLoader2URLs.get(keyCL);
        if (urls == null) {
            urls = new Vector();
            classLoader2URLs.put(keyCL, urls);
        }
        urls.add(url);

        return wsdd;
    }

    /**
     * return the specified webservices deployment descriptor and put it in
     * cache.
     * @param url an existing module (ejbjar or war). It can be a directory or a
     *        jar file
     * @param unpackedURL Unpacked URL of the module archive
     * @param jarCL classloader used to load war or ejbjar classes.
     * @param earCL the parent classloader (the ear classloader). Null when not
     *        in the case of an ear application.
     * @return the module webservices deployment descriptor if it exists, null
     *         else.
     * @throws WSDeploymentDescException when WSDeploymentDesc cannot be created
     *         with the given files.
     */
    private WSDeploymentDesc getDeploymentDescriptor(URL url, URL unpackedURL, ClassLoader jarCL, ClassLoader earCL)
            throws WSDeploymentDescException {

        URL baseURL = url;
        if (unpackedURL != null) {
            baseURL = unpackedURL;
        }
        WSDeploymentDesc wsdd = loadDeploymentDesc(baseURL, jarCL);

        // add in cache the deployment descriptor and return it
        urlWsddBindings.put(url, wsdd);

        // No WSDeploymentDesc, return null
        if (wsdd == null) {
            return null;
        }

        // Resolve ejb-link and servlet-link elements
        List sdl = wsdd.getServiceDescs();

        for (int i = 0; i < sdl.size(); i++) {
            List pcdl = ((ServiceDesc) sdl.get(i)).getPortComponents();

            for (int j = 0; j < pcdl.size(); j++) {
                // Resolve the ejb-link and servlet-link of each port components
                PortComponentDesc pcd = (PortComponentDesc) pcdl.get(j);
                String sibLink = pcd.getSibLink();

                // a link is defined, we resolve it
                if (pcd.hasBeanImpl()) {
                    SessionStatelessDesc desc = getBeanDesc(url.getFile(), sibLink, jarCL, earCL);
                    pcd.setDesc(desc);

                } else if (pcd.hasJaxRpcImpl()) {
                    WebContainerDeploymentDesc desc = getWebDesc(url.getFile(), sibLink, jarCL, earCL);
                    pcd.setDesc(desc);

                }
            }
        }

        return wsdd;
    }

    /**
     * Load webservices.xml in the WSDeploymentDesc structure (null if
     * webservices.xml not found). Can take as parameter a directory (like an
     * unpacked jar root directory), a XML file name (path to
     * (META-INF|WEB-INF)/webservices.xml) or a packed jar.
     * @param url the url to load (can be a directory, xml, jar).
     * @param cl the classLoader to use for loading files.
     * @return WSDeploymentDesc object.
     * @throws WSDeploymentDescException when parsing error.
     */
    private static WSDeploymentDesc loadDeploymentDesc(URL url, ClassLoader cl) throws WSDeploymentDescException {

        URLClassLoader ucl = (URLClassLoader) cl;

        // get the Webservices object for this module
        InputStream isWebservices = null;

        // get the JonasWebservices object for this module
        InputStream isJonasWebservices = null;

        URL wsXml = null;
        URL jwsXml = null;

        try {

            boolean foundInEjb = false;
            for (Enumeration ejbWebservices = ucl.findResources("META-INF/webservices.xml"); ejbWebservices
                    .hasMoreElements()
                    && !foundInEjb;) {
                wsXml = (URL) ejbWebservices.nextElement();
                if (isResourceInFile(url, wsXml)) {
                    foundInEjb = true;
                }
            }

            // if DD found in Ejb
            if (foundInEjb) {
                isWebservices = openInputStream(wsXml);

                foundInEjb = false;
                // try load jonas DD
                for (Enumeration ejbJonasWebservices = ucl.findResources("META-INF/jonas-webservices.xml"); ejbJonasWebservices
                        .hasMoreElements()
                        && !foundInEjb;) {
                    jwsXml = (URL) ejbJonasWebservices.nextElement();
                    if (isResourceInFile(url, jwsXml)) {
                        foundInEjb = true;
                    }
                }
                if (foundInEjb) {
                    isJonasWebservices = openInputStream(jwsXml);

                }
            }

            boolean foundInWeb = false;
            for (Enumeration webWebservices = ucl.findResources("WEB-INF/webservices.xml"); webWebservices
                    .hasMoreElements()
                    && !foundInWeb;) {
                wsXml = (URL) webWebservices.nextElement();
                if (isResourceInFile(url, wsXml)) {
                    foundInWeb = true;
                }
            }

            // if DD found in Web
            if (foundInWeb) {
                isWebservices = openInputStream(wsXml);

                foundInWeb = false;
                // try load jonas DD
                for (Enumeration webJonasWebservices = ucl.findResources("WEB-INF/jonas-webservices.xml"); webJonasWebservices
                        .hasMoreElements()
                        && !foundInWeb;) {
                    jwsXml = (URL) webJonasWebservices.nextElement();
                    if (isResourceInFile(url, jwsXml)) {
                        foundInWeb = true;
                    }
                }
                if (foundInWeb) {
                    isJonasWebservices = openInputStream(jwsXml);
                }
            }
        } catch (IOException ioe) {
            String err = "Cannot open Streams on WebServices Deployment Descriptor for '" + url + "'";
            throw new WSDeploymentDescException(err, ioe);
        }

        // webservices.xml not found in module, return null
        if (isWebservices == null) {
            return null;
        }

        // Load and Parse files
        Webservices webservices = loadWebservices(new InputStreamReader(isWebservices), wsXml.getFile());
        JonasWebservices jonasWebservices = null;

        if (isJonasWebservices != null) {
            jonasWebservices = loadJonasWebservices(new InputStreamReader(isJonasWebservices), jwsXml.getFile());
        }

        try {
            if (isWebservices != null) {
                isWebservices.close();
            }
            if (isJonasWebservices != null) {
                isJonasWebservices.close();
            }
        } catch (IOException ioe) {
            // nothing to do, just log a warning
            String err = "Cannot close InputStreams for '" + url + "'";
            logger.log(BasicLevel.WARN, err);
        }

        // Create DeploymentDesc
        WSDeploymentDesc wsdd = new WSDeploymentDesc(cl, logger, webservices, jonasWebservices);

        return wsdd;

    }

    /**
     * @param xml URL
     * @return InputStream of the URL Content
     * @throws IOException
     */
    private static InputStream openInputStream(URL xml) throws IOException {
        URLConnection conn = xml.openConnection();
        conn.setUseCaches(false);
        conn.setDefaultUseCaches(false);
        InputStream is = conn.getInputStream();

        return is;
    }

    /**
     * Returns true if the URL resource is located in the specified file.
     * @param file file to search in
     * @param resource resource name to search
     * @return true if the URL resource is located in the specified file.
     */
    private static boolean isResourceInFile(URL file, URL resource) {

        boolean within = false;

        File f = new File(file.getFile());
        if (f.isDirectory()) {
            // test directory
            // resource need to be of the form :
            //  = /META-INF/webservices.xml for example
            if (resource.toString().startsWith(file.toString())) {
                within = true;
                if (logger.isLoggable(BasicLevel.DEBUG)) {
                    logger.log(BasicLevel.DEBUG, "Directory case. found '" + resource + "' in '" + file + "'");
                }
            }
        } else if (f.isFile()) {
            if (f.getPath().endsWith(".xml")) {
                // test XML
                // resource need to be of the form :
                //  = 
                if (file.equals(resource)) {
                    within = true;
                    if (logger.isLoggable(BasicLevel.DEBUG)) {
                        logger.log(BasicLevel.DEBUG, "XML case. found '" + resource + "' in '" + file + "'");
                    }
                }
            } else if ((f.getPath().endsWith(".war")) || (f.getPath().endsWith(".jar"))) {
                // test JarFile
                // resource need to be of the form :
                //  = jar:!/META-INF/webservices.xml for example
                int index = resource.toString().indexOf("!/");
                if (index != -1) {
                    if (resource.toString().startsWith(("jar:" + file.toString()))) {
                        within = true;
                        if (logger.isLoggable(BasicLevel.DEBUG)) {
                            logger.log(BasicLevel.DEBUG, "Archive case. found '" + resource + "' in '" + file + "'");
                        }
                    }
                }
            }
        }
        return within;
    }

    /**
     * return a 'xml' object containing webservices.xml informations
     * @param reader webservices.xml file input stream reader
     * @param fileName webservices.xml file name
     * @return a 'xml' object containing webservices.xml informations
     * @throws WSDeploymentDescException when Webservices cannot be created with
     *         the given files.
     */
    public static Webservices loadWebservices(Reader reader, String fileName) throws WSDeploymentDescException {

        Webservices ws = new Webservices();

        // Create if wsDigester is null
        if (wsDigester == null) {
            try {
                // Create and initialize the digester
                wsDigester = new JDigester(wsRuleSet, getParsingWithValidation(), true, null, new WsSchemas());
            } catch (DeploymentDescException e) {
                throw new WSDeploymentDescException(e);
            }
        }

        try {
            wsDigester.parse(reader, fileName, ws);
        } catch (DeploymentDescException e) {
            throw new WSDeploymentDescException(e);
        } finally {
            wsDigester.push(null);
        }

        return ws;
    }

    /**
     * return a 'xml' object containing jonas-webservices.xml informations
     * @param reader jonas-webservices.xml file input stream reader
     * @param fileName jonas-webservices.xml file name
     * @return a 'xml' object containing jonas-webservices.xml informations
     * @throws WSDeploymentDescException when JonasWebservices cannot be created
     *         with the given files.
     */
    public static JonasWebservices loadJonasWebservices(Reader reader, String fileName)
            throws WSDeploymentDescException {

        JonasWebservices jws = new JonasWebservices();

        // Create if wsDigester is null
        if (jwsDigester == null) {
            try {
                // Create and initialize the digester
                jwsDigester = new JDigester(jwsRuleSet, getParsingWithValidation(), true, null, new JonasWsSchemas());
            } catch (DeploymentDescException e) {
                throw new WSDeploymentDescException(e);
            }
        }

        try {
            jwsDigester.parse(reader, fileName, jws);
        } catch (DeploymentDescException e) {
            throw new WSDeploymentDescException(e);
        } finally {
            jwsDigester.push(null);
        }

        return jws;

    }

    /**
     * Get the size of the cache (number of entries in the cache). Used only for
     * debugging.
     * @return the size of the cache (number of entries in the cache).
     */
    public int getCacheSize() {
        return urlWsddBindings.size();

    }

    /**
     * Clear the cache.
     */
    public void clearCache() {
        urlWsddBindings = new HashMap();
    }

    /**
     * Remove the DD cache for the specified ClassLoader
     * @param cl the Key ClassLoader
     */
    public void removeCache(ClassLoader cl) {
        List urls = (List) classLoader2URLs.remove(cl);
        if (urls != null) {
            for (Iterator i = urls.iterator(); i.hasNext();) {
                URL url = (URL) i.next();
                urlWsddBindings.remove(url);
            }
        }
    }

    /**
     * Return a string representation of the cache. (Used only for debugging).
     * @return a string representation of the cache.
     */
    public String toString() {
        return "" + getCacheSize();

    }

    /**
     * Return a StatelessSessionDesc found in filename with the name link. Used
     * by WsGen only. (No JOnAS running).
     * @param filename the ejb-jar file to load.
     * @param link the ejb-name to retrieve.
     * @param cl the classLoader to use.
     * @return he StatelessSessionDesc associated with this port component
     * @throws WSDeploymentDescException if ejb-link not found or something went
     *         wrong when parsing ejb deployment desc.
     */
    private static SessionStatelessDesc getBeanDesc(String filename, String link, ClassLoader cl)
            throws WSDeploymentDescException {

        BeanDesc bd = null;

        try {
            // Note : Because we are in the static getDeploymentDesc
            // we have the right (accordingly to classloader hierarchie) to use
            // real EjbJar Manager
            // ---------------------------------------------------
            // Do not add import on EjbDeploymentDescManager !!!!
            DeploymentDesc dd = org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager.getDeploymentDesc(
                    filename, cl);
            bd = dd.getBeanDesc(link);

        } catch (DeploymentDescException dde) {
            throw new WSDeploymentDescException("DeploymentDescException when searching '" + link + "' in '" + filename
                    + "'", dde);
        }

        if (bd == null) {
            throw new WSDeploymentDescException("Unable to find the ejb-link '" + link + "' in '" + filename + "'");
        }

        if (!(bd instanceof SessionStatelessDesc)) {
            throw new WSDeploymentDescException("ejb-link '" + link + "' must be a Stateless Session Bean not a '"
                    + bd.getClass().getName() + "'");
        }

        return (SessionStatelessDesc) bd;

    }

    /**
     * Return a StatelessSessionDesc found in filename with the name link. Used
     * when JOnAS is running.
     * @param filename the ejb-jar file to load.
     * @param link the ejb-name to retrieve.
     * @param jarCL the loader for classes.
     * @param earCL the EAR classLoader .
     * @return the StatelessSessionDesc associated with this port component
     * @throws WSDeploymentDescException if ejb-link not found or something went
     *         wrong when parsing ejb deployment desc.
     */
    private SessionStatelessDesc getBeanDesc(String filename, String link, ClassLoader jarCL, ClassLoader earCL)
            throws WSDeploymentDescException {
        URL url;

        try {
            url = new File(filename).toURL();

        } catch (MalformedURLException mue) {
            throw new WSDeploymentDescException("Url Error with '" + filename + "'", mue);
        }

        BeanDesc bd = null;

        try {
            DeploymentDesc dd = ejbManager.getDeploymentDesc(url, jarCL, earCL);
            bd = dd.getBeanDesc(link);

        } catch (DeploymentDescException dde) {
            throw new WSDeploymentDescException("Unable to load EjbJar '" + url + "'", dde);
        }

        // Ejb Link not found
        if (bd == null) {
            throw new WSDeploymentDescException("Unable to find the ejb-link '" + link + "' in '" + filename + "'");
        }

        if (!(bd instanceof SessionStatelessDesc)) {
            throw new WSDeploymentDescException("ejb-link '" + link + "' must be a Stateless Session Bean");
        }

        return (SessionStatelessDesc) bd;

    }

    /**
     * Return the Web Deployment Desc found in filename with the name link.
     * @param filename the war file to load.
     * @param link the servlet-name to retrieve.
     * @param cl the classLoader to use.
     * @return the Web Deployment Desc associated with this port component
     * @throws WSDeploymentDescException if servlet-link not found or something
     *         went wrong when parsing web deployment desc.
     */
    private static WebContainerDeploymentDesc getWebDesc(String filename, String link, ClassLoader cl)
            throws WSDeploymentDescException {

        WebContainerDeploymentDesc wd = null;

        try {
            // Note : Because we are in the static getDeploymentDesc
            // we have the right (accordingly to classloader hierarchie) to use
            // real Web Manager
            // ---------------------------------------------------
            // Do not add import on WebDeploymentDescManager !!!!
            wd = org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager.getDeploymentDesc(filename, cl);
        } catch (WebContainerDeploymentDescException wcdde) {
            throw new WSDeploymentDescException("Error while reading/parsing " + filename, wcdde);
        }

        // link not found in this deployment desc
        if (wd.getServletClassname(link) == null) {
            throw new WSDeploymentDescException("Unable to find the servlet-link '" + link + "' in '" + filename + "'");
        }

        return wd;

    }

    /**
     * Return the Web Deployment Desc found in filename with the name link. Used
     * when JOnAS is up and running.
     * @param filename the war file to load.
     * @param link the servlet-name to retrieve.
     * @param jarCL the classLoader to us.
     * @param earCL the EAR classLoader.
     * @return the Web Deployment Desc associated with this port component
     * @throws WSDeploymentDescException if servlet-link not found or something
     *         went wrong when parsing web deployment desc.
     */
    private WebContainerDeploymentDesc getWebDesc(String filename, String link, ClassLoader jarCL, ClassLoader earCL)
            throws WSDeploymentDescException {

        URL url;

        try {
            url = new File(filename).toURL();
        } catch (MalformedURLException mue) {
            throw new WSDeploymentDescException("Url Error with '" + filename + "'", mue);
        }

        WebContainerDeploymentDesc wd = null;

        try {
            wd = webManager.getDeploymentDesc(url, jarCL, earCL);
        } catch (DeploymentDescException wcdde) {
            throw new WSDeploymentDescException("Error while reading/parsing " + filename, wcdde);
        }

        // link not found in this deployment desc
        if (wd.getServletClassname(link) == null) {
            throw new WSDeploymentDescException("Unable to find the servlet-link '" + link + "' in '" + filename + "'");
        }

        return wd;

    }

    /**
     * Controls whether the parser is reporting all validity errors.
     * @return if true, all external entities will be read.
     */
    public static boolean getParsingWithValidation() {
        return parsingWithValidation;
    }

    /**
     * Controls whether the parser is reporting all validity errors.
     * @param validation if true, all external entities will be read.
     */
    public static void setParsingWithValidation(boolean validation) {
        WSDeploymentDescManager.parsingWithValidation = validation;
    }

    /**
     * Return the port component desc from the pcLink string. pcLink format :
     * filename.[jar or war]#portComponentName in the same Ear File
     * @param callerURL the url of the module being parsed. This is needed because
     *        pcLink is relative. With the url and the pcLink, we can know where
     *        the file is locate.
     * @param portComponentLinkName the pcLink tag of an port-component-ref.
     * @param earLoader the classloader of the ear.
     * @param moduleLoader classlaoder of the current module
     * @return the pcLink portComponent.
     * @throws WSDeploymentDescException when it failed
     */
    public PortComponentDesc getPortComponentDesc(URL callerURL, String portComponentLinkName, ClassLoader moduleLoader, ClassLoader earLoader)
            throws WSDeploymentDescException {

        // Extract from the pc link
        //   - the name of the file
        //   - the name of the bean
        String moduleLink = null;
        String pcNameLink = null;
        URL moduleLinkUrl = null;
        URLClassLoader loaderForCls = null;

        // port-component-link can use directly the portComponentName without #
        // See Bug #300592
        if (!portComponentLinkName.matches(".*#.*")) {
            // no xxx#yyy
            // we just have the port link
            pcNameLink = portComponentLinkName;

            moduleLinkUrl = callerURL;
            loaderForCls = (URLClassLoader) moduleLoader;
        } else {
            // xxx#yyy

            // Check the format of the pc-link. It must contains .jar# or .war#
            if ((portComponentLinkName.toLowerCase().indexOf(".war" + AbsDeploymentDescManager.LINK_SEPARATOR) == -1) && (portComponentLinkName.toLowerCase().indexOf(".jar" + AbsDeploymentDescManager.LINK_SEPARATOR) == -1)) {
                // the pc link is not in war or jar file
                String err = "PC-link " + portComponentLinkName + " has a bad format. Correct format : filename.[jar or war]#portComponentName or just portComponentName";
                throw new WSDeploymentDescException(err);
            }
            StringTokenizer st = new StringTokenizer(portComponentLinkName, LINK_SEPARATOR);

            // We must have only two elements after this step, one for the fileName
            //   before the # and the name of the bean after the # char
            if (st.countTokens() != 2 || portComponentLinkName.startsWith(AbsDeploymentDescManager.LINK_SEPARATOR)
                || portComponentLinkName.endsWith(AbsDeploymentDescManager.LINK_SEPARATOR)) {
                String err = "PC-link " + portComponentLinkName + " has a bad format. Correct format :  filename.[jar or war]#portComponentName or just portComponentName";
                throw new WSDeploymentDescException(err);
            }

            //Get the token
            moduleLink = st.nextToken();
            pcNameLink = st.nextToken();

            // Now construct the URL from the absolute path from the url module and
            // the relative path from moduleJarLink
            try {
                moduleLinkUrl = new File(new File(callerURL.getFile()).getParent() + File.separator + moduleLink).getCanonicalFile().toURL();
            } catch (MalformedURLException mue) {
                String err = "Error when creating an url for the module filename. Error :" + mue.getMessage();
                throw new WSDeploymentDescException(err, mue);
            } catch (IOException ioe) {
                String err = "Error when creating/accessing a file. Error :" + ioe.getMessage();
                throw new WSDeploymentDescException(err, ioe);
            }

            // Check if the jar exist.
            if (!new File(moduleLinkUrl.getFile()).exists()) {
                String err = "Cannot get the deployment descriptor for '" + moduleLinkUrl.getFile() + "'. The file doesn't exist.";
                throw new WSDeploymentDescException(err);
            }

            URL[] ddURL = new URL[1];
            ddURL[0] = moduleLinkUrl;
            loaderForCls = new URLClassLoader(ddURL, earLoader);

        }

        // We've got the url
        //   Now, We can ask the Deployment Descriptor of this url
        WSDeploymentDesc wsDD = null;

        try {
            wsDD = getDeploymentDesc(moduleLinkUrl, loaderForCls, earLoader);
        } catch (DeploymentDescException e) {
            String err = "Cannot get the deployment descriptor for '" + moduleLinkUrl.getFile() + "'.";
            throw new WSDeploymentDescException(err, e);
        }
        if (wsDD == null) {
            // the module doesn't contain port components.
            String err = "Port component link " + pcNameLink + " not found in " + moduleLinkUrl.getFile();
            throw new WSDeploymentDescException(err);
        }

        //get port component desc //pcNameLink
        List sdl = wsDD.getServiceDescs();
        boolean isFound = false;
        PortComponentDesc pcd = null;
        for (int i = 0; (i < sdl.size()) && !isFound; i++) {
            if (sdl.get(i) != null) {
                pcd = ((ServiceDesc) sdl.get(i)).getPortComponent(pcNameLink);
                isFound = (pcd != null);
                // we stop when we have found the good portComponent
            }
        }
        if (!isFound) {
            // the module doesn't contain port components.
            String err = "the port component link " + pcNameLink + " doesn't exist in " + moduleLinkUrl.getFile();
            throw new WSDeploymentDescException(err);
        }

        return pcd;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy