Package org.jvnet.glassfish.comms.deployment.backend

Source Code of org.jvnet.glassfish.comms.deployment.backend.SipArchiveDeployer$ApplicationMatcher

/*
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
*
* Copyright 1997-2009 Sun Microsystems, Inc. All rights reserved.
* Copyright (c) Ericsson AB, 2004-2008. 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.html
* or glassfish/bootstrap/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 glassfish/bootstrap/legal/LICENSE.txt.
* Sun designates this particular file as subject to the "Classpath" exception
* as provided by Sun in the GPL Version 2 section of the License file that
* accompanied this code.  If applicable, add the following below the License
* Header, with the fields enclosed by brackets [] replaced by your own
* identifying information: "Portions Copyrighted [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.
*/

/*
* SipArchiveDeployer.java
*
* This class is an implementation of the ArchiveDeployer intereface and
* extends the WebArchiveDeployer. The main function of this class is to
* handle the processing of a SIP/Converged HTTP+SIP archive by
* 1. expanding the archive
* 2. Processing the SIP Deployment descriptors
* 3. Processing all the Web Application supported deployment descriptors
* 4. Adding these processed descriptors in a SipBundleDescriptor
* In addition this class also supports undeployment and clean up operations
* for a SIP/Converged HTTP+SIP application
* Created on February 27, 2007, 3:10 PM
*
*/
package org.jvnet.glassfish.comms.deployment.backend;

import com.ericsson.ssa.container.auth.DescriptorProcessor;
import com.sun.enterprise.deployment.util.ApplicationValidator;
import com.sun.enterprise.deployment.util.WebBundleVisitor;
import com.sun.enterprise.security.util.IASSecurityException;
import com.sun.enterprise.util.io.FileUtils;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.logging.Level;

import javax.enterprise.deploy.shared.ModuleType;

import org.xml.sax.SAXParseException;

import org.jvnet.glassfish.comms.deployment.backend.SipApplicationBase;

import com.sun.enterprise.config.ConfigException;
import com.sun.enterprise.deployment.Application;
import com.sun.enterprise.deployment.BundleDescriptor;
import com.sun.enterprise.deployment.DeploymentException;
import com.sun.enterprise.deployment.Descriptor;
import com.sun.enterprise.deployment.WebBundleDescriptor;
import com.sun.enterprise.deployment.annotation.AnnotatedElementHandler;
import com.sun.enterprise.deployment.annotation.AnnotationProcessor;
import com.sun.enterprise.deployment.annotation.ProcessingContext;
import com.sun.enterprise.deployment.annotation.factory.AnnotatedElementHandlerFactory;
import com.sun.enterprise.deployment.backend.IASDeploymentException;
import com.sun.enterprise.deployment.backend.WebArchiveDeployer;
import com.sun.enterprise.deployment.deploy.shared.AbstractArchive;
import com.sun.enterprise.deployment.deploy.shared.FileArchive;
import com.sun.enterprise.deployment.interfaces.pluggable.ArchiveDeployer;
import com.sun.enterprise.deployment.interfaces.pluggable.ArchiveDescriptor;
import com.sun.enterprise.deployment.io.DeploymentDescriptorFile;
import com.sun.enterprise.deployment.io.WebDeploymentDescriptorFile;
import com.sun.enterprise.deployment.io.runtime.WebRuntimeDDFile;
import com.sun.enterprise.deployment.pluggable.PluggableDeploymentInfo;
import com.sun.enterprise.deployment.util.DOLLoadingContextFactory;
import com.sun.enterprise.deployment.util.XModuleType;
import com.sun.enterprise.loader.ClassLoaderUtils;
import com.sun.enterprise.loader.EJBClassLoader;
import com.sun.enterprise.security.SecurityUtil;
import com.sun.enterprise.util.i18n.StringManager;

import com.sun.web.security.WebSecurityManager;
import org.xml.sax.SAXParseException;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import javax.enterprise.deploy.shared.ModuleType;

import org.jvnet.glassfish.comms.deployment.backend.SipApplication;
import org.jvnet.glassfish.comms.deployment.annotations.factory.SipHandlerFactory;
import org.jvnet.glassfish.comms.deployment.annotations.scanners.SarScanner;
import org.jvnet.glassfish.comms.deployment.io.runtime.SipRuntimeDDFile;
import org.jvnet.glassfish.comms.deployment.io.SipDeploymentDescriptorFile;
import org.jvnet.glassfish.comms.extensions.Extension;
import org.jvnet.glassfish.comms.security.auth.impl.SipSecurityManager;

/**
*
* @author Prasad Subramanian
*/
public class SipArchiveDeployer extends WebArchiveDeployer
    implements ArchiveDeployer {
    private static StringManager newLocalStrings = StringManager.getManager(SipArchiveDeployer.class);

    // Member variables
    /* Private variables */
    private String SIP_JAR_ENTRY = "WEB-INF/sip.xml";
    private String WEB_JAR_ENTRY = "WEB-INF" + File.separator + "web.xml";
    private ModuleType moduleType = XModuleType.getModuleType(this.getClass()
                                                                  .getName());
    private boolean isJ2eeApplication = false;

    /* Protected variables */
    protected SipBundleDescriptor sbd = null;
    protected DeploymentDescriptorFile standardDD = new WebDeploymentDescriptorFile();
    protected ClassLoader classLoader = null;

    //protected ExtensionModuleConfigManager emConfigMgr = null;
    // need this for representing the BundleDescriptor
    protected WebBundleDescriptor descriptor = null;

    //Public methods
    public boolean load(ArchiveDescriptor descriptor) {
        return true;
    }

    public boolean unload(ArchiveDescriptor descriptor) {
        return true;
    }

    /**
     * This method does the following
     * a. Parse the sip.xml
     * b. Process the web related bundle descriptors
     * c. add the web bundle descriptor to SipBundleDescriptor
     * d. During startup of the Application server reads the deployment
     *    except sip.xml from the generated folder.
     * e. Process annotations defined by the SIP Servlet API (code to be added)
     *
     * @param moduleRootDirectory the directory where the archive is exploded
     * @param moduleScratchDirectory the directory where the generated artifacts     *                               are stored
     * @param parentClassLoader the parent class loader for this application
     * @param isStartup a boolean that indicates if this is a deployment time
     *                  operation or startup time
     */
    public ArchiveDescriptor prepare(File moduleRootDirectory,
        File moduleScratchDirectory, ClassLoader parentClassLoader,
        boolean isStartup) throws Exception {
        classLoader = parentClassLoader;
        String moduleDir = moduleRootDirectory.getAbsolutePath();
        String moduleName = moduleDir.substring(moduleDir.lastIndexOf(File.separator) + 1,
                moduleDir.length());

        // This is the initial moduleDir
        // sailfin/domains/domain1/applications/j2ee-apps/DeployTest/DeployTest-war_war

        // This is the moduleDir at reDeployment
        // sailfin/domains/domain1/generated/xml/j2ee-apps/DeployTest/DeployTest-war_war
        String sarScanDir = moduleDir;

        try {
            if ((moduleDir.indexOf("generated") >= 0) &&
                    (moduleDir.indexOf("xml") >= 0)) {
                if (getJ2eeApplication()) {
                    //
                    String earName = moduleRootDirectory.getParentFile()
                                                        .getName();
                    String appType = moduleRootDirectory.getParentFile()
                                                        .getParentFile()
                                                        .getName();
                    File domainDir = moduleRootDirectory.getParentFile()
                                                        .getParentFile()
                                                        .getParentFile()
                                                        .getParentFile()
                                                        .getParentFile();
                    File scanDir = new File(domainDir,
                            "applications" + File.separatorChar + appType +
                            File.separatorChar + earName + File.separatorChar +
                            moduleRootDirectory.getName());
                    sarScanDir = scanDir.getAbsolutePath();
                } else {
                    //
                    String appType = moduleRootDirectory.getParentFile()
                                                        .getName();
                    File domainDir = moduleRootDirectory.getParentFile()
                                                        .getParentFile()
                                                        .getParentFile()
                                                        .getParentFile();
                    File scanDir = new File(domainDir,
                            "applications" + File.separatorChar + appType +
                            File.separatorChar + moduleRootDirectory.getName());
                    sarScanDir = scanDir.getAbsolutePath();
                }
            }
        } catch (NullPointerException e) {
            logger.log(Level.WARNING, e.toString());
        }

        //parse the web and SIP DDs

        Application application = null;
        WebBundleDescriptor wbd = null;

        // check if this is a converged app. The rule is the presence of a
        // web.xml
        if (hasDDXML(moduleRootDirectory, WEB_JAR_ENTRY)) {
            setConverged(true);
        } else {
            setConverged(false);
        }

        // now check is this a sub-module of an Enterprise Application
        if (getJ2eeApplication()) {
            // we know that its a sub-module in a EAR
            wbd = (WebBundleDescriptor) getBundleDescriptor(moduleDir,
                    parentClassLoader);

            //((SipBundleDescriptor)wbd).setConverged(isConverged());
        } else if (!isStartup && (moduleDir.indexOf("nodeagents") < 0)) {
            // deployment operation
            //set the module type to be WAR
            this.setModuleType(ModuleType.WAR);
            processWebArchive();
            application = getApplication();
            //set the module type back to the archive deployer type
            this.setModuleType(XModuleType.getModuleType(
                    this.getClass().getName()));

            if (application != null) {
                wbd = (WebBundleDescriptor) application.getStandaloneBundleDescriptor();
            }
        } else {
            //this.setModuleType(ModuleType.WAR);

            // loading application during AS startup
            // Obtain the application object
            application = getApplication(moduleName, moduleRootDirectory,
                    moduleScratchDirectory, moduleType);

            //set the module type back to the archive deployer type
            //this.setModuleType(XModuleType.getModuleType(
            //                    this.getClass().getName()));           
            if (application != null) {
                wbd = (WebBundleDescriptor) application.getStandaloneBundleDescriptor();
            }
        }
       
        // check if we have sip.xml or its a DD-less archive
        // If there is a DD we read it, else we initialize the DD objects for annotation
        // processing.
        if (hasDDXML(moduleRootDirectory, SIP_JAR_ENTRY)) {
            readSipDeploymentDescriptors(moduleRootDirectory);
        } else {
            sbd = new SipBundleDescriptor();
            SipApplication sipApplication = new SipApplication();
            sbd.setSipApplication(sipApplication);
        }
        // set the module name
        sbd.getSipApplication().setModuleName(moduleName);
        //set the Referring Decsriptor
        sbd.getSipApplication().setReferringDescriptor(sbd);
        sbd.setConverged(isConverged());

        // copy the web bundle descriptor contents to sbd.
        if (wbd != null) {
            ifwbd.getServletDescriptors().size() > 2 ) {
                sbd.setContainsHTTPServlets(true);
            }
            sbd.copyWebBundleDescriptor(wbd);
            sbd.setApplication(application);
        }

        logger.log(Level.FINE, "Version ="+sbd.getSipApplication().getApplicationVersion());

        // Now process the runtime DDs
        readRuntimeDeploymentDescriptors(moduleRootDirectory, sbd);
        if(!isStartup && (moduleDir.indexOf("nodeagents") < 0) ) {
           //runSipVerifier();
        }
       
        prepareAnnotations(sarScanDir);
      
        if (!getJ2eeApplication()) {           
            if (!isStartup && (moduleDir.indexOf("nodeagents") < 0)) {
                generateSipPolicy((ArchiveDescriptor)sbd);
            }
        }
       
        return sbd;
    }

    /** Utility method to determine if this is directory deploy case or not
     *  The presence of a WEB-INF directory is checked to determine if this
     *  archive needs to be sniffed for sip annotations
     * @param archiveURI
     * @return boolean
     */
    private boolean isDirectoryDeploy(String archiveURI) {
       File directoryRoot = new File(archiveURI);
       File webInfDir = new File(directoryRoot, "WEB-INF");
       if(webInfDir.exists() && webInfDir.isDirectory()) {
            return true;
       } else {
            return false;
       }
    }

    private void prepareAnnotations(String sarScanDir)
        throws DeploymentException , Exception{

        if ( sbd.getSipApplication().getDeploymentErrorInfo() != null ){
            Exception e = new Exception (sbd.getSipApplication().getDeploymentErrorInfo());
            throw e;
        }


        //Create an Annotation processor here
        try {
            AnnotatedElementHandler aeHandler = AnnotatedElementHandlerFactory.createAnnotatedElementHandler(sbd);
            SarScanner scanner = new SarScanner();
            scanner.initScanRepository(new File(sarScanDir),
                  (WebBundleDescriptor) sbd, classLoader);

            if (!scanner.getElements().isEmpty()) {
                AnnotationProcessor ap = SipHandlerFactory.getAnnotationProcessor();
                ProcessingContext ctx = ap.createContext();

                ctx.setProcessingInput(scanner);
                ctx.pushHandler(aeHandler);
                ap.process(ctx);
                postProcessAnnotations();
            }
        } catch (DeploymentException e) {
            throw e;
        }
        catch (Exception ioe) {
            ioe.printStackTrace();
            logger.log(Level.SEVERE, ioe.toString());
        }
    }

    @Override
    public void removePolicy() throws IASDeploymentException {
        try {
            super.removePolicy();
           
            String requestName = request.getName();
            cleanSecurityContext(requestName);
            String[] ctxIds = SipSecurityManager.getContextsForApp(requestName, true);
            if (ctxIds != null) {
                for (String pid : ctxIds) {                   
                    SecurityUtil.removePolicy(pid);
                }
            }
           


        } catch (IASSecurityException ex) {
            Logger.getLogger(SipArchiveDeployer.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
   
     private void cleanSecurityContext(String appName) {

//        String[] ctxIds = SipSecurityManager.getContextsForApp(appName, false);
//        if(ctxIds != null){
//        for (String pid : ctxIds) {
//            try {
//                SecurityUtil.removePolicy(pid);
//            } catch (IASSecurityException ex) {
//                ex.printStackTrace();
//                Logger.getLogger(ConvergedContextConfig.class.getName()).log(Level.SEVERE, null, ex);
//            }
//        }
//        }
        ArrayList<SipSecurityManager> managers =
                SipSecurityManager.getManagersForApp(appName, false);

        for (int i = 0; managers != null && i < managers.size(); i++) {

            try {
                managers.get(i).destroy();
            } catch (javax.security.jacc.PolicyContextException pce) {
                pce.printStackTrace();
            // log it and continue
            //_logger.log(Level.WARNING,
            //      "Unable to destroy WebSecurityManager",
            //    pce);
            }
        }
    }
   
    public void generateSipPolicy(ArchiveDescriptor desc) throws Exception {
        super.generatePolicy();
        SipBundleDescriptor sipDesc = (org.jvnet.glassfish.comms.deployment.backend.SipBundleDescriptor) desc;

        SipApplication sipApplication = (SipApplication) sipDesc.getSipApplication();

        SipSecurityManager manager = SipSecurityManager.createManager(sipDesc, true);
        String pContextId = manager.getContextID();

        if (!manager.inService()) {
            new DescriptorProcessor().process(pContextId, sipApplication);
        }


    }
   
    public void removePolicy(String appName) throws Exception {
        try {


            cleanSecurityContext(appName);
            String[] ctxIds = SipSecurityManager.getContextsForApp(appName, true);
            if (ctxIds != null) {
                for (String pid : ctxIds) {
                    SecurityUtil.removePolicy(pid);
                }
            }

            ArrayList<WebSecurityManager> managers =
                    WebSecurityManager.getManagersForApp(appName, false);

            for (int i = 0; managers != null && i < managers.size(); i++) {

                try {
                    managers.get(i).destroy();
                } catch (javax.security.jacc.PolicyContextException pce) {
                    // log it and continue
                    logger.log(Level.WARNING,
                            "Unable to destroy WebSecurityManager",
                            pce);
                }
            }

            ctxIds = WebSecurityManager.getContextsForApp(appName, true);

            if (ctxIds != null && ctxIds.length > 0 && ctxIds[0] != null) {
                SecurityUtil.removePolicy(ctxIds[0]);
            }

        } catch (IASSecurityException ex) {
            throw new IASDeploymentException( ex);
        }
    }
   
    public void generatePolicy(ArchiveDescriptor desc) throws Exception {
        SipBundleDescriptor sipDesc = (org.jvnet.glassfish.comms.deployment.backend.SipBundleDescriptor) desc;

        SipApplication sipApplication = (SipApplication) sipDesc.getSipApplication();

        SipSecurityManager manager = SipSecurityManager.createManager(sipDesc, true);
        String pContextId = manager.getContextID();

        if (!manager.inService()) {
            new DescriptorProcessor().process(pContextId, sipApplication);
        }


    }
    
    private void postProcessAnnotations() throws Exception {
         postProcessServletAnnotations();
         postProcessListenerAnnotations();
         postProcessSipApplicationKeyAnnotations();
     }
     /**
      * Post process the listener annotations. The matching listeners
      * will be added to the listener list.
      *
      * @throws DeploymentException
      */
     private void postProcessListenerAnnotations() throws DeploymentException {
         SipApplication sipApplication = (SipApplication) sbd.getSipApplication();
         Collection<SipListener> listeners = sipApplication.getAnnotatedListeners();
         ApplicationMatcher matcher = new ApplicationMatcher(sipApplication);
         for (SipListener listener : listeners) {
             /// XXX: Commenting out for now.
             /*if (matcher.match(listener.getPackageName(),
                         listener.getApplicationName())) { */
                 sipApplication.addListener(listener.getListenerClass());
            
         }
     }
     /**
      * Post process SipApplicationKey annotations.
      * There may only be one matching such per application.
      *
      * @throws DeploymentException
      */
     private void postProcessSipApplicationKeyAnnotations()
         throws DeploymentException {
         SipApplication sipApplication = (SipApplication) sbd.getSipApplication();
         /**
          * Fetch the candidates.
          */
         Collection<SipApplicationKey> sipApplicationKeyAnnotationCandidates = sipApplication.getAnnotatedSipApplicationKeys();
         ApplicationMatcher matcher = new ApplicationMatcher(sipApplication);
         /**
          * Create temporary object that stores all application name matching such
          */
         ArrayList<SipApplicationKey> matchingSipApplicationKeyAnnotations = new ArrayList<SipApplicationKey>();
         /**
          * Match.
          */
         for (SipApplicationKey listener : sipApplicationKeyAnnotationCandidates) {
             /* if (matcher.match(listener.getPackageName(),
                         listener.getApplicationName())) { */
                 matchingSipApplicationKeyAnnotations.add(listener);
            /* } */
         }
         /**
          * There may be at most one matching @SipApplicationKey
          */
        
         if (matchingSipApplicationKeyAnnotations.size() > 1) {
             // Several sipApplicationKey methods
             String errMsg = newLocalStrings.getString(
                        "enterprise.deployment.backend.sip.duplicatesak.found",
                           sipApplication.getModuleID());
             logger.log(Level.SEVERE, errMsg );
             String exMsg = newLocalStrings.getString(
                        "enterprise.deployment.backend.sip.cannot.have.dupsak");
             throw new DeploymentException(exMsg);
         }
        
         if (matchingSipApplicationKeyAnnotations.size() == 1) {
             sipApplication.setSipApplicationKey(matchingSipApplicationKeyAnnotations.get(
                     0).getApplicationKeyMethod());
         }
     }
    private void postProcessServletAnnotations() throws Exception {

        // Rules for adding annotated SipServlets

        // 1. If only one annotated SipServlet exists, then the SipApplication
        // annotation is optional.
        // Otherwise a logging error

        SipApplication sipApplication = (SipApplication) sbd
                .getSipApplication();
       
        String ApplicationName = sipApplication.getAppName();
        String mainServletName = sipApplication.getMainservletName();

        Map<String, Servlet> annotatedServlets = sipApplication.getAnnotatedServlets();

        if (annotatedServlets == null || annotatedServlets.isEmpty()) {
            Extension.getInstance().processAnnotations(sipApplication);
        }

        // Find the number of annotated servlets
        int noAnnotatedServlets = annotatedServlets.size();

        // Find the number of servlets defined in the DD.
        int declarativeDefinedServlets = sipApplication.getServlets().size();

        // If multiple annotated servlets exists, then a main servlet has to be
        // defined in the SipApplication annotation.
        // If a servlet-mapping mechanism is used, then we do not need the
        // main-servlet

        if (mainServletName == null &&
                noAnnotatedServlets > 1 &&
                    sipApplication.getServletMappings() == null) {
            logger.log(Level.SEVERE,
                            "No main servlet defined in a SAR archive " +
                            "with multiple annotated servlets");
            throw new DeploymentException(
                    "No main servlet defined in a SAR archive " +
                    "with multiple annotated servlets");
        }
       
        if ( mainServletName != null ) {
            ExistsOperand existsOperand = new ExistsOperand();
            existsOperand.setVariable("request.method");
            Pattern pattern = new Pattern();
            pattern.addCondition(existsOperand);

            ServletMapping servletMapping = new ServletMapping();
            servletMapping.setServletName(mainServletName);
            servletMapping.setPattern(pattern);
           
            // applicable if main servlet is annotated
            Servlet servlet = annotatedServlets.remove(mainServletName);
           
            if ( servlet != null ) {
              sipApplication.addServlet(servlet);
            }
           
            sipApplication.addServletMapping(servletMapping);
        }
       

        for (String servletName : annotatedServlets.keySet()) {
            Servlet servlet = annotatedServlets.get(servletName);

            // Check that the servlet belongs to the same application, by bening
            // defined in same package

            // Check that this servlet name is not defined in sip.xml
            // then ignore it.
            Map<String, Servlet> servlets = sipApplication.getServlets();

            // Servlets defined in sip.xml overrides annotations
            if (servlets.get(servletName) != null) {
                // Servlet specified in sip.xml
                if (logger.isLoggable(Level.INFO)) {
                    logger.log(Level.INFO,
                        "Annotated servlet found with same name " +
                        "as servlet defined in sip.xml name = " + servletName);
                    logger.log(Level.INFO, "Annotated servlet discarded");
                }

                continue;
            }
           
            // check if the same servlet class has been defined twice using annotations and sip.xml
            boolean isDuplicateClass = false;
            Iterator servletNameIter = sipApplication.getServletNames();
            while( servletNameIter.hasNext()) {
                String servletNameinDD = (String) servletNameIter.next();
                if(sipApplication.getServlet(servletNameinDD).getServletClass().equals(
                    servlet.getServletClass())) {
                    String msg = newLocalStrings.getString(
                        "enterprise.deployment.backend.sip.same.servlet.class.used",
                            servlet.getServletName());
                    logger.log(Level.WARNING, msg);                   
                    isDuplicateClass = true;
                    break;
                }
            }
           
            if(isDuplicateClass) continue;

            /*
             * Check that the Servlet belongs to the same Application, That is
             * 1. Same Package as the package-info.java package annotation, or
             * 2. Same Application Name
             *
             */
            String servletPackage = servlet.getPackageName();
            String anotatedServletApplication = servlet.getApplicationName();

            /// XXX: Fix me later
            /*
            if (!new ApplicationMatcher(sipApplication).match(servletPackage,
                        anotatedServletApplication)) {
                // Not in same application, discharge his servlet
                if (logger.isLoggable(Level.INFO)) {
                    logger.log(Level.INFO,
                        "Annotated servlet found " + servletName +
                        " Servlet not defined as part of Sip Application " +
                        sipApplication.getAppName() + "and discharged");
                }

                continue;
            } else {
                if (logger.isLoggable(Level.INFO)) {
                    logger.log(Level.INFO,
                        "Deploying " + servletName +
                        " as belonging to application " +
                        sipApplication.getAppName());
                }
            }
             */

            ExistsOperand existsOperand = new ExistsOperand();

            // If only one annotated servlet exist, this is regarded as main
            // servlet
            if (servletName.equals(mainServletName) ||
                    (noAnnotatedServlets == 1)) {
                // Create a match all Pattern
                existsOperand.setVariable("request.method");
            } else {
                // Create a match nothing Pattern
                // This is not part of Operand.getAttributeValue()
                existsOperand.setVariable("NeverMatchMe");
            }

            sipApplication.addServlet(servlet);
            if(sipApplication.getServletMappings(servletName) == null ) {
                Pattern pattern = new Pattern();
                pattern.addCondition(existsOperand);

                ServletMapping servletMapping = new ServletMapping();
                servletMapping.setServletName(servletName);
                servletMapping.setPattern(pattern);
                sipApplication.addServletMapping(servletMapping);
            }
        }
    }

    /**
    * Expands the archive to be deployed. Delegates to the super class.
    * @param archivePath the path to the archive
    * @param moduleRootDirectory the directory where the contents of the
    *                            archive would need to be copied after
    *                            exploded
    */
    public void expand(File archivePath, File moduleRootDirectory)
        throws Exception {
        super.expand(archivePath, moduleRootDirectory);
    }

    /**
     * Determines if this is the correct ArchiveDeployer to process this archive
     * @param archive the archive being processed
     * @return boolean true if this the ArchiveDeployer implementation to
     *                 process this archive
     */
    public boolean handles(AbstractArchive archive) throws IOException {
           
        // Need to check the case when there is no sip.xml  
        return hasSipXML(archive) || hasSipAnnotations(archive);
       
    }

    /**
     * Main method that deals with undeployment of the SIP/Converged Applications
     * @param archive the location of the archive that is being undeployed
     */
    public void cleanup(File archive) {
        //set the module type to be WAR
        this.setModuleType(ModuleType.WAR);
        processWebArchive();
        cleanup_internal();
        //set the module type back to the archive deployer type
        this.setModuleType(XModuleType.getModuleType(this.getClass().getName()));
    }

    /**
     * Method that returns a description for this extension module
     * @return the description for this module
     */
    public String getModuleDescription() {
        return "SIP Application";
    }

    /**
     * Method that returns the standard deployment descriptor
     * @return the class that represents a standard deployment descriptor
     *          file
     */
    public DeploymentDescriptorFile getStandardDDFile() {
        return standardDD;
    }

    /**
     * Returns the runtime deployment descriptor sun-web.xml in this case
     * @return the class that represenst the runtime web descriptor
     */
    public DeploymentDescriptorFile getConfigurationDDFile() {
        return new WebRuntimeDDFile();
    }

    /**
     * Returns the default web.xml representation
     * @return the class the represents the default-web.xml
     */
    public Descriptor getDefaultBundleDescriptor() {
        WebBundleDescriptor webBundleDesc = DOLLoadingContextFactory.getDefaultWebBundleDescriptor();

        return webBundleDesc;
    }

    protected boolean hasDDXML(File moduleRootDirectory, String JAR_ENTRY) {
        try {
            File webXML = new File(moduleRootDirectory, JAR_ENTRY);

            if (!webXML.exists()) {
                return false;
            }

            FileInputStream fis = new FileInputStream(webXML);

            if (fis.read() > 0) {
                fis.close();

                return true;
            } else {
                fis.close();

                return false;
            }
        } catch (IOException ioe) {
            logger.log(Level.SEVERE, ioe.toString());

            return false;
        }
    }

    /**
     * This method checks if the archive being processed has a WEB-INF/sip.xml
     * or not. This is used to deteremine if this class can process this archive     * or not
     * @return true if there is a WEB-INF/sip.xml in the archive
     */
    protected boolean hasSipXML(AbstractArchive archive)
        throws IOException {
        InputStream is = null;

        try {
            is = archive.getEntry(SIP_JAR_ENTRY);

            if (is != null) {
                return true;
            } else {
                return false;
            }
        } catch (IOException ioe) {
            String msg = newLocalStrings.getString(
                    "enterprise.deployment.backend.sip.ioexception") +
                ioe.getMessage();
            IOException e = new IOException(msg);
            e.initCause(ioe);
            throw e;
        } finally {
            try {
                if (is != null) {
                    is.close();
                }
            } catch (IOException ioexception) {
                String msg = newLocalStrings.getString(
                        "enterprise.deployment.backend.sip.ioexception") +
                    ioexception.getMessage();
                IOException e = new IOException(msg);
                e.initCause(ioexception);
                throw e;
            }
        }
    }

    /**
     * This method reads the sip.xml contents into a byteArryInputStream. This
     * method tries to replicate what the ServletContext.getResourceAsStream
     * does
     *
     * @param moduleRootDirectory the directory where the module is exploded
     * @param sipXmlPath the path to the sip.xml with the application
     * @return InputStream
     */
    protected InputStream getSipXml(File moduleRootDirectory, String sipXmlPath)
        throws Exception {
        File sipXmlFile = new File(moduleRootDirectory, sipXmlPath);

        try {
            // create a FileInputStream
            FileInputStream fis = new FileInputStream(sipXmlFile);
            byte[] sipXmlBytes = new byte[(int) sipXmlFile.length()];

            // read the file into the byte array
            int offset = 0;
            int numRead = 0;

            while ((offset < sipXmlBytes.length) &&
                    ((numRead = fis.read(sipXmlBytes, offset,
                            sipXmlBytes.length - offset)) >= 0)) {
                offset = +numRead;
            }

            // now create a ByteArrayInputStream
            return new ByteArrayInputStream(sipXmlBytes);
        } catch (FileNotFoundException fnfe) {
            String msg = newLocalStrings.getString(
                    "enterprise.deployment.backend.sip.filenotfound") +
                fnfe.getMessage();
            Exception e = new Exception(msg);
            e.initCause(fnfe);
            throw e;
        } catch (IOException ioe) {
            String msg = newLocalStrings.getString(
                    "enterprise.deployment.backend.sip.ioexception") +
                ioe.getMessage();
            Exception e = new Exception(msg);
            e.initCause(ioe);
            throw e;
        }
    }

    /**
     * Returns the moduleType of the application being processed
     * @return the ModuleType object that represents the module type of the
     *         application being processed
     */
    public ModuleType getModuleType() {
        return moduleType;
    }

    /**
     * Sets the module type for the application being processed
     * @param mType the ModuleType object representing the module type
     */
    public void setModuleType(ModuleType mType) {
        moduleType = mType;
    }

    public void setDescriptor(Descriptor descriptor) {
        if (descriptor instanceof WebBundleDescriptor) {
            this.descriptor = (WebBundleDescriptor) descriptor;
        } else {
            if (descriptor instanceof Application) {
                // this is acceptable if the application actually represents
                // a standalone module
                java.util.Set webBundles = ((Application) descriptor).getWebBundleDescriptors();

                if (webBundles.size() > 0) {
                    this.descriptor = (WebBundleDescriptor) webBundles.iterator()
                                                                      .next();

                    if (this.descriptor.getModuleDescriptor().isStandalone()) {
                        return;
                    } else {
                        this.descriptor = null;
                    }
                }
            }

            throw new RuntimeException("Error setting descriptor " +
                descriptor + " in " + this);
        }
    }

    /**
     * Returns the descriptor object for the module being processed
     * @return the descriptor object for the module being processed
     */
    public BundleDescriptor getDescriptor() {
        return descriptor;
    }

    /**
     * This method parses the sun-sip.xml
     * @param moduleRootDirectory
     * @param sbd
     * @throws java.lang.Exception
     */
    public void readRuntimeDeploymentDescriptors(File moduleRootDirectory,
        SipBundleDescriptor sbd) throws Exception {
        FileArchive archive = new FileArchive();

        try {
            archive.open(moduleRootDirectory.getAbsolutePath());
        } catch (IOException io) {
            throw new Exception(io.getCause());
        }

        String ddFileEntryName = getRuntimeDeploymentDescriptorPath();

        if (ddFileEntryName == null) {
            return;
        }

        InputStream is = null;

        try {
            // apply the runtime settings if any
            is = archive.getEntry(ddFileEntryName);

            DeploymentDescriptorFile confDD = new SipRuntimeDDFile();

            if (archive.getArchiveUri() != null) {
                confDD.setErrorReportingString(archive.getArchiveUri());
            }

            if ((is != null) && (confDD != null)) {
                confDD.setXMLValidation(super.getRuntimeXMLValidation());
                confDD.setXMLValidationLevel(super.getRuntimeXMLValidationLevel());
                confDD.read(sbd, is);
            }
        } catch (SAXParseException spe) {
            String msg = newLocalStrings.getString(
                    "enterprise.deployment.backend.sip.saxparseexception") +
                spe.getMessage();
            Exception e = new Exception(msg);
            e.initCause(spe);
            throw e;
        } catch (IOException ioe) {
            String msg = newLocalStrings.getString(
                    "enterprise.deployment.backend.sip.ioexception") +
                ioe.getMessage();
            Exception e = new Exception(msg);
            e.initCause(ioe);
            throw e;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ioe) {
                    throw new Exception(ioe.getCause());
                }
            }
        }
    }

    public String getRuntimeDeploymentDescriptorPath() {
        return new SipRuntimeDDFile().getDeploymentDescriptorPath();
    }

    @Override
    public void runVerifier() throws IASDeploymentException {
        /**
         * Verification process should be deferred until the
         * SipApplication is available. Hence, deliberate NO-OP here.
         */
    }
   
    private void runSipVerifier() throws Exception {
        /**
         * Set sbd in the ModuleDescriptor so that
         * application.getModules().next() returns the newly created
         * SipModule instead of WebModule.
         */
        BundleDescriptor prev = sbd.getModuleDescriptor().getDescriptor();
        sbd.getModuleDescriptor().setDescriptor(sbd);
        super.runVerifier();
        sbd.getModuleDescriptor().setDescriptor(prev);
    }
   
    /**
     * Method to read the sip.xml in an archive and add a SipApplication  object
     * to the SipBundledescriptor passed in
     * @param moduleRootDirectory the path where the archive is exploded
     * @param sbd the SipBundleDescriptor object for the entire bundle
     */
    public void readSipDeploymentDescriptors(File moduleRootDirectory)
         throws Exception {
       
        FileArchive archive = new FileArchive();

        try {
            archive.open(moduleRootDirectory.getAbsolutePath());
        } catch (IOException io) {
           String msg =
                   newLocalStrings.getString("enterprise.deployment.backend.sip.ioexception")
                   + io.getMessage();
           Exception e = new Exception(msg);
           e.initCause(io);
           throw e;
        }

        String ddFileEntryName = getSipDeploymentDescriptorPath();

        if (ddFileEntryName == null) {
            return;
        }

        InputStream is = null;

        try {
            // apply the runtime settings if any
            is = archive.getEntry(ddFileEntryName);

            DeploymentDescriptorFile confDD = new SipDeploymentDescriptorFile();

            if (archive.getArchiveUri() != null) {
                confDD.setErrorReportingString(archive.getArchiveUri());
            }

            if ((is != null) && (confDD != null)) {
                confDD.setXMLValidation(super.getRuntimeXMLValidation());
                confDD.setXMLValidationLevel(super.getRuntimeXMLValidationLevel());
                SipApplication sipApplication = (SipApplication) confDD.read(is);
                this.sbd = (SipBundleDescriptor) sipApplication.getReferringDescriptor();
            }
        } catch (SAXParseException spe) {
           String msg =
                   newLocalStrings.getString("enterprise.deployment.backend.sip.saxparseexception")
                   + spe.getMessage();
           Exception e = new Exception(msg);
           e.initCause(spe);
           throw e;
        } catch (IOException ioe) {
           String msg =
                   newLocalStrings.getString("enterprise.deployment.backend.sip.ioexception")
                   + ioe.getMessage();
           Exception e = new Exception(msg);
           e.initCause(ioe);
           throw e;
        } finally {
            if (is != null) {
                try {
                    is.close();
                } catch (IOException ioe) {
                   String msg =
                       newLocalStrings.getString("enterprise.deployment.backend.sip.ioexception")
                       + ioe.getMessage();
                   Exception e = new Exception(msg);
                   e.initCause(ioe);
                   throw e;                  
                }
            }
        }
     }

    /**
     * Method to return the Deployment Descriptor path in a archive
     * @return String the relative path of the DD within the archive
     */
    public String getSipDeploymentDescriptorPath() {
        return new SipDeploymentDescriptorFile().getDeploymentDescriptorPath();
    }

    public void setJ2eeApplication(boolean isJ2ee) {
        this.isJ2eeApplication = isJ2ee;
    }

    public boolean getJ2eeApplication() {
        return isJ2eeApplication;
    }
   
    /**
     * This method scans the archive for annotations defined by Sip Servlet API 1.1
     * @param archive
     * @return boolean
     * @throws java.io.IOException
     */
    public boolean hasSipAnnotations(AbstractArchive archive)  {
        if(System.getProperty("com.sun.aas.comms.sipDDMandated") != null ) {
            return false;
        }

        if (Extension.getInstance().isConverged(archive)) {
            return true;
        }

        // We create a dummy descriptor for checkin for annotations in the handles() method.
        SipBundleDescriptor dummySbd = new SipBundleDescriptor();
        // create a new dummy SipApplication object and add it to the dummySbd
        SipApplication dummySipApp = new SipApplication();
        dummySbd.setSipApplication(dummySipApp);
        File destForArchive = null;
        boolean isDirectoryDeploy = false;
      
        //Create an Annotation processor here
        try {
            // get the destination to expand this
            String archiveURI = archive.getArchiveUri();
            isDirectoryDeploy = isDirectoryDeploy(archiveURI);
            destForArchive = new File(archiveURI.replace(".", "_"));
           
            // It has to be a .war or .sar to have annotations defined by
            // JSR289. If the extension is not either of them, we return a
            // false and do not process the archive.
            if(archiveURI.endsWith(".war") || archiveURI.endsWith(".sar")) {
                super.expand(new File(archiveURI), destForArchive);
            else if(!isDirectoryDeploy) {
                return false;
            }

            System.out.println("CL ::"+getClassLoader().toString());
            AnnotatedElementHandler aeHandler = AnnotatedElementHandlerFactory.createAnnotatedElementHandler(dummySbd);
            SarScanner scanner = new SarScanner();
            scanner.initScanRepository(destForArchive,
                  (WebBundleDescriptor) dummySbd, getClassLoader());

            if (!scanner.getElements().isEmpty()) {
                AnnotationProcessor ap = SipHandlerFactory.getAnnotationProcessor();
                ProcessingContext ctx = ap.createContext();

                ctx.setProcessingInput(scanner);
                ctx.pushHandler(aeHandler);
                ap.process(ctx);
               
                // Check if there are Servlets or Listeners. XXX: Should the check for Servlets alone be not
                // enough?
                if ((!dummySbd.getSipApplication().getAnnotatedServlets().isEmpty()) ||
                   (!dummySbd.getSipApplication().getAnnotatedListeners().isEmpty())){
                    dummySbd = null
                    if(!isDirectoryDeploy) whackExpandedArchive(destForArchive);
                    return true;
                } else {
                    dummySbd = null
                    if(!isDirectoryDeploy) whackExpandedArchive(destForArchive);
                    return false;
                }
            }
           
        } catch (Exception ex ) {
            if(!isDirectoryDeploy) whackExpandedArchive(destForArchive);
            logger.log(Level.WARNING, "Exception thrown in " + this.getClass() +
                "while scanning for annotations");
        }
 
       if(!isDirectoryDeploywhackExpandedArchive(destForArchive);
       
        dummySbd = null;
        return false;
       
    }
   
    private void whackExpandedArchive(File archiveToBeWhacked) {
       
        if( archiveToBeWhacked != null &&
                   archiveToBeWhacked.exists() &&
                       archiveToBeWhacked.isDirectory() ) {
               FileUtils.whack(archiveToBeWhacked);
              
        }
    }

    /**
     * Class ApplicationMatcher
     *
     * An ApplicationMatcher matches appName settings in an annotated object (SipServlet or SipListener) against
     * name of application.
     *
     *
     * @author qmaghes
     */
    class ApplicationMatcher {
        /**
             * SipApplication to match against.
             */
        SipApplication sipApplication;

        public ApplicationMatcher(SipApplication application) {
            this.sipApplication = application;
        }

        /**
             * match application name against SipApplication
             * There are three possible outcomes.
             * 1. Returns true if this object belongs to application and should be deployed
             * 2. Returns false if this object belongs to another application and should not be deployed.
             * 3. Throws DeploymentException if the settings are invalid and JSR289 mandates deployment error.
             *
             * @param objectPackageName
             * @param objectAnnotatedApplicationName
             * @return
             * @throws DeploymentException
             */
        public boolean match(String objectPackageName,
            String objectAnnotatedApplicationName) {
            if (noApplicationNameSet()) {
                logger.log(Level.WARNING,
                     "Application name is not specified, though it is mandatory for sipservlet 1.1 applications");
                return false;
                //throw new DeploymentException(
                 //   "Application name is not specified, though it is mandatory for sipservlet 1.1 applications");
            }

            if (hasSpecifiedApplicationName(objectAnnotatedApplicationName)) {
                return sameApplicationName(objectAnnotatedApplicationName);
            } else {
                // has not specified application
                // There are three possibilities
                // since we have already checked that
                // appname is set somehow.
                //
                // 1. Appname set in DD => OK
                // 2. Appname set in same package => OK 
                // 3. Appname set in other package => Deployment error
                if (isApplicationNameSpecifiedInDD()) {
                    return true;
                } else {
                    if (belongsToPackage(objectPackageName)) {
                        return true;
                    } else {
                       logger.log(Level.WARNING, "Application \'" +
                            sipApplication.getAppName() +
                            "\' not deployed since some SipListeners or SipServlets has not specified appName in annotation");                      
                       return false;
                        //throw new DeploymentException("Application \'" +
                         //   sipApplication.getAppName() +
                         //   "\' not deployed since some SipListeners or SipServlets has not specified appName in annotation");
                    }
                }
            }
        }

        private boolean noApplicationNameSet() {
            return sipApplication.getAppName() == null;
        }

        /**
        *
        * @return
        */
        private boolean isApplicationNameSpecifiedInDD() {
            return sipApplication.isAppNameFromDD();
        }

        private boolean sameApplicationName(String annotatedListenerApplication) {
            return annotatedListenerApplication.equals(sipApplication.getAppName());
        }

        private boolean belongsToPackage(String listenerPackage) {
            String packageInfoPackage = sipApplication.getPackageName();

            return (packageInfoPackage != null) && (listenerPackage != null) &&
            listenerPackage.equals(packageInfoPackage);
        }

        private boolean hasSpecifiedApplicationName(
            String annotatedListenerApplication) {
            return !"".equals(annotatedListenerApplication);
        }
    }
}
TOP

Related Classes of org.jvnet.glassfish.comms.deployment.backend.SipArchiveDeployer$ApplicationMatcher

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.