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

org.glassfish.deployment.admin.DeployCommand Maven / Gradle / Ivy

There is a newer version: 10.0-b28
Show newest version
/*
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (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/CDDLv1.0.html or
 * glassfish/bootstrap/legal/CDDLv1.0.txt.
 * See the License for the specific language governing
 * permissions and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at glassfish/bootstrap/legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * you own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
 */

package org.glassfish.deployment.admin;

import com.sun.enterprise.config.serverbeans.Application;
import com.sun.enterprise.config.serverbeans.Applications;
import com.sun.enterprise.deploy.shared.ArchiveFactory;
import com.sun.enterprise.util.LocalStringManagerImpl;
import com.sun.enterprise.util.io.FileUtils;
import com.sun.enterprise.v3.admin.CommandRunner;
import java.net.URI;
import org.glassfish.internal.data.ApplicationInfo;
import com.sun.enterprise.v3.server.ApplicationLifecycle;
import com.sun.enterprise.config.serverbeans.ConfigBeansUtilities;
import org.glassfish.server.ServerEnvironmentImpl;
import com.sun.enterprise.config.serverbeans.Domain;
import com.sun.enterprise.config.serverbeans.ServerTags;
import com.sun.enterprise.config.serverbeans.ApplicationConfig;
import org.glassfish.api.ActionReport;
import org.glassfish.api.I18n;
import org.glassfish.api.Param;
import org.glassfish.api.admin.AdminCommand;
import org.glassfish.api.admin.AdminCommandContext;
import org.glassfish.api.admin.ParameterNames;
import org.glassfish.api.container.Sniffer;
import org.glassfish.api.deployment.archive.ArchiveHandler;
import org.glassfish.api.deployment.archive.ReadableArchive;
import org.jvnet.hk2.annotations.Inject;
import org.jvnet.hk2.annotations.Scoped;
import org.jvnet.hk2.annotations.Service;
import org.jvnet.hk2.component.PerLookup;

import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.glassfish.deployment.common.DeploymentProperties;
import org.glassfish.deployment.common.DeploymentContextImpl;


/**
 * Deploy command
 *
 * @author Jerome Dochez
 */
@Service(name="deploy")
@I18n("deploy.command")
@Scoped(PerLookup.class)
public class DeployCommand extends ApplicationLifecycle implements AdminCommand {

    final private static LocalStringManagerImpl localStrings = new LocalStringManagerImpl(DeployCommand.class);

    private static final String INSTANCE_ROOT_URI_PROPERTY_NAME = "com.sun.aas.instanceRootURI";

    @Inject
    Applications apps;

    @Inject
    ServerEnvironmentImpl env;

    @Inject
    CommandRunner commandRunner;

    @Param(name = ParameterNames.NAME, optional=true)
    String name = null;

    @Param(name = ParameterNames.CONTEXT_ROOT, optional=true)
    String contextRoot = null;

    @Param(name = ParameterNames.VIRTUAL_SERVERS, optional=true)
    @I18n("virtualservers")
    String virtualservers = null;

    @Param(name=ParameterNames.LIBRARIES, optional=true)
    String libraries = null;

    @Param(optional=true, defaultValue="false")
    Boolean force;

    @Param(name=ParameterNames.PRECOMPILE_JSP, optional=true, defaultValue="false")
    Boolean precompilejsp;

    @Param(optional=true, defaultValue="false")
    Boolean verify;
    
    @Param(optional=true)
    String retrieve = null;
    
    @Param(optional=true)
    String dbvendorname = null;

    //mutually exclusive with dropandcreatetables
    @Param(optional=true)
    Boolean createtables;

    //mutually exclusive with createtables
    @Param(optional=true)
    Boolean dropandcreatetables;

    @Param(optional=true)
    Boolean uniquetablenames;

    @Param(name=ParameterNames.DEPLOYMENT_PLAN, optional=true)
    File deploymentplan = null;

    @Param(name=ParameterNames.ENABLED, optional=true, defaultValue="true")
    Boolean enabled;
    
    @Param(optional=true, defaultValue="false")
    Boolean generatermistubs;
    
    @Param(optional=true, defaultValue="false")
    Boolean availabilityenabled;
    
    @Param(optional=true)
    String target = "server";
    
    @Param(optional=true, defaultValue="false")
    Boolean keepreposdir;

    @Param(optional=true, defaultValue="true")
    Boolean logReportedErrors;

    @Inject
    Domain domain;

    @Param(primary=true)
    File path;

    @Param(optional=true)
    String description;

    @Param(optional=true, name="property")
    Properties properties;

    private List appConfigList; 

    /**
     * Entry point from the framework into the command execution
     * @param context context for the command.
     */
    public void execute(AdminCommandContext context) {

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

        final Properties parameters = context.getCommandParameters();
        final ActionReport report = context.getActionReport();

        File file = choosePathFile(context);
        if (!file.exists()) {
            report.setMessage(localStrings.getLocalString("fnf","File not found", file.getAbsolutePath()));
            report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            return;
        }

        deploymentplan = chooseDeploymentPlanFile(context);
        
        if (snifferManager.hasNoSniffers()) {
            String msg = localStrings.getLocalString("nocontainer", "No container services registered, done...");
            report.failure(logger,msg);
            return;
        }

        ReadableArchive archive;
        try {
            archive = archiveFactory.openArchive(file);
        } catch (IOException e) {
            if (logReportedErrors) {
                report.failure(logger,"Error opening deployable artifact : " + file.getAbsolutePath(),e);
            } else {
                report.setMessage("Error opening deployable artifact : " + file.getAbsolutePath() + e.toString());
                report.setActionExitCode(ActionReport.ExitCode.FAILURE);
            }
            return;
        }
        File expansionDir=null;
        try {

            ArchiveHandler archiveHandler = getArchiveHandler(archive);
            if (archiveHandler==null) {
                report.failure(logger,localStrings.getLocalString("deploy.unknownarchivetype","Archive type of {0} was not recognized",file.getName()));
                return;
            }
            // get an application name
            if (name==null) {
                // Archive handlers know how to construct default app names.
                name = archiveHandler.getDefaultApplicationName(archive);
                // For the autodeployer in particular the name must be set in the
                // command context parameters for later use.
                parameters.put(ParameterNames.NAME, name);
            }
            
            if (parameters.containsKey(ParameterNames.DEPLOYMENT_PLAN)) {
                parameters.put(ParameterNames.DEPLOYMENT_PLAN, deploymentplan.getAbsolutePath());
            }
            
            Properties undeployProps = handleRedeploy(name, report, parameters);

            // clean up any left over repository files
            if ( ! keepreposdir.booleanValue()) {
                FileUtils.whack(new File(env.getApplicationRepositoryPath(), name));
            }
            parameters.put(ParameterNames.ENABLED, enabled.toString());

            File source = new File(archive.getURI().getSchemeSpecificPart());
            boolean isDirectoryDeployed = true;
            if (!source.isDirectory()) {
                isDirectoryDeployed = false;
                expansionDir = new File(domain.getApplicationRoot(), name);
                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 {
                    archiveHandler.expand(archive, archiveFactory.createArchive(expansionDir));
                    // Close the JAR archive before losing the reference to it or else the JAR remains locked.
                    try {
                        archive.close();
                    } catch(IOException e) {
                        report.failure(logger,localStrings.getLocalString("deploy.errorclosingarchive","Error while closing deployable artifact {0}", file.getAbsolutePath()),e);
                        return;
                    }
                    // Proceed using the expanded directory.
                    file = expansionDir;
                    archive = archiveFactory.openArchive(expansionDir);
                } catch(IOException e) {
                    report.failure(logger,localStrings.getLocalString("deploy.errorexpandingjar","Error while expanding archive file"),e);
                    return;

                }
            }

            // create the parent class loader
            final ReadableArchive sourceArchive = archive;
            final DeploymentContextImpl deploymentContext = new DeploymentContextImpl(logger,
                    sourceArchive, parameters, env);

            // reset the properties (might be null) set by the deployers when undeploying.
            deploymentContext.setProps(undeployProps);

            if (properties!=null) {
                deploymentContext.getProps().putAll(properties);
            }

            // create the classloaders used for deployment and load-time
            deploymentContext.createClassLoaders(clh, archiveHandler);
            final ClassLoader cloader = deploymentContext.getClassLoader();

            final ClassLoader currentCL = Thread.currentThread().getContextClassLoader();
            try {
                Thread.currentThread().setContextClassLoader(cloader);
                final Collection appSniffers = snifferManager.getSniffers(archive, cloader);
                if (appSniffers.size()==0) {
                    report.failure(logger,localStrings.getLocalString("deploy.unknownmoduletpe","Module type not recognized"));
                    return;
                }

                // clean up any generated files
                deleteContainerMetaInfo(deploymentContext);

                Properties moduleProps = deploymentContext.getProps();
                moduleProps.setProperty(ServerTags.NAME, name);
                /*
                 * If the app's location is within the domain's directory then
                 * express it in the config as ${com.sun.aas.instanceRootURI}/rest-of-path
                 * so users can relocate the entire installation without having
                 * to modify the app locations.  Leave the location alone if
                 * it does not fall within the domain directory.
                 */
                URI instanceRootURI = new URI(System.getProperty(INSTANCE_ROOT_URI_PROPERTY_NAME));
                URI appURI = instanceRootURI.relativize(deploymentContext.getSource().getURI());
                String appLocation = (appURI.isAbsolute()) ?
                    appURI.toString() :
                    "${" + INSTANCE_ROOT_URI_PROPERTY_NAME + "}/" + appURI.toString();
                moduleProps.setProperty(ServerTags.LOCATION, appLocation);
                // set to default "user", deployers can override it
                // during processing
                moduleProps.setProperty(ServerTags.OBJECT_TYPE, "user");
                if (contextRoot!=null) {
                    moduleProps.setProperty(ServerTags.CONTEXT_ROOT, contextRoot);
                }
                if (libraries!=null) {
                    moduleProps.setProperty(ServerTags.LIBRARIES, libraries);
                }
                moduleProps.setProperty(ServerTags.ENABLED, enabled.toString());
                moduleProps.setProperty(ServerTags.DIRECTORY_DEPLOYED, String.valueOf(isDirectoryDeployed));
                if (virtualservers != null) {
                    moduleProps.setProperty(ServerTags.VIRTUAL_SERVERS,
                        virtualservers);
                }
                if (description != null) {
                    moduleProps.setProperty(ServerTags.DESCRIPTION, description);
                }

                if (appConfigList != null) {
                    addApplicationConfigToProps(moduleProps, appConfigList);
                }

                ApplicationInfo appInfo = deploy(appSniffers, deploymentContext, report);
                if (report.getActionExitCode()==ActionReport.ExitCode.SUCCESS) {
                    // register application information in domain.xml
                    registerAppInDomainXML(appInfo, deploymentContext);

                }
            } finally {
                Thread.currentThread().setContextClassLoader(currentCL);
            }
        } catch(Exception e) {
            report.failure(logger,"Error during deployment : "+e.getMessage(),e);
        } finally {
            try {
                archive.close();
            } catch(IOException e) {
                logger.log(Level.INFO, "Error while closing deployable artifact : " + file.getAbsolutePath(), e);
            }
            if (report.getActionExitCode().equals(ActionReport.ExitCode.SUCCESS)) {
                logger.info("Deployment of " + name + " done is "
                        + (Calendar.getInstance().getTimeInMillis() - operationStartTime) + " ms");
            } else {
                if (expansionDir!=null) {
                   FileUtils.whack(expansionDir);
                }
            }
        }
    }

    private File choosePathFile(AdminCommandContext context) {
        if (context.getUploadedFiles().size() >= 1) {
            /*
             * Use the uploaded file rather than the one specified by --path.
             */
            return context.getUploadedFiles().get(0);
        }
        return path;
    }
    
    private File chooseDeploymentPlanFile(AdminCommandContext context) {
        if (context.getUploadedFiles().size() >= 2) {
            /*
             * Use the uploaded file rather than the one specified by
             * --deploymentplan.
             */
            return context.getUploadedFiles().get(1);
        }
        return deploymentplan;
    }
    
    /**
     *  Check if the application is deployed or not.
     *  If force option is true and appInfo is not null, then undeploy
     *  the application and return false.  This will force deployment
     *  if there's already a running application deployed.
     *
     *  @param name application name
     *  @param report ActionReport, report object to send back to client.
     * @return context properties that might have been set by the deployers
     * while undeploying the application
     *
     */
    private Properties handleRedeploy(final String name, final ActionReport report,
                                Properties parameters) 
        throws Exception {
        boolean isRegistered = isRegistered(name);
        if (isRegistered && !force) {
            String msg = localStrings.getLocalString(
                "application.alreadyreg.redeploy",
                "Application {0} already registered, please use deploy --force=true to redeploy", name);
            throw new Exception(msg);
        }
        else if (isRegistered && force) 
        {
            //preserve settings first before undeploy
            settingsFromDomainXML(parameters);
            //if applicaiton is already deployed and force=true,
            //then undeploy the application first.
            Properties undeployParam = new Properties();
            undeployParam.put(ParameterNames.NAME, name);
            undeployParam.put(DeploymentProperties.KEEP_REPOSITORY_DIRECTORY, 
                    keepreposdir.toString());
            ActionReport subReport = report.addSubActionsReport();
            if (properties!=null && properties.containsKey(DeploymentProperties.KEEP_SESSIONS)) {
                undeployParam.setProperty("properties", DeploymentProperties.KEEP_SESSIONS+"="+properties.getProperty(DeploymentProperties.KEEP_SESSIONS));
                subReport.setExtraProperties(new Properties());
            }
            commandRunner.doCommand("undeploy", undeployParam, subReport);
            return subReport.getExtraProperties();
        }
        return null;
    }

    
    /**
     *  Get settings from domain.xml and preserve the values.
     *  This is a private api and its invoked when --force=true and if the app is registered.
     *
     *  @param parameters 
     *
     */
    private void settingsFromDomainXML(Properties parameters) {
            //if name is null then cannot get the application's setting from domain.xml
        if (name != null) {
            if (contextRoot == null) {            
                contextRoot = ConfigBeansUtilities.getContextRoot(name);
                if (contextRoot != null) {
                    parameters.put(ParameterNames.PREVIOUS_CONTEXT_ROOT, 
                        contextRoot);
                }
            }
            if (libraries == null) {
                libraries = ConfigBeansUtilities.getLibraries(name);
                if (libraries != null) {
                    parameters.put(ParameterNames.LIBRARIES, libraries);
                }
            }
            if (virtualservers == null) {
                virtualservers = ConfigBeansUtilities.getVirtualServers(
                    target, name);
                if (virtualservers != null) {
                    parameters.put(ParameterNames.VIRTUAL_SERVERS, virtualservers);
                }
            }

            // also save the application config data
            final Application app = apps.getModule(Application.class, name);
            if (app != null) {
                appConfigList = app.getApplicationConfigs();
                if (appConfigList != null) {
                    addApplicationConfigToProps(parameters, appConfigList);
                }
            }

        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy