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

com.sun.enterprise.admin.servermgmt.cli.StartDomainCommand Maven / Gradle / Ivy

There is a newer version: 7.2024.1.Alpha1
Show newest version
/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 1997-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 [2017-2023] Payara Foundation and/or affiliates

package com.sun.enterprise.admin.servermgmt.cli;

import com.sun.enterprise.admin.cli.CLIConstants;
import java.io.*;
import java.util.*;
import java.util.logging.*;

import jakarta.inject.Inject;

import org.jvnet.hk2.annotations.*;
import org.glassfish.api.Param;
import org.glassfish.api.admin.*;
import org.glassfish.hk2.api.PerLookup;

import com.sun.enterprise.admin.cli.Environment;
import com.sun.enterprise.admin.launcher.GFLauncher;
import com.sun.enterprise.admin.launcher.GFLauncherException;
import com.sun.enterprise.admin.launcher.GFLauncherFactory;
import com.sun.enterprise.admin.launcher.GFLauncherInfo;
import com.sun.enterprise.admin.util.CommandModelData.ParamModelData;
import com.sun.enterprise.universal.i18n.LocalStringsImpl;
import com.sun.enterprise.universal.process.ProcessStreamDrainer;
import com.sun.enterprise.universal.xml.MiniXmlParserException;
import org.glassfish.security.common.FileRealmStorageManager;

import static java.util.concurrent.TimeUnit.SECONDS;

/**
 * The start-domain command.
 *
 * @author bnevins
 * @author Bill Shannon
 */
@Service(name = "start-domain")
@PerLookup
public class StartDomainCommand extends LocalDomainCommand implements StartServerCommand {

    private GFLauncherInfo info;
    private GFLauncher launcher;
    @Param(optional = true, shortName = "v", defaultValue = "false")
    private boolean verbose;
    @Param(optional = true, defaultValue = "false")
    private boolean upgrade;
    @Param(optional = true, shortName = "w", defaultValue = "false")
    private boolean watchdog;
    @Param(optional = true, shortName = "d", defaultValue = "false")
    private boolean debug;
    @Param(name = "domain_name", primary = true, optional = true)
    private String domainName0;
    @Param(name = "dry-run", shortName = "n", optional = true,
            defaultValue = "false")
    private boolean dry_run;
    @Param(name = "drop-interrupted-commands", optional = true, defaultValue = "false")
    private boolean drop_interrupted_commands;
    @Param(name = "prebootcommandfile", optional = true)
    private String preBootCommand;
    @Param(name = "postbootcommandfile", optional = true)
    private String postBootCommand;

    @Param(defaultValue = "600", optional = true)
    protected int timeout;
    
    @Param(optional = true, defaultValue = "false")
    private boolean warmup;
    
    @Inject
    ServerEnvironment senv;
    
    private static final LocalStringsImpl STRINGS = new LocalStringsImpl(StartDomainCommand.class);
    // the name of the master password option
    private StartServerHelper helper;
    private String newpwName = Environment.getPrefix() + "NEWPASSWORD";

    @Override
    public List getLauncherArgs() {
        return launcher.getCommandLine();
    }

    @Override
    public RuntimeType getType() {
        return RuntimeType.DAS;
    }

    @Override
    protected void validate()
            throws CommandException, CommandValidationException {
        setDomainName(domainName0);
        
        if (preBootCommand != null){
            File prebootfile = new File(preBootCommand);
            if (!prebootfile.exists()){
                throw new CommandValidationException("preboot commands file does not exist: " + prebootfile.getAbsolutePath());
            }
        }
        
        if (postBootCommand != null){
            File postbootFile = new File(postBootCommand);
            if (!postbootFile.exists()){
                throw new CommandValidationException("postboot commands file does not exist: "+ postbootFile.getAbsolutePath());
            }
        }
        if (timeout < 1) {
            throw new CommandValidationException("Timeout must be at least 1 second long.");
        }
        super.validate();
    }

    @Override
    protected int executeCommand() throws CommandException {
        try {
            // createLauncher needs to go before the helper is created!!
            createLauncher();
            final String mpv = getMasterPassword();

            helper = new StartServerHelper(
                    logger,
                    programOpts.isTerse(),
                    getServerDirs(),
                    launcher,
                    mpv);

            if (helper.prepareForLaunch() == false){
                return ERROR;
            }
            
            if (!upgrade && launcher.needsManualUpgrade()) {
                logger.info(STRINGS.get("manualUpgradeNeeded"));
                return ERROR;
            }
            doAutoUpgrade(mpv);

            if (dry_run) {
                logger.fine(Strings.get("dry_run_msg"));
                List cmd = launcher.getCommandLine();
                StringBuilder sb = new StringBuilder();
                for (String s : cmd) {
                    sb.append(s);
                    sb.append('\n');
                }
                logger.info(sb.toString());
                return SUCCESS;
            }

            doAdminPasswordCheck();

            if (warmup) {
                info.setWarmup(warmup);
                helper.setWarmup(warmup);
            }

            // launch returns very quickly if verbose is not set
            // if verbose is set then it returns after the domain dies
            launcher.launch();

            if (verbose || upgrade || watchdog) { // we can potentially loop forever here...
                while (true) {
                    int returnValue = launcher.getExitValue();

                    switch (returnValue) {
                        case CLIConstants.RESTART_NORMAL:
                            logger.info(STRINGS.get("restart"));
                            break;
                        case CLIConstants.RESTART_DEBUG_ON:
                            logger.info(STRINGS.get("restartChangeDebug", "on"));
                            info.setDebug(true);
                            break;
                        case CLIConstants.RESTART_DEBUG_OFF:
                            logger.info(STRINGS.get("restartChangeDebug", "off"));
                            info.setDebug(false);
                            break;
                        default:
                            return returnValue;
                    }

                    if (env.debug())
                        System.setProperty(CLIConstants.WALL_CLOCK_START_PROP,
                                "" + System.currentTimeMillis());

                    launcher.relaunch();
                }

            }
            else {
                helper.waitForServer(timeout, SECONDS);
                helper.report();
                return SUCCESS;
            }
        }
        catch (GFLauncherException gfle) {
            throw new CommandException(gfle.getMessage());
        }
        catch (MiniXmlParserException me) {
            throw new CommandException(me);
        }
    }

    /**
     * Create a launcher for the domain specified by arguments to
     * this command.The launcher is for a server of the specified type.
     * Sets the launcher and info fields.  
     * It has to be public because it is part of an interface
     * @throws GFLauncherException if the launcher fails to setup
     * @throws MiniXmlParserException if the domain.xml cannot be processed
     */
    @Override
    public void createLauncher()
            throws GFLauncherException, MiniXmlParserException {
        launcher = GFLauncherFactory.getInstance(getType());
        info = launcher.getInfo();

        info.setDomainName(getDomainName());
        info.setDomainParentDir(getDomainsDir().getPath());
        info.setVerbose(verbose || upgrade);
        info.setDebug(debug);
        info.setUpgrade(upgrade);
        info.setWatchdog(watchdog);
        info.setWarmup(warmup);
        info.setDropInterruptedCommands(drop_interrupted_commands);
        info.setPrebootCommandsFile(preBootCommand);
        info.setpostbootCommandsFile(postBootCommand);
        info.setRespawnInfo(programOpts.getClassName(),
                programOpts.getClassPath(),
                respawnArgs());

        launcher.setup();
    }

    /**
     * Return the asadmin command line arguments necessary to start
     * this domain admin server.
     */
    private String[] respawnArgs() {
        List args = new ArrayList(15);
        args.addAll(Arrays.asList(programOpts.getProgramArguments()));

        // now the start-domain specific arguments
        args.add(getName());    // the command name
        args.add("--verbose=" + verbose);
        args.add("--watchdog=" + watchdog);
        args.add("--debug=" + debug);
        args.add("--warmup=" + warmup);
        args.add("--domaindir");
        args.add(getDomainsDir().toString());
        if (ok(getDomainName()))
            args.add(getDomainName());  // the operand

        if (logger.isLoggable(Level.FINER))
            logger.log(Level.FINER, "Respawn args: {0}", args);
        String[] a = new String[args.size()];
        args.toArray(a);
        return a;
    }

    /*
     * If this domain needs to be upgraded and --upgrade wasn't
     * specified, first start the domain to do the upgrade and
     * then start the domain again for real.
     */
    private void doAutoUpgrade(String mpv) throws GFLauncherException, MiniXmlParserException, CommandException {
        if (upgrade || !launcher.needsAutoUpgrade())
            return;

        logger.info(STRINGS.get("upgradeNeeded"));
        info.setUpgrade(true);
        launcher.setup();
        launcher.launch();
        Process p = launcher.getProcess();
        int exitCode = -1;
        try {
            exitCode = p.waitFor();
        }
        catch (InterruptedException ex) {
            // should never happen
        }
        if (exitCode != SUCCESS) {
            ProcessStreamDrainer psd =
                    launcher.getProcessStreamDrainer();
            String output = psd.getOutErrString();
            if (ok(output))
                throw new CommandException(
                        STRINGS.get("upgradeFailedOutput",
                        info.getDomainName(), exitCode, output));
            else
                throw new CommandException(STRINGS.get("upgradeFailed",
                        info.getDomainName(), exitCode));
        }
        logger.info(STRINGS.get("upgradeSuccessful"));

        // need a new launcher to start the domain for real
        createLauncher();
        // continue with normal start...
    }

    /*
     * Check to make sure that at least one admin user is able to login.
     * If none is found, then prompt for an admin password.
     *
     * NOTE: this depends on launcher.setup having already been called.
     */
    private void doAdminPasswordCheck() throws CommandException {
        String adminKeyFile = launcher.getAdminRealmKeyFile();
        if (adminKeyFile != null) {
            try {
                FileRealmStorageManager fileStorageManager = new FileRealmStorageManager(adminKeyFile);
                if (!fileStorageManager.hasAuthenticatableUser()) {
                    
                    // Prompt for the password for the first user and set it
                    Set names = fileStorageManager.getUserNames();
                    if (names == null || names.isEmpty()) {
                        throw new CommandException("no admin users");
                    }
                    
                    String adminUsername = names.iterator().next();
                    ParamModelData paramModelData = new ParamModelData(newpwName, String.class, false, null);
                    paramModelData.prompt = STRINGS.get("new.adminpw", adminUsername);
                    paramModelData.promptAgain = STRINGS.get("new.adminpw.again", adminUsername);
                    paramModelData.param._password = true;
                    
                    logger.info(STRINGS.get("new.adminpw.prompt"));
                    
                    char[] password = super.getPassword(paramModelData, null, true);
                    String passwordCopy = password != null ? new String(password) : null;
                    if (passwordCopy == null) {
                        throw new CommandException(STRINGS.get("no.console"));
                    }
                    
                    fileStorageManager.updateUser(adminUsername, adminUsername, passwordCopy.toCharArray(), null);
                    fileStorageManager.persist();
                }
            } catch (IOException ioe) {
                throw new CommandException(ioe);
            }
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy