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

com.sun.enterprise.v3.server.ApplicationLifecycle Maven / Gradle / Ivy

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

package com.sun.enterprise.v3.server;

import com.sun.enterprise.config.serverbeans.*;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.deploy.shared.FileArchive;
import com.sun.enterprise.util.LocalStringManagerImpl;
import java.beans.PropertyVetoException;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.util.*;
import java.util.concurrent.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.glassfish.api.*;
import org.glassfish.api.admin.ParameterMap;
import org.glassfish.api.admin.ServerEnvironment;
import org.glassfish.api.admin.config.ApplicationName;
import org.glassfish.api.container.Container;
import org.glassfish.api.container.Sniffer;
import org.glassfish.api.deployment.*;
import org.glassfish.api.deployment.archive.*;
import org.glassfish.api.event.*;
import org.glassfish.api.event.EventListener.Event;
import org.glassfish.api.virtualization.VirtualizationEnv;
import org.glassfish.common.util.admin.ParameterMapExtractor;
import org.glassfish.deployment.common.*;
import org.glassfish.deployment.monitor.DeploymentLifecycleProbeProvider;
import org.glassfish.deployment.versioning.VersioningSyntaxException;
import org.glassfish.deployment.versioning.VersioningUtils;
import org.glassfish.hk2.api.MultiException;
import org.glassfish.hk2.api.PostConstruct;
import org.glassfish.hk2.api.PreDestroy;
import org.glassfish.hk2.api.ServiceLocator;
import org.glassfish.hk2.classmodel.reflect.Parser;
import org.glassfish.hk2.classmodel.reflect.ParsingContext;
import org.glassfish.hk2.classmodel.reflect.Types;
import org.glassfish.internal.api.*;
import org.glassfish.internal.data.*;
import org.glassfish.internal.deployment.ApplicationLifecycleInterceptor;
import org.glassfish.internal.deployment.Deployment;
import org.glassfish.internal.deployment.DeploymentTracing;
import org.glassfish.internal.deployment.ExtendedDeploymentContext;
import org.glassfish.kernel.KernelLoggerInfo;
import org.glassfish.server.ServerEnvironmentImpl;
import org.jvnet.hk2.annotations.Optional;

import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.config.ConfigBean;
import org.jvnet.hk2.config.ConfigBeanProxy;
import org.jvnet.hk2.config.ConfigSupport;
import org.jvnet.hk2.config.RetryableException;
import org.jvnet.hk2.config.SingleConfigCode;
import org.jvnet.hk2.config.Transaction;
import org.jvnet.hk2.config.TransactionFailure;
import org.jvnet.hk2.config.types.Property;

/**
 * Application Loader is providing useful methods to load applications
 *
 * @author Jerome Dochez, Sanjeeb Sahoo
 */
@Service
@Singleton
public class ApplicationLifecycle implements Deployment, PostConstruct {

    private static final String[] UPLOADED_GENERATED_DIRS = new String [] {"policy", "xml", "ejb", "jsp"};

    @Inject
    protected SnifferManagerImpl snifferManager;

    @Inject
    ServiceLocator habitat;

    @Inject
    ArchiveFactory archiveFactory;

    @Inject
    ContainerRegistry containerRegistry;

    @Inject
    public ApplicationRegistry appRegistry;

    @Inject
    protected Applications applications;

    @Inject @Named( ServerEnvironment.DEFAULT_INSTANCE_NAME)
    Server server;

    @Inject
    protected Domain domain;

    @Inject
    ServerEnvironmentImpl env;
   
    @Inject @Optional
    VirtualizationEnv virtEnv;

    @Inject
    Events events;

    @Inject
    ConfigSupport configSupport;

    protected Logger logger = KernelLoggerInfo.getLogger();
    final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(ApplicationLifecycle.class);      
    
    protected  Deployer getDeployer(EngineInfo engineInfo) {
        return engineInfo.getDeployer();
    }

    protected DeploymentLifecycleProbeProvider 
        deploymentLifecycleProbeProvider = null;

    private ExecutorService executorService = null;

    private Collection alcInterceptors = Collections.EMPTY_LIST;
    
    public void postConstruct() {
        executorService = createExecutorService();
        deploymentLifecycleProbeProvider = 
            new DeploymentLifecycleProbeProvider();
        alcInterceptors = habitat.getAllServices(
            ApplicationLifecycleInterceptor.class);
    }

    /**
     * Returns the ArchiveHandler for the passed archive abstraction or null
     * if there are none.
     *
     * @param archive the archive to find the handler for
     * @return the archive handler or null if not found.
     * @throws IOException when an error occur
     */
    public ArchiveHandler getArchiveHandler(ReadableArchive archive) throws IOException {
        return getArchiveHandler(archive, null);
    }

    /**
     * Returns the ArchiveHandler for the passed archive abstraction or null
     * if there are none.
     *
     * @param archive the archive to find the handler for
     * @param type the type of the archive
     * @return the archive handler or null if not found.
     * @throws IOException when an error occur
     */
    public ArchiveHandler getArchiveHandler(ReadableArchive archive, String type) throws IOException {
        if (type != null) {
            return habitat.getService(ArchiveDetector.class, type).getArchiveHandler();
        }
        List detectors = new ArrayList(habitat.getAllServices(ArchiveDetector.class));
        Collections.sort(detectors, new Comparator() {
            // rank 2 is considered lower than rank 1, let's sort them in inceasing order
            @Override
            public int compare(ArchiveDetector o1, ArchiveDetector o2) {
                return o1.rank() - o2.rank();
            }
        });
        for (ArchiveDetector ad : detectors) {
            if (ad.handles(archive)) {
                return ad.getArchiveHandler();
            }
        }
        return null;
    }

    public ApplicationInfo deploy(final ExtendedDeploymentContext context) {
        return deploy(null, context);
    }

    public ApplicationInfo deploy(Collection sniffers, final ExtendedDeploymentContext context) {

        long operationStartTime = Calendar.getInstance().getTimeInMillis();

        events.send(new Event(Deployment.DEPLOYMENT_START, context), false);
        final ActionReport report = context.getActionReport();

        final DeployCommandParameters commandParams = context.getCommandParameters(DeployCommandParameters.class);

        final String appName = commandParams.name();
        if (commandParams.origin == OpsParams.Origin.deploy && 
            appRegistry.get(appName) != null) {
            report.setMessage(localStrings.getLocalString("appnamenotunique","Application name {0} is already in use. Please pick a different name.", appName));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return null;                
        }

        // if the virtualservers param is not defined, set it to all
        // defined virtual servers minus __asadmin on that target
        if (commandParams.virtualservers == null) {
            commandParams.virtualservers = DeploymentUtils.getVirtualServers(
                commandParams.target, env, domain);
        }
        
        if (commandParams.enabled == null) {
            commandParams.enabled = Boolean.TRUE;
        }

        if (commandParams.altdd != null) {
            context.getSource().addArchiveMetaData(DeploymentProperties.ALT_DD, commandParams.altdd);
        }

        if (commandParams.runtimealtdd != null) {
            context.getSource().addArchiveMetaData(DeploymentProperties.RUNTIME_ALT_DD, commandParams.runtimealtdd);
        }

        ProgressTracker tracker = new ProgressTracker() {
            @Override
            public void actOn(Logger logger) {
                //loaded is used instead of started to include more modules to
                //stop. In some modules, the setup and cleanup steps are not
                //fully symmetric, and to ensure thorough cleanup, we need to
                //call module.stop() for started modules, and modules that are 
                //loaded but may not be started. Issue 18263
                for (EngineRef module : get("loaded", EngineRef.class)) {
                    try {
                        module.stop(context);
                    } catch (Exception e) {
                        // ignore
                    }
                }
                try {
                    PreDestroy.class.cast(context).preDestroy();
                } catch (Exception e) {
                    // ignore
                }                
                for (EngineRef module : get("loaded", EngineRef.class)) {
                    try {
                        module.unload(context);
                    } catch (Exception e) {
                        // ignore
                    }
                }
                try {
                    ApplicationInfo appInfo = appRegistry.get(appName);
                    if (appInfo != null) {
                        // send the event to close necessary resources
                        events.send(new Event(Deployment.APPLICATION_DISABLED, appInfo));
                    }
                } catch (Exception e) {
                    // ignore
                }
                for (EngineRef module : get("prepared", EngineRef.class)) {
                    try {
                        module.clean(context);
                    } catch (Exception e) {
                        // ignore
                    }
                }
                // comment this out for now as the interceptor seems to use 
                // a different hook to roll back failure
                // notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.REPLICATION, context);
                
                if (!commandParams.keepfailedstubs) {
                    try {
                        context.clean();
                    } catch (Exception e) {
                        // ignore
                    }
                }
                appRegistry.remove(appName);

            }
        };

        context.addTransientAppMetaData(ExtendedDeploymentContext.TRACKER, 
            tracker);
        context.setPhase(DeploymentContextImpl.Phase.PREPARE);
        ApplicationInfo appInfo = null;
        try {
            ArchiveHandler handler = context.getArchiveHandler();
            if (handler == null) {
                handler = getArchiveHandler(context.getSource(), 
                    commandParams.type);
                context.setArchiveHandler(handler);
            }

            if (handler==null) {
                report.setMessage(localStrings.getLocalString("unknownarchivetype","Archive type of {0} was not recognized",context.getSourceDir()));
                report.setActionExitCode(ActionReport.ExitCode.FAILURE);
                return null;
            }

            DeploymentTracing tracing = context.getModuleMetaData(DeploymentTracing.class);

            if (tracing!=null) {
                tracing.addMark(DeploymentTracing.Mark.ARCHIVE_HANDLER_OBTAINED);
            }

            if (handler.requiresAnnotationScanning(context.getSource())) {
                getDeployableTypes(context);
            }

            if (tracing!=null) {
                tracing.addMark(DeploymentTracing.Mark.PARSING_DONE);
            }

            // containers that are started are not stopped even if 
            // the deployment fail, the main reason
            // is that some container do not support to be restarted.
            if (sniffers!=null && logger.isLoggable(Level.FINE)) {
                for (Sniffer sniffer : sniffers) {
                    logger.fine("Before Sorting" + sniffer.getModuleType());
                }
            }
 
            sniffers = getSniffers(handler, sniffers, context);

            ClassLoaderHierarchy clh = habitat.getService(ClassLoaderHierarchy.class);
            if (tracing!=null) {
                tracing.addMark(DeploymentTracing.Mark.CLASS_LOADER_HIERARCHY);
            }

            context.createDeploymentClassLoader(clh, handler);
            events.send(new Event(Deployment.AFTER_DEPLOYMENT_CLASSLOADER_CREATION, context), false);
            
            if (tracing!=null) {
                tracing.addMark(DeploymentTracing.Mark.CLASS_LOADER_CREATED);
            }

            final ClassLoader cloader = context.getClassLoader();
            final ClassLoader currentCL = Thread.currentThread().getContextClassLoader();
            try {
                Thread.currentThread().setContextClassLoader(cloader);
                
                List sortedEngineInfos =
                    setupContainerInfos(handler, sniffers, context);
                if (tracing!=null) {
                    tracing.addMark(DeploymentTracing.Mark.CONTAINERS_SETUP_DONE);
                }

                if (logger.isLoggable(Level.FINE)) {
                    for (EngineInfo info : sortedEngineInfos) {
                        logger.fine("After Sorting " + info.getSniffer().getModuleType());
                    }
                }
                if (sortedEngineInfos ==null || sortedEngineInfos.isEmpty()) {
                    report.failure(logger, localStrings.getLocalString("unknowncontainertype","There is no installed container capable of handling this application {0}",context.getSource().getName()));
                    tracker.actOn(logger);
                    return null;
                }


                // create a temporary application info to hold metadata
                // so the metadata could be accessed at classloader 
                // construction time through ApplicationInfo
                ApplicationInfo tempAppInfo = new ApplicationInfo(events, 
                    context.getSource(), appName);
                for (Object m : context.getModuleMetadata()) {
                    tempAppInfo.addMetaData(m);
                }
                tempAppInfo.setIsJavaEEApp(sortedEngineInfos);
                // set the flag on the archive to indicate whether it's 
                // a JavaEE archive or not
                context.getSource().setExtraData(Boolean.class, tempAppInfo.isJavaEEApp());
                appRegistry.add(appName, tempAppInfo);

                try {
                    notifyLifecycleInterceptorsBefore(ExtendedDeploymentContext.Phase.PREPARE, context);
                } catch(Throwable interceptorException) {
                    report.failure(logger, "Exception while invoking the lifecycle interceptor", null);
                    report.setFailureCause(interceptorException);
                    logger.log(Level.SEVERE, KernelLoggerInfo.lifecycleException, interceptorException);
                    tracker.actOn(logger);
                    return null;
                }

                events.send(new Event(Deployment.DEPLOYMENT_BEFORE_CLASSLOADER_CREATION, context), false);

                context.createApplicationClassLoader(clh, handler);
                
                events.send(new Event(Deployment.AFTER_APPLICATION_CLASSLOADER_CREATION, context), false);
                
                if (tracing!=null) {
                    tracing.addMark(DeploymentTracing.Mark.CLASS_LOADER_CREATED);
                }

                    // this is a first time deployment as opposed as load following an unload event,
                    // we need to create the application info
                    // todo : we should come up with a general Composite API solution
                    ModuleInfo moduleInfo = null;
                    try {
                          moduleInfo = prepareModule(sortedEngineInfos, appName, context, tracker);
                          // Now that the prepare phase is done, any artifacts 
                          // should be available.  Go ahead and create the
                          // downloadable client JAR.  We want to do this now, or
                          // at least before the load and start phases, because
                          // (for example) the app client deployer start phase
                          // needs to find all generated files when it runs.
                          final ClientJarWriter cjw = new ClientJarWriter(context);
                          cjw.run();
                    } catch(Throwable prepareException) {
                        prepareException.printStackTrace();
                        report.failure(logger, "Exception while preparing the app", null);
                        report.setFailureCause(prepareException);
                        logger.log(Level.SEVERE, KernelLoggerInfo.lifecycleException, prepareException);
                        tracker.actOn(logger);
                        return null;
                    }

                    // the deployer did not take care of populating the application info, this
                    // is not a composite module.
                    appInfo=context.getModuleMetaData(ApplicationInfo.class);
                    if (appInfo==null) {
                        appInfo = new ApplicationInfo(events, context.getSource(), appName);
                        appInfo.addModule(moduleInfo);

                        for (Object m : context.getModuleMetadata()) {
                            moduleInfo.addMetaData(m);
                            appInfo.addMetaData(m);
                        }
                    } else {
                        for (EngineRef ref : moduleInfo.getEngineRefs()) {
                            appInfo.add(ref);
                        }
                    }

                // remove the temp application info from the registry
                // first, then register the real one
                appRegistry.remove(appName);
                appInfo.setIsJavaEEApp(sortedEngineInfos);
                appRegistry.add(appName, appInfo);

                notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.PREPARE, context);

                if (tracing!=null) {
                    tracing.addMark(DeploymentTracing.Mark.PREPARED);
                }
                
                // send the APPLICATION_PREPARED event
                // set the phase and thread context classloader properly 
                // before sending the event
                context.setPhase(DeploymentContextImpl.Phase.PREPARED);
                Thread.currentThread().setContextClassLoader(context.getClassLoader());
                appInfo.setAppClassLoader(context.getClassLoader());
                events.send(new Event(Deployment.APPLICATION_PREPARED, context), false);

                // now were falling back into the mainstream loading/starting sequence, at this
                // time the containers are set up, all the modules have been prepared in their
                // associated engines and the application info is created and registered
                if (loadOnCurrentInstance(context)) {
                    appInfo.setLibraries(commandParams.libraries());
                    try {
                        notifyLifecycleInterceptorsBefore(ExtendedDeploymentContext.Phase.LOAD, context);
                        appInfo.load(context, tracker);
                        notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.LOAD, context);
                        
                        notifyLifecycleInterceptorsBefore(ExtendedDeploymentContext.Phase.START, context);
                        appInfo.start(context, tracker);
                        notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.START, context);
                    } catch(Throwable loadException) {
                        logger.log(Level.SEVERE, KernelLoggerInfo.lifecycleException, loadException);
                        report.failure(logger, "Exception while loading the app", null);
                        report.setFailureCause(loadException);
                        tracker.actOn(logger);
                        return null;
                    }
                }
                return appInfo;
            } finally {
                context.postDeployClean(false /* not final clean-up yet */);
                Thread.currentThread().setContextClassLoader(currentCL);
            }

        } catch (Throwable e) {
            report.failure(logger, localStrings.getLocalString("error.deploying.app", "Exception while deploying the app [{0}]", appName), null);
            report.setFailureCause(e);
            logger.log(Level.SEVERE, KernelLoggerInfo.lifecycleException, e);
            tracker.actOn(logger);
            return null;
        } finally {
            if (report.getActionExitCode()==ActionReport.ExitCode.SUCCESS) {
                events.send(new Event(Deployment.DEPLOYMENT_SUCCESS, appInfo));
                long operationTime = Calendar.getInstance().getTimeInMillis() - operationStartTime;
                if (appInfo != null) {
                    deploymentLifecycleProbeProvider.applicationDeployedEvent(appName, getApplicationType(appInfo), String.valueOf(operationTime));
                }
            } else {
                events.send(new Event(Deployment.DEPLOYMENT_FAILURE, context));
            }
        }
    }

    @Override
    public Types getDeployableTypes(DeploymentContext context) throws IOException {

        synchronized(context) {
            Types types = context.getTransientAppMetaData(Types.class.getName(), Types.class);
            if (types!=null) {
                return types;
            } else {

                try {
                    // scan the jar and store the result in the deployment context.
                    ParsingContext parsingContext = new ParsingContext.Builder().logger(context.getLogger()).executorService(executorService).build();
                    Parser parser = new Parser(parsingContext);
                    ReadableArchiveScannerAdapter scannerAdapter = new ReadableArchiveScannerAdapter(parser, context.getSource());
                    parser.parse(scannerAdapter, null);
                    for (ReadableArchive externalLibArchive :
                        getExternalLibraries(context)) {
                        ReadableArchiveScannerAdapter libAdapter = null;
                        try {
                            libAdapter = new ReadableArchiveScannerAdapter(parser, externalLibArchive);
                            parser.parse(libAdapter, null);
                        } finally {
                            if (libAdapter!=null) {
                                libAdapter.close();
                            }
                        }
                    }
                    parser.awaitTermination();
                    scannerAdapter.close();
                    context.addTransientAppMetaData(Types.class.getName(), parsingContext.getTypes());
                    context.addTransientAppMetaData(Parser.class.getName(), parser);
                    return parsingContext.getTypes();
                } catch(InterruptedException e) {
                    throw new IOException(e);
                }
            }
        }
    }

    private void notifyLifecycleInterceptorsBefore(final ExtendedDeploymentContext.Phase phase,
            final ExtendedDeploymentContext dc) {
        for (ApplicationLifecycleInterceptor i : alcInterceptors) {
            i.before(phase, dc);
        }
    }
    
    private void notifyLifecycleInterceptorsAfter(final ExtendedDeploymentContext.Phase phase,
            final ExtendedDeploymentContext dc) {
        for (ApplicationLifecycleInterceptor i : alcInterceptors) {
            i.after(phase, dc);
        }
    }
    
    private List getExternalLibraries(
        DeploymentContext context) throws IOException {
        List externalLibArchives = new ArrayList();
        
        String skipScanExternalLibProp = context.getAppProps().getProperty(
                DeploymentProperties.SKIP_SCAN_EXTERNAL_LIB);

        if (Boolean.valueOf(skipScanExternalLibProp)) {
            // if we skip scanning external libraries, we should just 
            // return an empty list here
            return Collections.EMPTY_LIST;
        } 

        List externalLibs = DeploymentUtils.getExternalLibraries(context.getSource());
        for (URI externalLib : externalLibs) {
            externalLibArchives.add(archiveFactory.openArchive(new File(externalLib.getPath())));
        }

        return externalLibArchives;
    }
    
    /**
     * Suspends this application.
     *
     * @param appName the registration application ID
     * @return true if suspending was successful, false otherwise.
     */
    public boolean suspend(String appName) {
        boolean isSuccess = true;

        ApplicationInfo appInfo = appRegistry.get(appName);
        if (appInfo != null) {
            isSuccess = appInfo.suspend(logger);
        }

        return isSuccess;
    }

    /**
     * Resumes this application.
     *
     * @param appName the registration application ID
     * @return true if resumption was successful, false otherwise.
     */
    public boolean resume(String appName) {
        boolean isSuccess = true;

        ApplicationInfo appInfo = appRegistry.get(appName);
        if (appInfo != null) {
            isSuccess = appInfo.resume(logger);
        }

        return isSuccess;
    }

    public List setupContainerInfos(DeploymentContext context)
        throws Exception {
        return setupContainerInfos(context.getArchiveHandler(), getSniffers(context.getArchiveHandler(), null, context), context);
    }

    public Collection getSniffers(final ArchiveHandler handler, Collection sniffers, DeploymentContext context) {
        if (handler == null) {
            return Collections.EMPTY_LIST;
        }

        if (sniffers==null) {
            if (handler instanceof CompositeHandler) {
                ((CompositeHandler)handler).initCompositeMetaData(context);
                context.getAppProps().setProperty(ServerTags.IS_COMPOSITE, "true");
            } 
            sniffers = snifferManager.getSniffers(context);
        }
        context.addTransientAppMetaData(DeploymentProperties.SNIFFERS, sniffers);
        snifferManager.validateSniffers(sniffers, context);

        return sniffers;
    }

    // set up containers and prepare the sorted ModuleInfos
    public List setupContainerInfos(final ArchiveHandler handler,
            Collection sniffers, DeploymentContext context)
             throws Exception {

        final ActionReport report = context.getActionReport();

        DeploymentTracing tracing = context.getModuleMetaData(DeploymentTracing.class);

        Map containerInfosByDeployers = new LinkedHashMap();

        for (Sniffer sniffer : sniffers) {
            if (sniffer.getContainersNames() == null || sniffer.getContainersNames().length == 0) {
                report.failure(logger, "no container associated with application of type : " + sniffer.getModuleType(), null);
                return null;
            }

            final String containerName = sniffer.getContainersNames()[0];
            if (tracing!=null) {
                tracing.addContainerMark(DeploymentTracing.ContainerMark.SNIFFER_DONE, containerName );
            }
            

            // start all the containers associated with sniffers.
            EngineInfo engineInfo = containerRegistry.getContainer(containerName);
            if (engineInfo == null) {
                // need to synchronize on the registry to not end up starting the same container from
                // different threads.
                Collection containersInfo=null;
                synchronized (containerRegistry) {
                    if (containerRegistry.getContainer(containerName) == null) {
                        if (tracing!=null) {
                            tracing.addContainerMark(
                                DeploymentTracing.ContainerMark.BEFORE_CONTAINER_SETUP, containerName );
                        }

                        containersInfo = setupContainer(sniffer, logger, context);
                        if (tracing!=null) {
                            tracing.addContainerMark(
                                DeploymentTracing.ContainerMark.AFTER_CONTAINER_SETUP, containerName );
                        }

                        if (containersInfo == null || containersInfo.size() == 0) {
                            String msg = "Cannot start container(s) associated to application of type : " + sniffer.getModuleType();
                            report.failure(logger, msg, null);
                            throw new Exception(msg);
                        }
                    }
                }

                // now start all containers, by now, they should be all setup...
                if (containersInfo != null && !startContainers(containersInfo, logger, context)) {
                    final String msg = "Aborting, Failed to start container " + containerName;
                    report.failure(logger, msg, null);
                    throw new Exception(msg);
                }
            }
            engineInfo = containerRegistry.getContainer(sniffer.getContainersNames()[0]);
            if (tracing!=null) {
                tracing.addContainerMark(
                    DeploymentTracing.ContainerMark.GOT_CONTAINER, containerName );
            }

            if (engineInfo ==null) {
                final String msg = "Aborting, Failed to start container " + containerName;
                report.failure(logger, msg, null);
                throw new Exception(msg);
            }
             Deployer deployer = getDeployer(engineInfo);
             if (deployer==null) {
                if (!startContainers(Collections.singleton(engineInfo), logger, context)) {
                    final String msg = "Aborting, Failed to start container " + containerName;
                    report.failure(logger, msg, null);
                    throw new Exception(msg);
                }
                deployer = getDeployer(engineInfo);

                if (deployer == null) {
                     report.failure(logger, "Got a null deployer out of the " + engineInfo.getContainer().getClass() + " container, is it annotated with @Service ?");
                     return null;
                }
             }
            if (tracing!=null) {
                tracing.addContainerMark(
                    DeploymentTracing.ContainerMark.GOT_DEPLOYER, containerName );
            }

            containerInfosByDeployers.put(deployer, engineInfo);
        }

        // all containers that have recognized parts of the application being deployed
        // have now been successfully started. Start the deployment process.

        List providers = new LinkedList();
        providers.addAll(habitat.getAllServices(ApplicationMetaDataProvider.class));

        List sortedEngineInfos = new ArrayList();

        Map typeByProvider = new HashMap();
        for (ApplicationMetaDataProvider provider : habitat.getAllServices(ApplicationMetaDataProvider.class)) {
            if (provider.getMetaData()!=null) {
                for (Class provided : provider.getMetaData().provides()) {
                    typeByProvider.put(provided, provider);
                }
            }
        }

        // check if everything is provided.
        for (ApplicationMetaDataProvider provider : habitat.getAllServices(ApplicationMetaDataProvider.class)) {
            if (provider.getMetaData()!=null) {
                 for (Class dependency : provider.getMetaData().requires()) {
                     if (!typeByProvider.containsKey(dependency)) {
                         // at this point, I only log problems, because it maybe that what I am deploying now
                         // will not require this application metadata.
                         logger.log(Level.WARNING, KernelLoggerInfo.applicationMetaDataProvider, 
                                 new Object[] {provider, dependency});
                     }
                 }
            }
        }

        Map typeByDeployer = new HashMap();
        for (Deployer deployer : containerInfosByDeployers.keySet()) {
            if (deployer.getMetaData()!=null) {
                for (Class provided : deployer.getMetaData().provides()) {
                    typeByDeployer.put(provided, deployer);
                }
            }
        }

        for (Deployer deployer : containerInfosByDeployers.keySet()) {
            if (deployer.getMetaData()!=null) {
                for (Class dependency : deployer.getMetaData().requires()) {
                    if (!typeByDeployer.containsKey(dependency) && !typeByProvider.containsKey(dependency)) {

                        Service s = deployer.getClass().getAnnotation(Service.class);
                        String serviceName;
                        if (s!=null && s.name()!=null && s.name().length()>0) {
                            serviceName = s.name();
                        } else {
                            serviceName = deployer.getClass().getSimpleName();
                        }
                        report.failure(logger, serviceName + " deployer requires " + dependency + " but no other deployer provides it", null);
                        return null;
                    }
                }
            }
        }

        // ok everything is satisfied, just a matter of running things in order
        List orderedDeployers = new ArrayList();
        for (Deployer deployer : containerInfosByDeployers.keySet()) {
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("Keyed Deployer " + deployer.getClass());   
            }
            loadDeployer(orderedDeployers, deployer, typeByDeployer, typeByProvider, context);
        }

        // now load metadata from deployers.
        for (Deployer deployer : orderedDeployers) {
            if (logger.isLoggable(Level.FINE)) {
                logger.fine("Ordered Deployer " + deployer.getClass());
            }

            final MetaData metadata = deployer.getMetaData();
            try {
                if (metadata!=null) {
                    if (metadata.provides()==null || metadata.provides().length==0) {
                        deployer.loadMetaData(null, context);
                    } else {
                        for (Class provide : metadata.provides()) {
                            if (context.getModuleMetaData(provide)==null) {
                                context.addModuleMetaData(deployer.loadMetaData(provide, context));
                            } else {
                                deployer.loadMetaData(null, context);
                            }
                        }
                    }
                } else {
                    deployer.loadMetaData(null, context);
                }
            } catch(Exception e) {
                report.failure(logger, "Exception while invoking " + deployer.getClass() + " prepare method", e);
                throw e;
            }
            
            sortedEngineInfos.add(containerInfosByDeployers.get(deployer));
        }

        return sortedEngineInfos;
    }

    private void loadDeployer(List results, Deployer deployer, Map typeByDeployer,  Map typeByProvider, DeploymentContext dc)
        throws IOException {

        if (results.contains(deployer)) {
            return;
        }
        results.add(deployer);
        if (deployer.getMetaData()!=null) {
            for (Class required : deployer.getMetaData().requires()) {
                if (dc.getModuleMetaData(required)!=null) {
                    continue;
                }
                if (typeByDeployer.containsKey(required)) {
                    loadDeployer(results,typeByDeployer.get(required), typeByDeployer, typeByProvider, dc);
                } else {
                    ApplicationMetaDataProvider provider = typeByProvider.get(required);
                    if (provider==null) {
                        logger.log(Level.SEVERE, KernelLoggerInfo.inconsistentLifecycleState, required);
                    } else {
                        LinkedList providers = new LinkedList();

                        addRecursively(providers, typeByProvider, provider);
                        for (ApplicationMetaDataProvider p : providers) {
                            dc.addModuleMetaData(p.load(dc));
                        }
                    }
                }
            }
        }                
    }

    private void addRecursively(LinkedList results, Map providers, ApplicationMetaDataProvider provider) {

        results.addFirst(provider);
        for (Class type : provider.getMetaData().requires()) {
            if (providers.containsKey(type)) {
                addRecursively(results, providers, providers.get(type));
            }
        }

    }

    public ModuleInfo prepareModule(
        List sortedEngineInfos, String moduleName,
        DeploymentContext context,
        ProgressTracker tracker) throws Exception {

        ActionReport report = context.getActionReport();
        List addedEngines = new ArrayList();

        DeploymentTracing tracing = context.getModuleMetaData(DeploymentTracing.class);

        if (tracing!=null) {
            tracing.addModuleMark(DeploymentTracing.ModuleMark.PREPARE,
                        moduleName);
        }

        for (EngineInfo engineInfo : sortedEngineInfos) {

            // get the deployer
            Deployer deployer = engineInfo.getDeployer();

            try {
                if (tracing!=null) {
                    tracing.addContainerMark(DeploymentTracing.ContainerMark.PREPARE,
                                engineInfo.getSniffer().getModuleType() );
                }
                deployer.prepare(context);
                if (tracing!=null) {
                    tracing.addContainerMark(DeploymentTracing.ContainerMark.PREPARED,
                                engineInfo.getSniffer().getModuleType() );
                }


                // construct an incomplete EngineRef which will be later
                // filled in at loading time
                EngineRef engineRef = new EngineRef(engineInfo, null);
                addedEngines.add(engineRef);
                tracker.add("prepared", EngineRef.class, engineRef);

                tracker.add(Deployer.class, deployer);
            } catch(Exception e) {
                report.failure(logger, "Exception while invoking " + deployer.getClass() + " prepare method", e);
                throw e;
            }
        }
        if (tracing!=null) {
            tracing.addModuleMark(DeploymentTracing.ModuleMark.PREPARE_EVENTS, moduleName);
        }
        
        if (events!=null) {
            events.send(new Event(Deployment.MODULE_PREPARED, context), false);
        }
        if (tracing!=null) {
            tracing.addModuleMark(DeploymentTracing.ModuleMark.PREPARED,moduleName);
        }

        // I need to create the application info here from the context, or something like this.
        // and return the application info from this method for automatic registration in the caller.

        // set isComposite property on module props so we know whether to persist 
        // module level properties inside ModuleInfo
        String isComposite = context.getAppProps().getProperty(
            ServerTags.IS_COMPOSITE);
        if (isComposite != null) {
            context.getModuleProps().setProperty(ServerTags.IS_COMPOSITE, isComposite);
        }

        ModuleInfo mi = new ModuleInfo(events, moduleName, addedEngines,
            context.getModuleProps());

        /*
         * Save the application config that is potentially attached to each
         * engine in the corresponding EngineRefs that have already created.
         * 
         * Later, in registerAppInDomainXML, the appInfo is saved, which in
         * turn saves the moduleInfo children and their engineRef children.
         * Saving the engineRef assigns the application config to the Engine
         * which corresponds directly to the  element in the XML.
         * A long way to get this done.
         */

//        Application existingApp = applications.getModule(Application.class, moduleName);
//        if (existingApp != null) {
            ApplicationConfigInfo savedAppConfig = new ApplicationConfigInfo(context.getAppProps());
            for (EngineRef er : mi.getEngineRefs()) {
               ApplicationConfig c = savedAppConfig.get(mi.getName(),
                       er.getContainerInfo().getSniffer().getModuleType());
               if (c != null) {
                   er.setApplicationConfig(c);
               }
            }
//        }
        return mi;
    }

    protected Collection setupContainer(Sniffer sniffer, Logger logger, DeploymentContext context) {
        ActionReport report = context.getActionReport();
        ContainerStarter starter = habitat.getService(ContainerStarter.class);
        Collection containersInfo = starter.startContainer(sniffer);
        if (containersInfo == null || containersInfo.size()==0) {
            report.failure(logger, "Cannot start container(s) associated to application of type : " + sniffer.getModuleType(), null);
            return null;
        }
        return containersInfo;
    }

    protected boolean startContainers(Collection containersInfo, Logger logger, DeploymentContext context) {
    	
    	ActionReport report = context.getActionReport();
        for (EngineInfo engineInfo : containersInfo) {
            Container container;
            try {
                container = engineInfo.getContainer();
            } catch(Exception e) {
                logger.log(Level.SEVERE, KernelLoggerInfo.cantStartContainer, 
                        new Object[] {engineInfo.getSniffer().getModuleType(), e});
                return false;
            }
                
            Class deployerClass = container.getDeployer();
            Deployer deployer;
            try {
                    deployer = habitat.getService(deployerClass);
                    engineInfo.setDeployer(deployer);
            } catch (MultiException e) {
                report.failure(logger, "Cannot instantiate or inject "+deployerClass, e);
                engineInfo.stop(logger);
                return false;
            } catch (ClassCastException e) {
                engineInfo.stop(logger);
                report.failure(logger, deployerClass+" does not implement " +
                                    " the org.jvnet.glassfish.api.deployment.Deployer interface", e);
                return false;
            }
        }
        return true;
    }

    protected void stopContainers(EngineInfo[] ctrInfos, Logger logger) {
        for (EngineInfo ctrInfo : ctrInfos) {
            try {
                ctrInfo.stop(logger);
            } catch(Exception e) {
                // this is not a failure per se but we need to document it.
                logger.log(Level.INFO, KernelLoggerInfo.cantReleaseContainer,
                        new Object[] {ctrInfo.getSniffer().getModuleType(), e});
            }
        }
    }

    public ApplicationInfo unload(ApplicationInfo info, ExtendedDeploymentContext context) {
        ActionReport report = context.getActionReport();
        if (info==null) {
            report.failure(context.getLogger(), "Application not registered", null);
            return null;
        }

        notifyLifecycleInterceptorsBefore(ExtendedDeploymentContext.Phase.STOP, context);

        if (info.isLoaded()) {
            info.stop(context, context.getLogger());
            notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.STOP, context);
            
            notifyLifecycleInterceptorsBefore(ExtendedDeploymentContext.Phase.UNLOAD, context);
            info.unload(context);
            notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.UNLOAD, context);
        }

        events.send(new Event(Deployment.APPLICATION_DISABLED, info), false);

        try {
            notifyLifecycleInterceptorsBefore(ExtendedDeploymentContext.Phase.CLEAN, context);
            info.clean(context);
            notifyLifecycleInterceptorsAfter(ExtendedDeploymentContext.Phase.CLEAN, context);
        } catch(Exception e) {
            report.failure(context.getLogger(), "Exception while cleaning", e);
            return info;
        }

        return info;
    }

    public void undeploy(String appName, ExtendedDeploymentContext context) {

        ActionReport report = context.getActionReport();
        UndeployCommandParameters params = context.getCommandParameters(UndeployCommandParameters.class);

        ApplicationInfo info = appRegistry.get(appName);
        if (info==null) {
            report.failure(context.getLogger(), "Application " + appName + " not registered", null);
            events.send(new Event(Deployment.UNDEPLOYMENT_FAILURE, context));
            return;

        }

        events.send(new Event(Deployment.UNDEPLOYMENT_START, info));

        // we unconditionally unload the application, even if it is not loaded, because we must clean the
        // application, especially the classloaders need to be closed to release file handles
        unload(info, context);

        
        if (report != null && report.getActionExitCode().equals(ActionReport.ExitCode.SUCCESS)) {
            events.send(new Event(Deployment.UNDEPLOYMENT_SUCCESS, context));
            deploymentLifecycleProbeProvider.applicationUndeployedEvent(appName, getApplicationType(info));
        } else {            
            events.send(new Event(Deployment.UNDEPLOYMENT_FAILURE, context));            
        }
        
        appRegistry.remove(appName);
    }

    // prepare application config change for later registering
    // in the domain.xml
    public Transaction prepareAppConfigChanges(final DeploymentContext context)
        throws TransactionFailure {
        final Properties appProps = context.getAppProps();
        final DeployCommandParameters deployParams = context.getCommandParameters(DeployCommandParameters.class);
        Transaction t = new Transaction();

        try {
            // prepare the application element
            ConfigBean newBean = ((ConfigBean)ConfigBean.unwrap(applications)).allocate(Application.class);
            Application app = newBean.createProxy();
            Application app_w = t.enroll(app);
            setInitialAppAttributes(app_w, deployParams, appProps, context);
            context.addTransientAppMetaData(ServerTags.APPLICATION, app_w);
        } catch(TransactionFailure e) {
            t.rollback();
            throw e;
        } catch (Exception e) {
            t.rollback();
            throw new TransactionFailure(e.getMessage(), e);
        }

        return t;
    }

    // register application information in domain.xml
    public void registerAppInDomainXML(final ApplicationInfo
        applicationInfo, final DeploymentContext context, Transaction t) 
        throws TransactionFailure {
        registerAppInDomainXML(applicationInfo, context, t, false);
    }

    // register application information in domain.xml
    public void registerAppInDomainXML(final ApplicationInfo
        applicationInfo, final DeploymentContext context, Transaction t, 
        boolean appRefOnly)
        throws TransactionFailure {
        final Properties appProps = context.getAppProps();
        final DeployCommandParameters deployParams = context.getCommandParameters(DeployCommandParameters.class);
        if (t != null) {
            try {
                if (!appRefOnly) {
                    Application app_w = context.getTransientAppMetaData(
                        ServerTags.APPLICATION, Application.class);
                    // adding the application element
                    setRestAppAttributes(app_w, appProps);
                    Applications apps_w = t.enroll(applications);
                    apps_w.getModules().add(app_w);
                    if (applicationInfo != null) {
                        applicationInfo.save(app_w);
                    }
                }

                List targets = new ArrayList();
                if (!DeploymentUtils.isDomainTarget(deployParams.target)) {
                    targets.add(deployParams.target);    
                } else {
                    List previousTargets = context.getTransientAppMetaData(DeploymentProperties.PREVIOUS_TARGETS, List.class);
		    if (previousTargets == null) {
                        previousTargets = domain.getAllReferencedTargetsForApplication(deployParams.name);
                    }
                    targets = previousTargets;
                }

                String origVS = deployParams.virtualservers;
                Boolean origEnabled = deployParams.enabled;
		Properties previousVirtualServers = context.getTransientAppMetaData(DeploymentProperties.PREVIOUS_VIRTUAL_SERVERS, Properties.class);
		Properties previousEnabledAttributes = context.getTransientAppMetaData(DeploymentProperties.PREVIOUS_ENABLED_ATTRIBUTES, Properties.class);
                for (String target : targets) {
                    // first reset the virtualservers, enabled attribute
                    deployParams.virtualservers = origVS;
                    deployParams.enabled = origEnabled;
                    // now if the target is domain target, 
                    // restore the previous attributes if 
                    // applicable
                    if (DeploymentUtils.isDomainTarget(deployParams.target)) {
                        String vs = previousVirtualServers.getProperty(target);
                        if (vs != null) {
                            deployParams.virtualservers = vs;
                        }
                        String enabledAttr = previousEnabledAttributes.getProperty(target);
                        if (enabledAttr != null) {
                            deployParams.enabled = Boolean.valueOf(enabledAttr);
                        }
                    }
                    if (deployParams.enabled == null) {
                        deployParams.enabled = Boolean.TRUE;
                    }
                    Server servr = domain.getServerNamed(target); 
                    if (servr != null) {
                        // adding the application-ref element to the standalone
                        // server instance
                        ConfigBeanProxy servr_w = t.enroll(servr);
                        // adding the application-ref element to the standalone
                        // server instance
                        ApplicationRef appRef = servr_w.createChild(ApplicationRef.class);
                        setAppRefAttributes(appRef, deployParams);
                        ((Server)servr_w).getApplicationRef().add(appRef);
                    }

                    Cluster cluster = domain.getClusterNamed(target); 
                    if (cluster != null) {
                        // adding the application-ref element to the cluster
                        // and instances
                        ConfigBeanProxy cluster_w = t.enroll(cluster);
                        ApplicationRef appRef = cluster_w.createChild(ApplicationRef.class);
                        setAppRefAttributes(appRef, deployParams);
                        ((Cluster)cluster_w).getApplicationRef().add(appRef);

                        for (Server svr : cluster.getInstances() ) {
                            ConfigBeanProxy svr_w = t.enroll(svr);
                            ApplicationRef appRef2 = svr_w.createChild(ApplicationRef.class);
                            setAppRefAttributes(appRef2, deployParams);
                            ((Server)svr_w).getApplicationRef().add(appRef2);
                        }
                    }
                }
            } catch(TransactionFailure e) {
                t.rollback();
                throw e;
            } catch (Exception e) {
                t.rollback();
                throw new TransactionFailure(e.getMessage(), e);
            }

            try {
                t.commit();
            } catch (RetryableException e) {
                System.out.println("Retryable...");
                // TODO : do something meaninful here
                t.rollback();
            } catch (TransactionFailure e) {
                t.rollback();
                throw e;
            }
        }
    }

    public void registerTenantWithAppInDomainXML(
            final String appName,
            final ExtendedDeploymentContext context) throws TransactionFailure {

        final Transaction t = new Transaction();
        try {
            final AppTenant appTenant_w = writeableTenantForApp(
                    appName,
                    t);
            appTenant_w.setContextRoot(context.getAppProps().getProperty(ServerTags.CONTEXT_ROOT));
            appTenant_w.setTenant(context.getTenant());

            t.commit();
        } catch (TransactionFailure ex) {
            t.rollback();
            throw ex;
        } catch (Throwable ex) {
            t.rollback();
            throw new TransactionFailure(ex.getLocalizedMessage(), ex);
        }
    }

    public void unregisterTenantWithAppInDomainXML(
            final String appName,
            final String tenantName
            ) throws TransactionFailure, RetryableException {
        final com.sun.enterprise.config.serverbeans.Application app =
                applications.getApplication(appName);
        if (app == null) {
            throw new IllegalArgumentException("Application " + appName + " not found");
        }
        final AppTenants appTenants = app.getAppTenants();
        final AppTenant appTenant = appTenants.getAppTenant(tenantName);
        if (appTenant == null) {
            throw new IllegalArgumentException("Tenant " + tenantName + " not provisioned for application " + appName);
        }
        Transaction t = new Transaction();
        final AppTenants appTenants_w = t.enroll(appTenants);
        appTenants_w.getAppTenant().remove(appTenant);
        t.commit();
    }

    private AppTenant writeableTenantForApp(
            final String appName,
            final Transaction t) throws TransactionFailure, PropertyVetoException {
        final com.sun.enterprise.config.serverbeans.Application app =
                applications.getApplication(appName);
        if (app == null) {
            throw new IllegalArgumentException("Application " + appName + " not found");
        }

        /*
         * The app-tenants subelement might or might not already be there.
         */
        AppTenants appTenants = app.getAppTenants();
        AppTenants appTenants_w;
        if (appTenants == null) {
            com.sun.enterprise.config.serverbeans.Application app_w =
                    t.enroll(app);
            appTenants_w = app_w.createChild(AppTenants.class);
            app_w.setAppTenants(appTenants_w);
        } else {
            appTenants_w = t.enroll(appTenants);
       }

        final List appTenantList = appTenants_w.getAppTenant();
        AppTenant appTenant_w = appTenants_w.createChild(AppTenant.class);
        appTenantList.add(appTenant_w);
        return appTenant_w;
    }

    // application attributes that are set in the beginning of the deployment
    // that will not be changed in the course of the deployment
    private void setInitialAppAttributes(Application app, 
        DeployCommandParameters deployParams, Properties appProps, 
        DeploymentContext context)
        throws PropertyVetoException {
        Properties previousEnabledAttributes = context.getTransientAppMetaData(DeploymentProperties.PREVIOUS_ENABLED_ATTRIBUTES, Properties.class);
        // various attributes
        app.setName(deployParams.name);
        if (deployParams.libraries != null) {
            app.setLibraries(deployParams.libraries);
        }
        if (deployParams.description != null) {
            app.setDescription(deployParams.description);
        }
        if (deployParams.deploymentorder != null) {
            app.setDeploymentOrder(deployParams.deploymentorder.toString());
        }

        app.setEnabled(String.valueOf(true));
        if (appProps.getProperty(ServerTags.LOCATION) != null) {
                    app.setLocation(appProps.getProperty(
                ServerTags.LOCATION));
            // when redeploy to domain we preserve the enable
            // attribute
            if (DeploymentUtils.isDomainTarget(deployParams.target)) {
                if (previousEnabledAttributes != null) {
                    String enabledAttr = previousEnabledAttributes.getProperty(DeploymentUtils.DOMAIN_TARGET_NAME);
                    if (enabledAttr != null) {
                        app.setEnabled(enabledAttr);
                    }
                }
            }
            app.setAvailabilityEnabled(deployParams.availabilityenabled.toString());
            app.setAsyncReplication(deployParams.asyncreplication.toString());
        }
        if (appProps.getProperty(ServerTags.OBJECT_TYPE) != null) {
            app.setObjectType(appProps.getProperty(
                ServerTags.OBJECT_TYPE));
        }
        if (appProps.getProperty(ServerTags.DIRECTORY_DEPLOYED) 
            != null) {
            app.setDirectoryDeployed(appProps.getProperty(
                ServerTags.DIRECTORY_DEPLOYED));
        }
    }


    // set the rest of the application attributes at the end of the
    // deployment
    private void setRestAppAttributes(Application app, Properties appProps)
        throws PropertyVetoException, TransactionFailure {
        // context-root element
        if (appProps.getProperty(ServerTags.CONTEXT_ROOT) != null) {
            app.setContextRoot(appProps.getProperty(
                ServerTags.CONTEXT_ROOT));
        }
        // property element
        // trim the properties that have been written as attributes
        // the rest properties will be written as property element
        for (Iterator itr = appProps.keySet().iterator();
            itr.hasNext();) {
            String propName = (String) itr.next();
            if (!propName.equals(ServerTags.LOCATION) &&
                !propName.equals(ServerTags.CONTEXT_ROOT) &&
                !propName.equals(ServerTags.OBJECT_TYPE) &&
                !propName.equals(ServerTags.DIRECTORY_DEPLOYED) &&
                !propName.startsWith(
                    DeploymentProperties.APP_CONFIG))
                    {
                if (appProps.getProperty(propName) != null) {
                    Property prop = app.createChild(Property.class);
                    app.getProperty().add(prop);
                    prop.setName(propName);
                    prop.setValue(appProps.getProperty(propName));
                }
            }
        }
    }

    public void unregisterAppFromDomainXML(final String appName,
        final String target) throws TransactionFailure {
        unregisterAppFromDomainXML(appName, target, false);
    }

    public void unregisterAppFromDomainXML(final String appName, 
        final String tgt, final boolean appRefOnly) 
        throws TransactionFailure {
        ConfigSupport.apply(new SingleConfigCode() {
            public Object run(ConfigBeanProxy param) throws PropertyVetoException, TransactionFailure {
                // get the transaction
                Transaction t = Transaction.getTransaction(param);
                if (t!=null) {
                    List targets = new ArrayList();
                    if (!DeploymentUtils.isDomainTarget(tgt)) {
                        targets.add(tgt);    
                    } else {
                        targets = domain.getAllReferencedTargetsForApplication(appName);
                    }

                    Domain dmn;
                    if (param instanceof Domain) {
                        dmn = (Domain)param;
                    } else {
                        return Boolean.FALSE;
                    }

                    for (String target : targets) {
                        Server servr = dmn.getServerNamed(target);
                        if (servr != null) {
                            // remove the application-ref from standalone 
                            // server instance
                            ConfigBeanProxy servr_w = t.enroll(servr);
                            for (ApplicationRef appRef : 
                                servr.getApplicationRef()) {
                                if (appRef.getRef().equals(appName)) {
                                    ((Server)servr_w).getApplicationRef().remove(
                                        appRef);
                                    break;
                                }
                            }
                        }
              
                        Cluster cluster = dmn.getClusterNamed(target);
                        if (cluster != null) {
                            // remove the application-ref from cluster
                            ConfigBeanProxy cluster_w = t.enroll(cluster);
                            for (ApplicationRef appRef : 
                                cluster.getApplicationRef()) {
                                if (appRef.getRef().equals(appName)) {
                                    ((Cluster)cluster_w).getApplicationRef().remove(
                                            appRef);
                                        break;
                                }
                            }

                            // remove the application-ref from cluster instances
                            for (Server svr : cluster.getInstances() ) {
                                ConfigBeanProxy svr_w = t.enroll(svr);
                                for (ApplicationRef appRef : 
                                    svr.getApplicationRef()) {
                                    if (appRef.getRef().equals(appName)) {
                                        ((Server)svr_w).getApplicationRef(
                                           ).remove(appRef);
                                        break;
                                    }
                                }
                            }
                        }
                    }

                    if (!appRefOnly) {
                        // remove application element
                        Applications apps = dmn.getApplications();
                        ConfigBeanProxy apps_w = t.enroll(apps);
                        for (ApplicationName module : apps.getModules()) {
                            if (module.getName().equals(appName)) {
                                ((Applications)apps_w).getModules().remove(module);
                                break;
                            }
                        }
                    }
                }
                return Boolean.TRUE;
            }
        }, domain);
    }


    public void updateAppEnabledAttributeInDomainXML(final String appName,
        final String target, final boolean enabled) throws TransactionFailure {
        ConfigSupport.apply(new SingleConfigCode() {
            public Object run(ConfigBeanProxy param) throws PropertyVetoException, TransactionFailure {
                // get the transaction
                Transaction t = Transaction.getTransaction(param);
                if (t!=null) {
                    Domain dmn;
                    if (param instanceof Domain) {
                        dmn = (Domain)param;
                    } else {
                        return Boolean.FALSE;
                    }

                    if (enabled || DeploymentUtils.isDomainTarget(target)) {
                        Application app = dmn.getApplications().getApplication(appName);
                        ConfigBeanProxy app_w = t.enroll(app);
                       ((Application)app_w).setEnabled(String.valueOf(enabled));

                    }

                    List targets = new ArrayList();
                    if (!DeploymentUtils.isDomainTarget(target)) {
                        targets.add(target);
                    } else {
                        targets = domain.getAllReferencedTargetsForApplication(appName);
                    }

                    for (String target : targets) {
                        Server servr = dmn.getServerNamed(target);
                        if (servr != null) {
                            // update the application-ref from standalone
                            // server instance
                            for (ApplicationRef appRef :
                                servr.getApplicationRef()) {
                                if (appRef.getRef().equals(appName)) {
                                    ConfigBeanProxy appRef_w = t.enroll(appRef);
                                    ((ApplicationRef)appRef_w).setEnabled(String.valueOf(enabled));
                                    break;
                                }
                            }
                            updateClusterAppRefWithInstanceUpdate(t, servr, appName, enabled);
                        }
                        Cluster cluster = dmn.getClusterNamed(target);
                        if (cluster != null) {
                            // update the application-ref from cluster
                            for (ApplicationRef appRef :
                                cluster.getApplicationRef()) {
                                if (appRef.getRef().equals(appName)) {
                                    ConfigBeanProxy appRef_w = t.enroll(appRef);
                                    ((ApplicationRef)appRef_w).setEnabled(String.valueOf(enabled));
                                    break;
                                }
                            }

                            // update the application-ref from cluster instances
                            for (Server svr : cluster.getInstances() ) {
                                for (ApplicationRef appRef :
                                    svr.getApplicationRef()) {
                                    if (appRef.getRef().equals(appName)) {
                                        ConfigBeanProxy appRef_w = t.enroll(appRef);
                                        ((ApplicationRef)appRef_w).setEnabled(String.valueOf(enabled));
                                        break;
                                    }
                                }
                            }
                        }
                    }
             }
             return Boolean.TRUE;
            }
        }, domain);
    }

    // check if the application is registered in domain.xml
    public boolean isRegistered(String appName) {
        return applications.getApplication(appName)!=null;
    }

    public ApplicationInfo get(String appName) {
        return appRegistry.get(appName);
    }

    private boolean isPaaSEnabled(Boolean isClassicStyle) {
        if (isClassicStyle) {
            return false;
        } 
 
        if (virtEnv != null && virtEnv.isPaasEnabled()) {
            return true;
        }

        return false;
    }

    // gets the default target when no target is specified for non-paas case
    public String getDefaultTarget(Boolean isClassicStyle) {
        if (!isPaaSEnabled(isClassicStyle)) {
            return DeploymentUtils.DAS_TARGET_NAME;     
        }
        return null;
    }

    // gets the default target when no target is specified
    public String getDefaultTarget(String appName, OpsParams.Origin origin, Boolean isClassicStyle) {
        if (!isPaaSEnabled(isClassicStyle)) {
            return DeploymentUtils.DAS_TARGET_NAME;     
        } else {
           // for deploy case, OE will set the deploy target later
           if (origin == OpsParams.Origin.deploy) {
              return null;
           }
           // for other cases, we try to derive it from domain.xml
           List targets = 
               domain.getAllReferencedTargetsForApplication(appName); 
           if (targets.size() == 0) {
               throw new IllegalArgumentException("Application not registered");
           }
           if (targets.size() > 1) {
               throw new IllegalArgumentException("Cannot determine the default target. Please specify an explicit target for the operation.");
           }
           return targets.get(0);
        }
    }

    public class DeploymentContextBuidlerImpl implements DeploymentContextBuilder {
        private final Logger logger;
        private final ActionReport report;
        private final OpsParams params;
        private File sFile;
        private ReadableArchive sArchive;
        private ArchiveHandler handler;

        public DeploymentContextBuidlerImpl(Logger logger, OpsParams params, ActionReport report) {
            this.logger = logger;
            this.report = report;
            this.params = params;
        }

        public DeploymentContextBuidlerImpl(DeploymentContextBuilder b) throws IOException {
            this.logger = b.logger();
            this.report = b.report();
            this.params = b.params();
            ReadableArchive archive = getArchive(b);
            source(archive);
            handler = b.archiveHandler();
        }

        public DeploymentContextBuilder source(File source) {
            this.sFile = source;
            return this;
        }

        public File sourceAsFile() {
            return sFile;
        }
        public ReadableArchive sourceAsArchive() {
            return sArchive;
        }

        public ArchiveHandler archiveHandler() {
            return handler;
        }

        public DeploymentContextBuilder source(ReadableArchive archive) {
            this.sArchive = archive;
            return this;
        }

        public DeploymentContextBuilder archiveHandler(ArchiveHandler handler) {
            this.handler = handler;
            return this;
        }

        public ExtendedDeploymentContext build() throws IOException {
            return build(null);
        }
        public Logger logger() { return logger; };
        public ActionReport report() { return report; };
        public OpsParams params() { return params; };

        public ExtendedDeploymentContext build(ExtendedDeploymentContext initialContext) throws IOException {
            return ApplicationLifecycle.this.getContext(initialContext, this);
        }
    }

    public DeploymentContextBuilder getBuilder(Logger logger, OpsParams params, ActionReport report) {
        return new DeploymentContextBuidlerImpl(logger, params, report);
    }

    /**
     * Updates the "enabled" setting of the cluster's app ref for the
     * given app if a change to the "enabled" setting of the app ref on one of 
     * the cluster's instances implies a cluster-level change.
     * 

* If the app is enabled on any single instance in a cluster * then the cluster state needs to be enabled. If * the app is disabled on all instances in the cluster * then the cluster state should be disabled. This method makes sure the * cluster-level app ref enabled state is correct, given the current values * of the app refs on the cluster's instances combined with the new value * for the specified instance. * * @param t current config Transaction in progress * @param servr the Server for which the app ref has been enabled or disabled * @param appName the name of the app whose app ref has been enabled or disabled * @param isNewInstanceAppRefStateEnabled whether the new instance app ref state is enabled (false if disabled) */ private void updateClusterAppRefWithInstanceUpdate( final Transaction t, final Server servr, final String appName, final boolean isNewInstanceAppRefStateEnabled) throws TransactionFailure, PropertyVetoException { final Cluster clusterContainingInstance = servr.getCluster(); if (clusterContainingInstance != null) { /* * Update the cluster state also if needed. */ boolean isAppRefEnabledOnAnyClusterInstance = false; for (Server inst : clusterContainingInstance.getInstances()) { /* * The app ref for the server just changed above * still has its old state when fetched using * inst.getApplicationRef(appName). So when we * encounter the same server in the list of * cluster instances, use the "enabled" value -- * which we just used above to update the app ref * for the targeted instance -- below when * we need to consider the "enabled" value for the * just-changed instance. */ isAppRefEnabledOnAnyClusterInstance |= ( servr.getName().equals(inst.getName()) ? isNewInstanceAppRefStateEnabled : Boolean.parseBoolean(inst.getApplicationRef(appName).getEnabled())); } final ApplicationRef clusterAppRef = clusterContainingInstance.getApplicationRef(appName); if (Boolean.parseBoolean(clusterAppRef.getEnabled()) != isAppRefEnabledOnAnyClusterInstance) { t.enroll(clusterAppRef).setEnabled(String.valueOf(isAppRefEnabledOnAnyClusterInstance)); } } } // cannot put it on the builder itself since the builder is an official API. private ReadableArchive getArchive(DeploymentContextBuilder builder) throws IOException { ReadableArchive archive = builder.sourceAsArchive(); if (archive==null && builder.sourceAsFile()==null) { throw new IOException("Source archive or file not provided to builder"); } if (archive==null && builder.sourceAsFile()!=null) { archive = habitat.getService(ArchiveFactory.class).openArchive(builder.sourceAsFile()); if (archive==null) { throw new IOException("Invalid archive type : " + builder.sourceAsFile().getAbsolutePath()); } } return archive; } private ExtendedDeploymentContext getContext(ExtendedDeploymentContext initial, DeploymentContextBuilder builder) throws IOException { DeploymentContextBuilder copy = new DeploymentContextBuidlerImpl(builder); ReadableArchive archive = getArchive(copy); copy.source(archive); if (initial==null) { initial = new DeploymentContextImpl(copy, env); } ArchiveHandler archiveHandler = copy.archiveHandler(); if (archiveHandler == null) { String type = null; OpsParams params = builder.params(); if (params != null) { if (params instanceof DeployCommandParameters) { type = ((DeployCommandParameters)params).type; } else if (params instanceof UndeployCommandParameters) { type = ((UndeployCommandParameters)params)._type; } } archiveHandler = getArchiveHandler(archive, type); } // this is needed for autoundeploy to find the application // with the archive name File sourceFile = new File(archive.getURI().getSchemeSpecificPart()); initial.getAppProps().put(ServerTags.DEFAULT_APP_NAME, DeploymentUtils.getDefaultEEName(sourceFile.getName())); if (!(sourceFile.isDirectory())) { String repositoryBitName = copy.params().name(); try { repositoryBitName = VersioningUtils.getRepositoryName(repositoryBitName); } catch (VersioningSyntaxException e) { ActionReport report = copy.report(); report.setMessage(e.getMessage()); report.setActionExitCode(ActionReport.ExitCode.FAILURE); } // create a temporary deployment context File expansionDir = new File(domain.getApplicationRoot(), repositoryBitName); if (!expansionDir.mkdirs()) { /* * On Windows especially a previous directory might have * remainded after an earlier undeployment, for example if * a JAR file in the earlier deployment had been locked. * Warn but do not fail in such a case. */ logger.fine(localStrings.getLocalString("deploy.cannotcreateexpansiondir", "Error while creating directory for jar expansion: {0}",expansionDir)); } try { Long start = System.currentTimeMillis(); final WritableArchive expandedArchive = archiveFactory.createArchive(expansionDir); archiveHandler.expand(archive, expandedArchive, initial); if (logger.isLoggable(Level.FINE)) { logger.fine("Deployment expansion took " + (System.currentTimeMillis() - start)); } // Close the JAR archive before losing the reference to it or else the JAR remains locked. try { archive.close(); } catch(IOException e) { logger.log(Level.SEVERE, KernelLoggerInfo.errorClosingArtifact, new Object[] { archive.getURI().getSchemeSpecificPart(), e}); throw e; } archive = (FileArchive) expandedArchive; initial.setSource(archive); } catch(IOException e) { logger.log(Level.SEVERE, KernelLoggerInfo.errorExpandingFile, e); throw e; } } initial.setArchiveHandler(archiveHandler); return initial; } private void setAppRefAttributes(ApplicationRef appRef, DeployCommandParameters deployParams) throws PropertyVetoException { appRef.setRef(deployParams.name); if (deployParams.virtualservers != null) { appRef.setVirtualServers(deployParams.virtualservers); } else { // deploy to all virtual-servers, we need to get the list. appRef.setVirtualServers(DeploymentUtils.getVirtualServers(deployParams.target, env, domain)); } if(deployParams.lbenabled != null){ appRef.setLbEnabled(deployParams.lbenabled); } else { //check if system property exists and use that String lbEnabledDefault = System.getProperty(Server.lbEnabledSystemProperty); if (lbEnabledDefault != null) { appRef.setLbEnabled(lbEnabledDefault); } } appRef.setEnabled(deployParams.enabled.toString()); } public ParameterMap prepareInstanceDeployParamMap(DeploymentContext dc) throws Exception { final DeployCommandParameters params = dc.getCommandParameters(DeployCommandParameters.class); final Collection excludedParams = new ArrayList(); excludedParams.add(DeploymentProperties.PATH); excludedParams.add(DeploymentProperties.DEPLOYMENT_PLAN); excludedParams.add(DeploymentProperties.ALT_DD); excludedParams.add(DeploymentProperties.RUNTIME_ALT_DD); excludedParams.add(DeploymentProperties.UPLOAD); // We'll force it to true ourselves. final ParameterMap paramMap; final ParameterMapExtractor extractor = new ParameterMapExtractor(params); paramMap = extractor.extract(excludedParams); prepareGeneratedContent(dc, paramMap); // set the path and plan params // get the location properties from the application so the token // will be resolved Application application = applications.getApplication(params.name); Properties appProperties = application.getDeployProperties(); String archiveLocation = appProperties.getProperty(Application.APP_LOCATION_PROP_NAME); final File archiveFile = new File(new URI(archiveLocation)); paramMap.set("DEFAULT", archiveFile.getAbsolutePath()); String planLocation = appProperties.getProperty(Application.DEPLOYMENT_PLAN_LOCATION_PROP_NAME); if (planLocation != null) { final File actualPlan = new File(new URI(planLocation)); paramMap.set(DeployCommandParameters.ParameterNames.DEPLOYMENT_PLAN, actualPlan.getAbsolutePath()); } String altDDLocation = appProperties.getProperty(Application.ALT_DD_LOCATION_PROP_NAME); if (altDDLocation != null) { final File altDD = new File(new URI(altDDLocation)); paramMap.set(DeployCommandParameters.ParameterNames.ALT_DD, altDD.getAbsolutePath()); } String runtimeAltDDLocation = appProperties.getProperty(Application.RUNTIME_ALT_DD_LOCATION_PROP_NAME); if (runtimeAltDDLocation != null) { final File runtimeAltDD = new File(new URI(runtimeAltDDLocation)); paramMap.set(DeployCommandParameters.ParameterNames.RUNTIME_ALT_DD, runtimeAltDD.getAbsolutePath()); } // always upload the archives to the instance side // but not directories. Note that we prepare a zip file containing // the generated directories and pass that as a single parameter so it // will be uploaded even though a deployment directory is not. paramMap.set(DeploymentProperties.UPLOAD, "true"); // pass the params we restored from the previous deployment in case of // redeployment if (params.previousContextRoot != null) { paramMap.set(DeploymentProperties.PRESERVED_CONTEXT_ROOT, params.previousContextRoot); } // pass the app props so we have the information to persist in the // domain.xml Properties appProps = dc.getAppProps(); appProps.remove(DeploymentProperties.APP_CONFIG); paramMap.set(DeploymentProperties.APP_PROPS, extractor.propertiesValue(appProps, ':')); Properties previousVirtualServers = dc.getTransientAppMetaData(DeploymentProperties.PREVIOUS_VIRTUAL_SERVERS, Properties.class); if (previousVirtualServers != null) { paramMap.set(DeploymentProperties.PREVIOUS_VIRTUAL_SERVERS, extractor.propertiesValue(previousVirtualServers, ':')); } Properties previousEnabledAttributes = dc.getTransientAppMetaData(DeploymentProperties.PREVIOUS_ENABLED_ATTRIBUTES, Properties.class); if (previousEnabledAttributes != null) { paramMap.set(DeploymentProperties.PREVIOUS_ENABLED_ATTRIBUTES, extractor.propertiesValue(previousEnabledAttributes, ':')); } return paramMap; } private void prepareGeneratedContent(final DeploymentContext dc, final ParameterMap paramMap) throws IOException { /* * Create a single ZIP file containing the various generated * directories for this app. * * Note that some deployments - such as of OSGI modules - might not * create any generated content. */ final File generatedContentZip = createGeneratedContentZip(); ZipOutputStream zipOS = null; /* * We want the ZIP file to contain xml/(appname), ejb/(appname), etc. * directories, even if those directories don't contain anything. * Then the instance deploy command can expand the uploaded zip file * based at the instance's generated/ directory and the files - including * empty directories if appropriate - will be stored in the right places. */ final File baseDir = dc.getScratchDir("xml").getParentFile().getParentFile(); for (String scratchType : UPLOADED_GENERATED_DIRS) { zipOS = addScratchContentIfPresent(dc, baseDir, zipOS, generatedContentZip, scratchType); } if (zipOS != null) { /* * Because we did zip up some generated content, add the just-generated * zip file as a parameter to the param map. */ zipOS.close(); // set the generated content param paramMap.set("generatedcontent", generatedContentZip.getAbsolutePath()); } } private File createGeneratedContentZip() throws IOException { final File tempFile = File.createTempFile("gendContent", ".zip"); tempFile.deleteOnExit(); return tempFile; } private ZipOutputStream addScratchContentIfPresent(final DeploymentContext dc, final File baseDir, ZipOutputStream zipOS, final File generatedContentZip, final String scratchDirName) throws IOException { final File genDir = dc.getScratchDir(scratchDirName); if (genDir.isDirectory()) { if (zipOS == null) { zipOS = new ZipOutputStream( new BufferedOutputStream(new FileOutputStream(generatedContentZip))); } addFileToZip(zipOS, baseDir, genDir); } return zipOS; } private void addFileToZip(final ZipOutputStream zipOS, final File baseDir, final File f) throws IOException { final String entryName = baseDir.toURI().relativize(f.toURI()).getPath(); final ZipEntry entry = new ZipEntry(entryName); zipOS.putNextEntry(entry); if ( ! f.isDirectory()) { final byte[] buffer = new byte[1024]; final InputStream is = new BufferedInputStream(new FileInputStream(f)); int bytesRead; try { while ((bytesRead = is.read(buffer)) != -1) { zipOS.write(buffer, 0, bytesRead); } } finally { is.close(); zipOS.closeEntry(); } } else { /* * A directory entry has no content itself. */ zipOS.closeEntry(); for (File subFile : f.listFiles()) { addFileToZip(zipOS, baseDir, subFile); } } } public void validateDeploymentTarget(String target, String name, boolean isRedeploy) { List referencedTargets = domain.getAllReferencedTargetsForApplication(name); if (referencedTargets.isEmpty()) { if (isRegistered(name)) { if (!isRedeploy && DeploymentUtils.isDomainTarget(target)) { throw new IllegalArgumentException(localStrings.getLocalString("application.alreadyreg.redeploy", "Application with name {0} is already registered. Either specify that redeployment must be forced, or redeploy the application. Or if this is a new deployment, pick a different name.", name)); } else { if (!DeploymentUtils.isDomainTarget(target)) { throw new IllegalArgumentException(localStrings.getLocalString("use.create_app_ref_2", "Application {0} is already deployed in this domain. Please use create application ref to create application reference on target {1}.", name, target)); } } } return; } if (!isRedeploy) { if (DeploymentUtils.isDomainTarget(target)) { throw new IllegalArgumentException(localStrings.getLocalString("application.deploy_domain", "Application with name {0} is already referenced by other target(s). Please specify force option to redeploy to domain.", name)); } if (referencedTargets.size() == 1 && referencedTargets.contains(target)) { throw new IllegalArgumentException(localStrings.getLocalString("application.alreadyreg.redeploy", "Application with name {0} is already registered. Either specify that redeployment must be forced, or redeploy the application. Or if this is a new deployment, pick a different name.", name)); } else { throw new IllegalArgumentException(localStrings.getLocalString("use.create_app_ref", "Application {0} is already referenced by other target(s). Please use create application ref to create application reference on target {1}.", name, target)); } } else { if (referencedTargets.size() == 1 && referencedTargets.contains(target)) { return; } else { if (!DeploymentUtils.isDomainTarget(target)) { throw new IllegalArgumentException(localStrings.getLocalString("redeploy_on_multiple_targets", "Application {0} is referenced by more than one targets. Please remove other references or specify all targets (or domain target if using asadmin command line) before attempting redeploy operation.", name)); } } } } public void validateUndeploymentTarget(String target, String name) { List referencedTargets = domain.getAllReferencedTargetsForApplication(name); if (referencedTargets.size() > 1) { Application app = applications.getApplication(name); if (!DeploymentUtils.isDomainTarget(target)) { if (app.isLifecycleModule()) { throw new IllegalArgumentException(localStrings.getLocalString("delete_lifecycle_on_multiple_targets", "Lifecycle module {0} is referenced by more than one targets. Please remove other references before attempting delete operation.", name)); } else { throw new IllegalArgumentException(localStrings.getLocalString("undeploy_on_multiple_targets", "Application {0} is referenced by more than one targets. Please remove other references or specify all targets (or domain target if using asadmin command line) before attempting undeploy operation.", name)); } } } } public void validateSpecifiedTarget(String target) { if (env.isDas()) { if (target == null) { // we only validate the specified target return; } Cluster cluster = domain.getClusterNamed(target); if (cluster != null) { if (cluster.isVirtual()) { throw new IllegalArgumentException(localStrings.getLocalString("cannot_specify_managed_target", "Cannot specify target {0} for the operation. Target {0} is a managed target.", target)); } } } } public boolean isAppEnabled(Application app) { if (Boolean.valueOf(app.getEnabled())) { ApplicationRef appRef = server.getApplicationRef(app.getName()); if (appRef != null && Boolean.valueOf(appRef.getEnabled())) { return true; } } return false; } public ExtendedDeploymentContext disable(UndeployCommandParameters commandParams, Application app, ApplicationInfo appInfo, ActionReport report, Logger logger) throws Exception { if (appInfo == null) { report.failure(logger, "Application not registered", null); return null; } // if it's not on DAS and the application is not loaded, do not unload // when it's on DAS, there is some necessary clean up we need to do if (!env.isDas() && !appInfo.isLoaded()) { return null; } if (app != null) { commandParams._type = app.archiveType(); } final ExtendedDeploymentContext deploymentContext = getBuilder(logger, commandParams, report).source(appInfo.getSource()).build(); if (app != null) { deploymentContext.getAppProps().putAll( app.getDeployProperties()); deploymentContext.setModulePropsMap( app.getModulePropertiesMap()); } if (commandParams.properties != null) { deploymentContext.getAppProps().putAll(commandParams.properties); } unload(appInfo, deploymentContext); return deploymentContext; } public ExtendedDeploymentContext enable(String target, Application app, ApplicationRef appRef, ActionReport report, Logger logger) throws Exception { ReadableArchive archive = null; try { DeployCommandParameters commandParams = app.getDeployParameters(appRef); // if the application is already loaded, do not load again ApplicationInfo appInfo = appRegistry.get(commandParams.name); if (appInfo != null && appInfo.isLoaded()) { return null; } commandParams.origin = DeployCommandParameters.Origin.load; commandParams.command = DeployCommandParameters.Command.enable; commandParams.target = target; commandParams.enabled = Boolean.TRUE; Properties contextProps = app.getDeployProperties(); Map modulePropsMap = app.getModulePropertiesMap(); ApplicationConfigInfo savedAppConfig = new ApplicationConfigInfo(app); URI uri = new URI(app.getLocation()); File file = new File(uri); if (!file.exists()) { throw new Exception(localStrings.getLocalString("fnf", "File not found {0}", file.getAbsolutePath())); } archive = archiveFactory.openArchive(file); final ExtendedDeploymentContext deploymentContext = getBuilder(logger, commandParams, report).source(archive).build(); Properties appProps = deploymentContext.getAppProps(); appProps.putAll(contextProps); savedAppConfig.store(appProps); if (modulePropsMap != null) { deploymentContext.setModulePropsMap(modulePropsMap); } deploy(getSniffersFromApp(app), deploymentContext); return deploymentContext; } finally { try { if (archive != null) { archive.close(); } } catch (IOException ioe) { // ignore } } } private boolean loadOnCurrentInstance(DeploymentContext context) { final DeployCommandParameters commandParams = context.getCommandParameters(DeployCommandParameters.class); final Properties appProps = context.getAppProps(); if (commandParams.enabled) { // if the current instance match with the target if (domain.isCurrentInstanceMatchingTarget(commandParams.target, commandParams.name(), server.getName(), context.getTransientAppMetaData(DeploymentProperties.PREVIOUS_TARGETS, List.class))) { return true; } if (server.isDas()) { String objectType = appProps.getProperty(ServerTags.OBJECT_TYPE); if (objectType != null) { // if it's a system application needs to be loaded on DAS if (objectType.equals(DeploymentProperties.SYSTEM_ADMIN) || objectType.equals(DeploymentProperties.SYSTEM_ALL)) { return true; } } } } return false; } private String getApplicationType(ApplicationInfo appInfo) { StringBuffer sb = new StringBuffer(); if (appInfo.getSniffers().size() > 0) { for (Sniffer sniffer : appInfo.getSniffers()) { if (sniffer.isUserVisible()) { sb.append(sniffer.getModuleType() + ", "); } } } if (sb.length() > 2) { return sb.substring(0, sb.length()-2); } return sb.toString(); } public List getSniffersFromApp(Application app) { List snifferTypes = new ArrayList(); for (com.sun.enterprise.config.serverbeans.Module module : app.getModule()) { for (Engine engine : module.getEngines()) { snifferTypes.add(engine.getSniffer()); } } if (snifferTypes.isEmpty()) { // for the upgrade scenario, we cannot get the sniffers from the // domain.xml, so we need to re-process it during deployment return null; } List sniffers = new ArrayList(); if (app.isStandaloneModule()) { for (String snifferType : snifferTypes) { Sniffer sniffer = snifferManager.getSniffer(snifferType); if (sniffer != null) { sniffers.add(sniffer); } else { logger.log(Level.SEVERE, KernelLoggerInfo.cantFindSniffer, snifferType); } } if (sniffers.isEmpty()) { logger.log(Level.SEVERE, KernelLoggerInfo.cantFindSnifferForApp, app.getName()); return null; } } else { // todo, this is a cludge to force the reload and reparsing of the // composite application. return null; } return sniffers; } private ExecutorService createExecutorService() { Runtime runtime = Runtime.getRuntime(); int nrOfProcessors = runtime.availableProcessors(); return Executors.newFixedThreadPool(nrOfProcessors, new ThreadFactory() { @Override public Thread newThread(Runnable r) { Thread t = new Thread(r); t.setName("deployment-jar-scanner"); t.setContextClassLoader(getClass().getClassLoader()); t.setDaemon(true); return t; } }); } }





© 2015 - 2024 Weber Informatics LLC | Privacy Policy