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

org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager Maven / Gradle / Ivy

/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * 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(s): Ludovic BERT & Florent BENOIT
 * --------------------------------------------------------------------------
 * $Id: WebDeploymentDescManager.java 10513 2007-06-04 13:38:32Z sauthieg $
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas_web.deployment.lib;

import java.io.File;
import java.io.FileInputStream;
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.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;

import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;

import org.objectweb.jonas_lib.deployment.api.DeploymentDescException;
import org.objectweb.jonas_lib.deployment.api.EjbLocalRefDesc;
import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc;
import org.objectweb.jonas_lib.deployment.digester.JDigester;
import org.objectweb.jonas_lib.deployment.lib.AbsDeploymentDescManager;
import org.objectweb.jonas_lib.deployment.xml.JonasMessageDestination;

import org.objectweb.jonas_web.deployment.api.JonasWebAppDTDs;
import org.objectweb.jonas_web.deployment.api.JonasWebAppSchemas;
import org.objectweb.jonas_web.deployment.api.WebAppDTDs;
import org.objectweb.jonas_web.deployment.api.WebAppSchemas;
import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDesc;
import org.objectweb.jonas_web.deployment.api.WebContainerDeploymentDescException;
import org.objectweb.jonas_web.deployment.rules.JonasWebAppRuleSet;
import org.objectweb.jonas_web.deployment.rules.WebAppRuleSet;
import org.objectweb.jonas_web.deployment.xml.JonasWebApp;
import org.objectweb.jonas_web.deployment.xml.WebApp;

import org.objectweb.jonas_ws.deployment.api.PortComponentDesc;
import org.objectweb.jonas_ws.deployment.api.PortComponentRefDesc;
import org.objectweb.jonas_ws.deployment.api.WSDeploymentDescException;
import org.objectweb.jonas_ws.deployment.api.IServiceRefDesc;
import org.objectweb.jonas_ws.deployment.lib.WSDeploymentDescManager;

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 WebContainerDeploymentDesc. Note
 * that there is an intance of the WebDeploymentDescManager on each JOnAS
 * server.
 * @author Ludovic Bert
 * @author Florent Benoit
 */
public class WebDeploymentDescManager extends AbsDeploymentDescManager {

    /**
     * The path to the web.xml file.
     */
    public static final String WEB_FILE_NAME = "WEB-INF/web.xml";

    /**
     * The path to the jonas-web.xml file.
     */
    public static final String JONAS_WEB_FILE_NAME = "WEB-INF/jonas-web.xml";

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

    /**
     * Digester use to parse web.xml
     */
    private static JDigester webAppDigester = null;

    /**
     * Digester use to parse jonas-web.xml
     */
    private static JDigester jonasWebAppDigester = null;

    /**
     * Rules to parse the web.xml
     */
    private static WebAppRuleSet webAppRuleSet = new WebAppRuleSet();

    /**
     * Rules to parse the jonas-web.xml
     */
    private static JonasWebAppRuleSet jonasWebAppRuleSet = new JonasWebAppRuleSet();

    /**
     * The unique instance of the WebDeploymentDescManager.
     */
    private static WebDeploymentDescManager unique;

    /**
     * Reference on the EjbDeploymentDescManager.
     */
    private EjbDeploymentDescManager ejbDDManager = null;

    /**
     * Reference on the WSDeploymentDescManager.
     */
    private WSDeploymentDescManager wsDDManager = null;

    /**
     * logger
     */
    private static Logger logger = Log.getLogger(Log.JONAS_WEB_PREFIX);

    /** The cache used when static getDeploymentDesc are called (WsGen case) */
    private static Hashtable staticCache = new Hashtable();

    /**
     * Contructs a unique new WebDeploymentDescManager.
     */
    private WebDeploymentDescManager() {
        ejbDDManager = EjbDeploymentDescManager.getInstance();
        earCLAltDDBindings = new Hashtable();
    }

    /**
     * Associate a ear classLoader to an hashtable which contains Association
     * between Urls of wars and their optional alt-dd
     */
    private Hashtable earCLAltDDBindings = null;

    /**
     * Get an instance of the WebDeploymentDescManager.
     * @return the instance of the WebDeploymentDescManager.
     */
    public static WebDeploymentDescManager getInstance() {
        if (unique == null) {
            unique = new WebDeploymentDescManager();
        }
        return unique;
    }

    /**
     * Get the specified web deployment descriptor.
     * @param url the url where to load xml deployment descriptors.
     * @param loaderForCls classloader used to load web classes.
     * @param earLoader the ear classloader.
     * @return WebContainerDeploymentDesc the web deployment descriptor.
     * @throws DeploymentDescException when WebContainerDeploymentDesc cannot be
     *         created with the given files.
     */
    public WebContainerDeploymentDesc getDeploymentDesc(URL url, ClassLoader loaderForCls, ClassLoader earLoader)
            throws DeploymentDescException {

        // load an instance of the WebService Manager
        if (wsDDManager == null) {
            wsDDManager = WSDeploymentDescManager.getInstance();
        }

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

        //url used to load an alternate DDesc in the EAR case
        URL altDDUrl = null;

        //check if it's an Ear case or not
        Hashtable urlAltddBindings = null;
        if (earLoader != null) {
            //Mapping ?
            urlAltddBindings = (Hashtable) earCLAltDDBindings.get(earLoader);
            if (urlAltddBindings == null) {
                //If there is no mapping, the setAltDD function was badly
                // called
                String err = "Cannot find if there is alt-dd for '" + url.getFile()
                        + "', the setAltDD function was badly called";
                throw new WebContainerDeploymentDescException(err);
            }
            //Now we can get the optional alt-dd url file
            altDDUrl = (URL) urlAltddBindings.get(url);
        }

        // ... and get the instance of the WebContainerDeploymentDesc.
        //If there is an alternate url for the web.xml, call the method with
        // this param.
        WebContainerDeploymentDesc webDD = null;
        try {
            if (altDDUrl != null) {
                webDD = getInstance(url.getFile(), loaderForCls, altDDUrl.getFile());
            } else {
                webDD = getInstance(url.getFile(), loaderForCls);
            }
        } catch (DeploymentDescException dde) {
            throw new WebContainerDeploymentDescException(dde);
        }

        // Resolve the ejb-link for ejb-ref
        EjbRefDesc[] ejbRef = webDD.getEjbRefDesc();
        for (int i = 0; i < ejbRef.length; i++) {
            if (ejbRef[i].getJndiName() == null) {
                String ejbLink = ejbRef[i].getEjbLink();
                String ejbRefType = ejbRef[i].getEjbRefType();
                if (ejbLink != null) {
                    if (earLoader == null) {
                        throw new WebContainerDeploymentDescException(
                                "Ejb-link is not authorized from a single war. The war must be in an ear.");
                    } else {
                        String jndiName = getJndiName(url, ejbLink, earLoader, ejbRefType, true);
                        ejbRef[i].setJndiName(jndiName);
                    }
                }
            }
        }

        // Resolve the ejb-link for ejb-local-ref
        EjbLocalRefDesc[] ejbLocalRef = webDD.getEjbLocalRefDesc();
        for (int i = 0; i < ejbLocalRef.length; i++) {
            String ejblink = ejbLocalRef[i].getEjbLink();
            if (earLoader == null) {
                throw new WebContainerDeploymentDescException(
                        "Ejb-link is not authorized from a single war. The war must be in an ear.");
            }
            String ejbRefType = ejbLocalRef[i].getEjbRefType();
            String ejbName = getJndiName(url, ejblink, earLoader, ejbRefType, false);
            ejbLocalRef[i].setJndiLocalName(ejbName);
        }

        // Resolve the port-component-link for service-ref
        IServiceRefDesc[] serviceRef = webDD.getServiceRefDesc();

        for (int i = 0; i < serviceRef.length; i++) {

            List pcRefs = serviceRef[i].getPortComponentRefs();
            for (int j = 0; j < pcRefs.size(); j++) {
                // for each service portComponents : resolve links
                PortComponentRefDesc pcr = (PortComponentRefDesc) pcRefs.get(j);
                String pclink = pcr.getPortComponentLink();
                if (pclink != null) {
                    // a pc link is defined, we resolve it
                    PortComponentDesc pcDesc = getPCDesc(url, pclink, loaderForCls, earLoader);
                    pcr.setPortComponentDesc(pcDesc);
                }
            }
        }

        // Resolve the message-destination-link for message-destination-ref
        MessageDestinationRefDesc[] mdRef = webDD.getMessageDestinationRefDesc();
        for (int i = 0; i < mdRef.length; i++) {
            if (mdRef[i].getJndiName() == null) {
                String jndiName = mdRef[i].getJndiName();
                String mdLink = mdRef[i].getMessageDestinationLink();
                String mdType = mdRef[i].getMessageDestinationType();
                String mdUsage = mdRef[i].getMessageDestinationUsage();
                if (mdLink != null) {
                    if (earLoader == null) {
                        throw new WebContainerDeploymentDescException(
                                "Message-destination-link is not authorized from a single client jar. The client jar must be in an ear.");
                    } else {
                        String mdName = getMDJndiName(url, mdLink, mdType, mdUsage, earLoader);
                        mdRef[i].setJndiName(jndiName);
                    }
                }
            }
        }

        return webDD;
    }

    /**
     * Return the port component desc from the pcLink string. pcLink format :
     * filename.[jar or war]#portComponentName in the same Ear File
     * @param warURL the url of the war being parsed. This is needed because
     *        pcLink is relative. With the url and the pcLink, we can know where
     *        the file is locate.
     * @param pcLink 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
     */
    private PortComponentDesc getPCDesc(URL warURL, String pcLink, ClassLoader moduleLoader, ClassLoader earLoader)
            throws WSDeploymentDescException {

        // now ask WS Manager for port-component-desc
        return wsDDManager.getPortComponentDesc(warURL, pcLink, moduleLoader, earLoader);
    }

    /**
     * Return the JNDI name from the ejbLink string. ejbLink format :
     * filename.jar#beanName in the same Ear File beanName in the same ejb-jar
     * file.
     * @param warURL the url of the war being parsed. This is needed because
     *        ejbLink is relative. With the url and the ejbLink, we can know
     *        where the file is locate.
     * @param ejbLink the ejbLink tag of an ejb-ref.
     * @param earLoader the classloader of the ear.
     * @param ejbType the type of the referenced ejb in the ejb-ref tag.
     * @param isEjbRef true if the jndi name to resolve is an ejb-ref
     * @return the JNDI name if found, null otherwise
     * @throws DeploymentDescException when it failed
     */
    private String getJndiName(URL warURL, String ejbLink, ClassLoader earLoader, String ejbType, boolean isEjbRef)
            throws DeploymentDescException {

        // Now ask EJB deployment Desc manager :
        return ejbDDManager.getJndiName(warURL, ejbLink, earLoader, ejbType, null, isEjbRef);
    }

    /**
     * Return the JNDI name from the mdLink string. mdLink format :
     * filename.jar#mdName in the same Ear File
     * @param warURL the url of the jar being parsed. This is needed because
     *        mdLink is relative. With the url and the mdLink, we can know where
     *        the file is locate.
     * @param mdLink the mdLink tag of a message-destination-ref
     * @param mdType the type of the referenced mdb in the
     *        message-destination-ref tag.
     * @param mdUsage the usage of the referenced mdb in the
     *        message-destination-ref tag.
     * @param earLoader the classloader of the ear.
     * @return the JNDI name if found, null otherwise
     * @throws WebContainerDeploymentDescException when it failed
     */
    private String getMDJndiName(URL warURL, String mdLink, String mdType, String mdUsage, ClassLoader earLoader)
            throws WebContainerDeploymentDescException {

        // Extract from the mdb link
        //   - the name of the file
        //   - the name of the destination
        String ejbJarLink = null;
        String destNameLink = null;
        org.objectweb.jonas_ejb.deployment.api.DeploymentDesc dd = null;

        // Check the format of the ejb-link. It must contains .jar#
        if (mdLink.toLowerCase().indexOf(".jar#") == -1) {
            String err = "Message-destination-link " + mdLink
                    + " has a bad format. Correct format :  filename.jar#messageDestinationName";
            throw new WebContainerDeploymentDescException(err);
        }

        StringTokenizer st = new StringTokenizer(mdLink, LINK_SEPARATOR);

        // We must have only two elements after this step, one for the fileName
        // before the # and the name of the message-destination after the # char
        if (st.countTokens() != 2 || mdLink.startsWith(LINK_SEPARATOR) || mdLink.endsWith(LINK_SEPARATOR)) {

            String err = "Message-destination-link " + mdLink
                    + " has a bad format. Correct format :  filename.jar#messageDestinationName.";
            throw new WebContainerDeploymentDescException(err);
        }

        //Get the token
        ejbJarLink = st.nextToken();
        destNameLink = st.nextToken();

        //Check if ejbJarLink is a jar or not
        if (!ejbJarLink.endsWith(".jar")) {
            String err = "Ejbjar filename " + ejbJarLink + " from the message-destination-link " + mdLink
                    + " has a bad format. Correct format :  filename.jar";
            throw new WebContainerDeploymentDescException(err);
        }

        // Now construct the URL from the absolute path from the url warURL and
        // the relative path from ejbJarLink
        URL ejbJarLinkUrl = null;
        try {
            ejbJarLinkUrl = new File(new File(warURL.getFile()).getParent() + File.separator + ejbJarLink)
                    .getCanonicalFile().toURL();
        } catch (MalformedURLException mue) {
            String err = "Error when creating an url for the ejb jar filename. Error :" + mue.getMessage();
            throw new WebContainerDeploymentDescException(err);
        } catch (IOException ioe) {
            String err = "Error when creating/accessing a file. Error :" + ioe.getMessage();
            throw new WebContainerDeploymentDescException(err);
        }

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

        // We've got the url
        //   Now, We can ask the Deployment Descriptor of this url
        URL[] ddURL = new URL[1];
        ddURL[0] = ejbJarLinkUrl;
        URLClassLoader loaderForClsEjb = new URLClassLoader(ddURL, earLoader);
        try {
            dd = ejbDDManager.getDeploymentDesc(ejbJarLinkUrl, loaderForClsEjb, earLoader);
        } catch (DeploymentDescException e) {
            String err = "Cannot get the deployment descriptor for '" + ejbJarLinkUrl.getFile() + "'.";
            throw new WebContainerDeploymentDescException(err, e);
        }

        JonasMessageDestination md = dd.getJonasMessageDestination(mdLink);

        if (md == null) {
            String err = "No message-destination-link was found for '" + mdLink + "' in the file " + warURL.getFile()
                    + " specified.";
            throw new WebContainerDeploymentDescException(err);
        }

        //Check if the type & usage of the message-destination-ref is correct.
        //For now checkTypeUsage(warURL, mdType, mdUsage, dd);

        return md.getJndiName();
    }

    /**
     * Make a cleanup of the cache of deployment descriptor. This method must be
     * invoked after the ear deployment by the EAR service.
     * @param earClassLoader the ClassLoader of the ear application to remove
     *        from the cache.
     */
    public void removeCache(ClassLoader earClassLoader) {
        //Remove the altdd mapping
        earCLAltDDBindings.remove(earClassLoader);

        //Then remove the cache of the ejb dd manager
        ejbDDManager.removeCache(earClassLoader);
    }

    /**
     * Set the alt deployment desc which are used instead of the web.xml file
     * which is in the war file. The alt-dd tag is in the application.xml file
     * of the ear files and is used ony in the EAR case. ie : deployment of wars
     * packaged into EAR applications. alt-dd tag is optionnal
     * @param earClassLoader the ear classloader which is used for mapped the
     *        URLs of the wars to the Alt dd.
     * @param urls the urls of the wars
     * @param altDDs the alt-dd name for the specified war URLs
     */
    public void setAltDD(ClassLoader earClassLoader, URL[] urls, URL[] altDDs) {

        //Associate an url to a altDD url
        Hashtable urlAltddBindings = new Hashtable();

        //Fill the hashtable for each url
        for (int i = 0; i < urls.length; i++) {
            if (altDDs[i] != null) {
                urlAltddBindings.put(urls[i], altDDs[i]);
            }
        }

        //Bind the hashtable
        earCLAltDDBindings.put(earClassLoader, urlAltddBindings);

    }

    /**
     * Get the size of the cache (number of entries in the cache). This method
     * is used only for the tests.
     * @return the size of the cache (number of entries in the cache).
     */
    public int getCacheSize() {
        int bufferSize = 0;

        Enumeration classLoaders = earCLAltDDBindings.keys();
        while (classLoaders.hasMoreElements()) {
            ClassLoader loader = (ClassLoader) classLoaders.nextElement();
            Hashtable hashtab = (Hashtable) earCLAltDDBindings.get(loader);
            bufferSize = bufferSize + hashtab.size();
        }

        return bufferSize;
    }

    /**
     * Get the specified web deployment descriptor.
     * @param filename the filename where to load xml deployment descriptors.
     * @param loader classloader used to load web classes.
     * @return WebContainerDeploymentDesc the web deployment descriptor.
     * @throws WebContainerDeploymentDescException when
     *         WebContainerDeploymentDesc cannot be created with the given
     *         files.
     */
    public static WebContainerDeploymentDesc getDeploymentDesc(String filename, ClassLoader loader)
            throws WebContainerDeploymentDescException {

        WebContainerDeploymentDesc wcdd = null;
        // if Desc already parsed
        if (staticCache.containsKey(filename)) {
            wcdd = (WebContainerDeploymentDesc) staticCache.get(filename);
        } else {
            // Check if the war exists ...
            if (!new File(filename).exists()) {
                String err = "Cannot get the deployment descriptor for ";
                err += "'" + filename + "'. The file doesn't exist.";
                throw new WebContainerDeploymentDescException(err);
            }
            // get the DeploymentDesc
            try {
                wcdd = getInstance(filename, loader);
            } catch (DeploymentDescException dde) {
                throw new WebContainerDeploymentDescException(dde);
            }
            // put in cache
            staticCache.put(filename, wcdd);
        }

        return wcdd;
    }

    /**
     * Get an instance of a WEB deployment descriptor by parsing the web.xml and
     * jonas-web.xml deployment descriptors.
     * @param warFileName the fileName of the war file for the deployment
     *        descriptors.
     * @param classLoaderForCls the classloader for the classes.
     * @param altWebXmlFilename the fileName to the web.xml for the alt-dd tag
     *        in the Ear Case. This is used for specify an alternate DDesc file.
     * @return a WEB deployment descriptor by parsing the web.xml and
     *         jonas-web.xml deployment descriptors.
     * @throws DeploymentDescException if the deployment descriptors are
     *         corrupted.
     */
    public static WebContainerDeploymentDesc getInstance(String warFileName, ClassLoader classLoaderForCls,
            String altWebXmlFilename) throws DeploymentDescException {

        // init xml contents values;
        String xmlContent = "";
        String jonasXmlContent = "";

        //war file
        JarFile warFile = null;

        //Input streams
        InputStream webInputStream = null;
        InputStream jonasWebInputStream = null;

        //ZipEntry
        ZipEntry webZipEntry = null;
        ZipEntry jonasWebZipEntry = null;

        //Webapps
        WebApp webApp;
        JonasWebApp jonasWebApp;

        //Build the file
        File fWar = new File(warFileName);

        //Check if the file exists.
        if (!(fWar.exists())) {
            String err = "' " + warFileName + "' was not found.";
            throw new WebContainerDeploymentDescException(err);
        }

        //Check if the Alt deploymentDesc file exists.
        //But only if it's a non null value because it's optionnal.
        if ((altWebXmlFilename != null) && (!new File(altWebXmlFilename).exists())) {
            String err = "The file for the altdd tag for the EAR case '" + altWebXmlFilename + "' was not found.";
            throw new WebContainerDeploymentDescException(err);
        }

        // load the web-app deployment descriptor data (WEB-INF/web.xml
        // and WEB-INF/jonas-web.xml)
        try {

            //No alt-dd case
            if (altWebXmlFilename == null) {

                //If warFile is a directory, there is no jar. Check file in the
                // directory
                if (fWar.isDirectory()) {
                    //lookup a WEB-INF/web.xml file
                    File webXmlF = new File(warFileName, WEB_FILE_NAME);
                    if (!webXmlF.exists()) {
                        String err = "You have choose to deploy a war directory but there is no " + WEB_FILE_NAME
                                + " file in the directory " + warFileName;
                        throw new WebContainerDeploymentDescException(err);
                    }
                    webInputStream = new FileInputStream(webXmlF);
                    xmlContent = xmlContent(webInputStream);
                    webInputStream = new FileInputStream(webXmlF);
                } else {
                    warFile = new JarFile(warFileName);
                    //Lookup in the JAR
                    //Check the web entry
                    webZipEntry = warFile.getEntry(WEB_FILE_NAME);
                    if (webZipEntry == null) {
                        throw new WebContainerDeploymentDescException("The entry '" + WEB_FILE_NAME
                                + "' was not found in the file '" + warFileName + "'.");
                    }
                    //Get the stream
                    webInputStream = warFile.getInputStream(webZipEntry);
                    xmlContent = xmlContent(webInputStream);
                    webInputStream = warFile.getInputStream(webZipEntry);
                }
            } else {
                webInputStream = new FileInputStream(altWebXmlFilename);
                xmlContent = xmlContent(webInputStream);
                webInputStream = new FileInputStream(altWebXmlFilename);
            }

            //This is a directory
            if (fWar.isDirectory()) {
                //lookup a WEB-INF/jonas-web.xml file
                File webJXmlF = new File(warFileName, JONAS_WEB_FILE_NAME);
                if (webJXmlF.exists()) {
                    jonasWebInputStream = new FileInputStream(webJXmlF);
                    jonasXmlContent = xmlContent(jonasWebInputStream);
                    jonasWebInputStream = new FileInputStream(webJXmlF);
                }
            } else {
                if (warFile == null) {
                    warFile = new JarFile(warFileName);
                }

                //Check the jonas web entry
                jonasWebZipEntry = warFile.getEntry(JONAS_WEB_FILE_NAME);

                //Get the stream
                if (jonasWebZipEntry != null) {
                    jonasWebInputStream = warFile.getInputStream(jonasWebZipEntry);
                    jonasXmlContent = xmlContent(jonasWebInputStream);
                    jonasWebInputStream = warFile.getInputStream(jonasWebZipEntry);

                }
            }

        } catch (Exception e) {
            if (warFile != null) {
                try {
                    warFile.close();
                } catch (IOException ioe) {
                    // We can't close the file
                    logger.log(BasicLevel.WARN, "Can't close file '" + warFileName + "'");
                }
            }
            throw new WebContainerDeploymentDescException(
                    "Cannot read the XML deployment descriptors of the war file '" + warFileName + "'.", e);
        }

        webApp = loadWebApp(new InputStreamReader(webInputStream), WEB_FILE_NAME);
        try {
            webInputStream.close();
        } catch (IOException e) {
            // Nothing to do
            logger.log(BasicLevel.WARN, "Can't close InputStream of web.xml from '" + warFileName + "'");
        }

        // load jonas-web-app deployment descriptor data
        // (WEB-INF/jonas-web.xml)
        if (jonasWebInputStream != null) {
            jonasWebApp = loadJonasWebApp(new InputStreamReader(jonasWebInputStream), JONAS_WEB_FILE_NAME);
            try {
                jonasWebInputStream.close();
            } catch (IOException e) {
                // Nothing to do
                logger.log(BasicLevel.WARN, "Can't close InputStream of jonas-web.xml from '" + warFileName + "'");
            }
        } else {
            jonasWebApp = new JonasWebApp();
        }

        // close the zip
        if (warFile != null) {
            try {
                warFile.close();
            } catch (IOException ioe) {
                // We can't close the file
                logger.log(BasicLevel.WARN, "Can't close file '" + warFileName + "'");
            }
        }

        // instantiate web deployment descriptor
        WebContainerDeploymentDesc webDD = new WebContainerDeploymentDesc(warFileName, classLoaderForCls, webApp,
                jonasWebApp);
        webDD.setXmlContent(xmlContent);
        webDD.setJOnASXmlContent(jonasXmlContent);
        return webDD;
    }

    /**
     * Get an instance of a WEB deployment descriptor by parsing the web.xml and
     * jonas-web.xml deployment descriptors.
     * @param warFileName the fileName of the war file for the deployment
     *        descriptors.
     * @param classLoaderForCls the classloader for the classes.
     * @return a WEB deployment descriptor by parsing the web.xml and
     *         jonas-web.xml deployment descriptors.
     * @throws DeploymentDescException if the deployment descriptors are
     *         corrupted.
     */
    public static WebContainerDeploymentDesc getInstance(String warFileName, ClassLoader classLoaderForCls)
            throws DeploymentDescException {

        return getInstance(warFileName, classLoaderForCls, null);
    }

    /**
     * Load the web.xml file.
     * @param reader the reader of the XML file.
     * @param fileName the name of the file (web.xml).
     * @return a structure containing the result of the web.xml parsing.
     * @throws DeploymentDescException if the deployment descriptor is
     *         corrupted.
     */
    public static WebApp loadWebApp(Reader reader, String fileName) throws DeploymentDescException {

        WebApp webApp = new WebApp();

        // Create if null
        if (webAppDigester == null) {
            webAppDigester = new JDigester(webAppRuleSet, getParsingWithValidation(), true, new WebAppDTDs(),
                    new WebAppSchemas());
        }

        try {
            webAppDigester.parse(reader, fileName, webApp);
        } catch (DeploymentDescException e) {
            throw e;
        } finally {
            webAppDigester.push(null);
        }
        return webApp;
    }

    /**
     * Load the jonas-web.xml file.
     * @param reader the Reader of the XML file.
     * @param fileName the name of the file (jonas-web.xml).
     * @return a structure containing the result of the jonas-web.xml parsing.
     * @throws DeploymentDescException if the deployment descriptor is
     *         corrupted.
     */
    public static JonasWebApp loadJonasWebApp(Reader reader, String fileName) throws DeploymentDescException {

        JonasWebApp jonasWebApp = new JonasWebApp();

        // Create if null
        if (jonasWebAppDigester == null) {
            jonasWebAppDigester = new JDigester(jonasWebAppRuleSet, getParsingWithValidation(), true,
                    new JonasWebAppDTDs(), new JonasWebAppSchemas());
        }

        try {
            jonasWebAppDigester.parse(reader, fileName, jonasWebApp);
        } catch (DeploymentDescException e) {
            throw e;
        } finally {
            jonasWebAppDigester.push(null);
        }
        return jonasWebApp;
    }

    /**
     * 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) {
        WebDeploymentDescManager.parsingWithValidation = validation;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy