FileDocCategorySizeDatePackage
ASLauncher.javaAPI DocGlassfish v2 API116552Tue Jul 31 20:25:18 BST 2007com.sun.enterprise.admin.servermgmt.launch

ASLauncher

public class ASLauncher extends Object
This is the main class for the new ProcessLauncher which is responcible for creating and executing a java command. There are two general types of commands, internal and external. An internal command is basically one that is mostly defined by domain.xml. The command's java-config (classpath, jvm option, system properties, debug info, ...) is extracted from domain.xml using the config-api who's information is coupled with more general information from the processLauncher.xml file. How the final command is executed is based on the LaunchConstants.LAUNCHER_RETURN_PROP system property: LaunchConstants.LAUNCHER_RETURN_RETURN_VALUE - denotes that the command is executed via the Runtime .exec and immediately returns. If the "verbose" option is present as an argurment then the processes' stdout and stderr is attached to and sent to the stderr of the calling process. "hold" - denotes that the command is written to a temporary script in the calling scripts directory, then once the ProcessLauncher's java command returns the script is executed as the next command in the script and doesn't return until the temportary script finishes execution.

Fields Summary
protected static final String
RELATIVE_LOCATION_DOMAIN_XML
protected static final String
CLASSPATH_ENV_NAME
protected static final String
LAUNCHER_SCRIPT_LOCATION
protected static final String
LAUNCHER_START_ACTION
protected static final String
LAUNCHER_STOP_ACTION
protected static final String
INTERNAL_SERVER_PROFILE
protected static final String
AS9_INTERNAL_SERVER_PROFILE
protected static final String
INTERNAL_NODE_AGENT_PROFILE
protected static final int
SLEEP_TIME_FOR_PROCESS_START
protected static final String
COMMAND_LINE_ARG_VERBOSE
protected static final String
COMMAND_LINE_ARG_DEBUG
protected static final String
COMMAND_LINE_ARG_DISPLAY
protected static final String
COMMAND_LINE_ARG_NATIVE
protected static final char[]
COMMAND_DELIMITER_LIST
public static final String
DEBUG_OPTIONS
public static final String
VERBOSE_SYSTEM_PROPERTY
public static final String
LOGFILE_SYSTEM_PROPERTY
public static final String
PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY
public static final String
SPARC
public static final String
SPARCV9
public static final String
X86
public static final String
AMD64
public static final String
JVM_OPTION_FOR_64BIT
private static final String
CLASSPATH_PREFIX_PROPERTY
private static final String
CLASSPATH_SUFFIX_PROPERTY
private static final String
SERVER_CLASSPATH_PROPERTY
private static final String
UNDEFINED_ACTION
private static final String
ERROR_FLUSHER
private static final String
OUT_FLUSHER
private static final String
DOMAIN_NAME_XML_PROPERTY
private static final String
DOMAIN_NAME_SYSTEM_PROPERTY
private static final String
SCRIPT_PATH_SYSTEM_PROPERTY
int
_returnValue
String[]
securityInfo
private static final Level
FINE_LEVEL
private Logger
_logger
private String[]
_args
private static boolean
bDebug
private boolean
refreshConfigContext
FileHandler
externalLogfileHandler
private static final String
APPSERV_LAUNCH_JAR
Constructors Summary
Methods Summary
protected voidaddDebugOptions(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command, java.lang.String debug_options)
This method handles the debug options and was pulled from the LaunchFilter

        // only do for start action, not stop
        
        // If debug is enabled, then we need to pass on -Xdebug option
        command.addDebugOption("-Xdebug");
        
        // It seems that -Xdebug and other debug options shouldn't go
        // as one argument  So we will check if debug_options starts
        //  with that and give it as separate argument
        debug_options=debug_options.trim();
        if ( debug_options.startsWith("-Xdebug") )
        {
            debug_options =debug_options.substring("-Xdebug".length()).trim();
        }
        
        // Get the JPDA transport and address (port) from the
        // debug_options. If address is not specified in debug_options
        // for transport=dt_socket, we find a free port
        // and add it to -Xrunjdwp.
        //
        // If address is specified in -Xrunjdwp, then the JVM
        // does not print any debug message, so we need to print it for
        // easy viewing by the user.
        // If address is not specified in debug_options,
        // then the JVM will print a message like:
        // Listening for transport dt_socket at address: 33305
        // This is only visible with "asadmin start-domain --verbose"
        //
        // The format of debug_options is:
        // -Xrunjdwp:<name1>[=<value1>],<name2>[=<value2>]
        
        String transport = getDebugProperty(debug_options, "transport");
        String addr = getDebugProperty(debug_options, "address");
        
        if ( transport == null || transport.equals("") )
        {
            // XXX I18N this
            // throw exception
            System.out.println("Cannot start server in debug mode: no transport specified in debug-options in domain.xml.");
        }
        
        if ( transport.equals("dt_socket") )
        {
            if ( addr != null && !addr.equals("") )
            {
                // XXX Should we check if the port is free using
                // com.sun.enterprise.util.net.NetUtils.isPortFree(port)
            }
            else
            {
                // Get a free port
                int port =
                        com.sun.enterprise.util.net.NetUtils.getFreePort();
                if ( port == 0 )
                {
                    // XXX I18N this
                    // throw exception ???
                    System.out.println("Cannot start server in debug mode: unable to obtain a free port for transport dt_socket.");
                }
                addr = String.valueOf(port);
                
                debug_options = debug_options + ",address=" + addr;
            }
        }
        
        command.addDebugOption(debug_options);
        
        // Provide the actual JDWP options to the server using a
        // system property. This allow the server to make it available
        // to the debugger (e.g. S1 Studio) using an API.
        String jdwpOptions = debug_options.substring(
                debug_options.indexOf("-Xrunjdwp:") + "-Xrunjdwp:".length());
        
        command.addSystemVariable(DEBUG_OPTIONS, jdwpOptions);
        
    
protected voidaddElementProperties(com.sun.enterprise.config.serverbeans.ElementProperty[] ep, java.util.Properties systemProperties)

        if(ep != null)
        {
            for(int ii=0; ii < ep.length; ii++)
            {
                systemProperties.put(ep[ii].getName(), ep[ii].getValue());
            }
        }
    
protected voidaddJvmArg(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command, java.lang.String option, java.lang.String action)

        
        //
        // fix for bug# 6416997 so that the memory options
        // -Xmx and -Xms are not passed to jvm for stop command
        //
        
        // WBN
        if(option == null)
            return;
        
        if (LAUNCHER_STOP_ACTION.equals(action))
        {
            option = removeJVMStopOption(option);
            if (option.equals(""))
            {
                return;
            }
        }
        if ( option.startsWith("-D") )
        {
            // set to systemvaiables for commandline ordering
            command.addSystemVariable(option);
        }
        else
        {
            if ( ( option.equals("-client")) || (option.equals("-server")) )
            {
                //If user mentions server or client mode for VM
                // then use that over default which is "server"
                // As we want to keep this as first arg don't add
                // to the jvmArgsList yet
                command.setMode(option);
            }
            else
            {
                // just add the option to the jvm options
                command.addJvmOption(option);
            }
        }
        
        //getLogger().log(Level.INFO,"addJvmOptions: OUT Property " + option);
        if (bDebug) System.out.println("addJvmOptions: OUT Property " + option);
    
protected voidaddJvmOptions(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command, java.lang.String[] args, java.lang.String action)
This method handles the jvm options and was pulled from the LaunchFilter

        String systemProperty = null;
        String property = null;
        String value = null;
        String[] jvmOptions = null;
        
        try
        {
            jvmOptions = (new JvmOptionsHelper(args)).getJvmOptions();
        }
        catch(Exception e)
        {
        }
        
        if(jvmOptions!=null)
        {
            for(int i=0; i<jvmOptions.length; i++)
            {
                addJvmArg(command, jvmOptions[i], action);
            }
            return;
        }
        
        //here we are only in case if jvm-options helper had exception
        // then - old style of parsing, to avoid exception
        if(args != null)
        {
            // loop through args
            for(int ii=0; ii < args.length; ii++)
            {
                // remove leading and trailing spaces
                systemProperty=args[ii].trim();
                
                if (bDebug) System.out.println("addJvmOptions: IN Property " + systemProperty);
                
                // ignore white space
                if(systemProperty.trim().equals(""))
                {
                    continue;
                }
                
                int iSpace=0, iQuote1=0, iQuote2=0;
                // loop through jvm-options line and see if multple entries on one line
                while(systemProperty.length() > 0)
                {
                    
                    // Find first space and quote
                    iSpace=systemProperty.indexOf(" -");
                    iQuote1=systemProperty.indexOf("\"");
                    
                    // see if it has a space that may specify 2 args
                    if (iSpace >= 0)
                    {
                        // see if there are double quotes, which could mean the space is part of the value
                        if (iQuote1 >= 0)
                        {
                            // see where quote is in relation to space, if a space exists
                            if (iQuote1 > iSpace && iSpace >= 0 )
                            {
                                // quote is before space so break up to space, should be full arg
                                addJvmArg(command, systemProperty.substring(0, iSpace), action);
                                // set remainder string, minus space delimiter
                                systemProperty=systemProperty.substring(iSpace + 1).trim();
                                if (bDebug) System.out.println("*** left 1:" + systemProperty);
                            }
                            else
                            {
                                // quote is first, could have a space in quotes, or just quoted string at end
                                
                                // loop to find next un-escaped quote
                                int iQuoteStartPos=iQuote1 + 1;
                                while (true)
                                {
                                    iQuote2=systemProperty.indexOf("\"", iQuoteStartPos);
                                    if (iQuote2 < 0)
                                    {
                                        // error can't find last quote, so log and exit loop
                                        getLogger().log(Level.WARNING, "launcher.missMatchQuotesInArg", systemProperty);
                                        // set to "" to end multiple arg loop
                                        systemProperty="";
                                        // breakout of inner quote loop
                                        break;
                                    }
                                    
                                    // found second quote see if it is escaped,which means the
                                    // value has internal quotes
                                    if (systemProperty.charAt(iQuote2 - 1) == '\\")
                                    {
                                        // quote escaped, look for next quote
                                        iQuoteStartPos=iQuote2 + 1;
                                        continue;
                                    }
                                    else
                                    {
                                        // found end quote that is not escaped
                                        
                                        // see if there are any more spaces after second quote
                                        // this happends when directories are added with spaces in them
                                        // like java.dirs.ext system property
                                        if (systemProperty.indexOf(" -", iQuote2) < 0)
                                        {
                                            // no more space, so space was enclosed in quotes
                                            // send total line as one
                                            addJvmArg(command, systemProperty, action);
                                            
                                            // should be at the end
                                            // set to "" to end multiple arg loop
                                            systemProperty="";
                                        }
                                        else
                                        {
                                            // another space was found in the line
                                            iQuote2++; // add on to include quote in arg
                                            addJvmArg(command, systemProperty.substring(0, iQuote2), action);
                                            // set remainder string minus space delimiter
                                            if (iQuote2 < systemProperty.length())
                                            {
                                                systemProperty=systemProperty.substring(iQuote2 + 1).trim();
                                                if (bDebug) System.out.println("*** left 2:" + systemProperty);
                                            }
                                            else
                                            {
                                                // should be at the end
                                                // set to "" to end multiple arg loop
                                                systemProperty="";
                                            }
                                        }
                                        // breakout of inner quote loop
                                        break;
                                    }
                                }
                            }
                            
                        }
                        else
                        {
                            // no quotes, just break on " -" for multiple args
                            // space could be non-quoted like in java.ext.dirs
                            int iDel=systemProperty.indexOf(" -");
                            while(iDel >= 0)
                            {
                                // found token
                                addJvmArg(command, systemProperty.substring(0, iDel), action);
                                systemProperty=systemProperty.substring(iDel + 1).trim();
                                iDel=systemProperty.indexOf(" -");
                            }
                            
                            // make sure you get the last one
                            if (!systemProperty.equals(""))
                            {
                                addJvmArg(command, systemProperty, action);
                            }
                            
                            // break out of multiple arg loop
                            break;
                        }
                    }
                    else
                    {
                        // no spaces, should just be one value so add
                        addJvmArg(command, systemProperty, action);
                        // break out of multiple arg loop
                        break;
                    }
                }
            }
        }
        
    
protected voidaddLogFileToLogger(java.lang.String logFile)

        if (logFile == null) return;
        
        // Send logger output to our FileHandler.
        getLogger().log(FINE_LEVEL, "*** Adding logFileHandler - " + logFile);
        // already created directory structure for log file, so just add log
        try
        {// todo 6581651
            externalLogfileHandler = new FileHandler(logFile, true);
            externalLogfileHandler.setFormatter(new SimpleFormatter());
            externalLogfileHandler.setLevel(Level.ALL);
            getLogger().addHandler(externalLogfileHandler);
        }
        catch(IOException e)
        {
            // should be seen in verbose mode for debugging
            e.printStackTrace();
        }
    
protected voidaddSystemProperties(com.sun.enterprise.config.serverbeans.SystemProperty[] sp, java.util.Properties systemProperties)

        if(sp != null)
        {
            for(int ii=0; ii < sp.length; ii++)
            {
                systemProperties.put(sp[ii].getName(), sp[ii].getValue());
            }
        }
    
protected booleanargExists(java.lang.String arg)

        boolean bRet=false;
        String[] args=getArgs();
        if(args != null)
        {
            for(int ii=0; ii < args.length; ii++)
            {
                if(args[ii].equals(arg))
                {
                    bRet=true;
                    break;
                }
            }
        }
        return bRet;
    
public static voidbootstrap(java.lang.String[] args)
This method is meant to be called from the PLBootstrap.class to finish the setup of the ProcessLauncher to execute normally arg[0] - should be the name of the profile to use from processLauncher.xml arg[1] - should be the action to run (default is "start")

        ASLauncher pl=new ASLauncher();
        
        // set to nodeagent, by default
        String profile="s1as-deploytool";
        if (args != null && args.length >= 1)
        {
            // set to argument profile
            profile=args[0];
            
            // shift args
            String[] newArgs=new String[args.length - 1];
            for (int ii=0; ii < newArgs.length; ii++)
            {
                newArgs[ii]=args[ii + 1];
            }
            
            // set back to args
            args=newArgs;
        }
        
        // put profile in properties for later use
        System.setProperty(LaunchConstants.PROCESS_NAME_PROP, profile);
        
        if (bDebug) System.out.println("bootstrapping profile - " + profile);
        
        // start processing
        pl.process(args);
    
public com.sun.enterprise.admin.servermgmt.launch.ASLauncher$CommandbuildCommand(java.lang.String action)

        
        // execute any preprocessing,
        preBuildProcessing();
        String processName=System.getProperty(LaunchConstants.PROCESS_NAME_PROP, INTERNAL_SERVER_PROFILE);
        //Set system properties that correspond directly to asenv.conf/bat. This
        //keeps us from having to pass them all from -D on the command line.
        
        // check to see whether to build external or internal (domain.xml) command
        Command command=null;
        if (isServerProfile())
        {
            command=buildInternalCommand(action);
        }
        else
        {
            command=buildExternalCommand(action);
        }

        command.reorder();
        
        // log final command
        String finalCommand=command.toStringWithLines();
        getLogger().log(Level.INFO, finalCommand);
        
        return command;
    
public com.sun.enterprise.admin.servermgmt.launch.ASLauncher$CommandbuildExternalCommand(java.lang.String action)
This Method builds an external java command to execute componets like the nodeagent and the deploy tool

        
        // create the command to execute
        Command command=new Command();
        
        getLogger().log(FINE_LEVEL,"Start building the command the to execute.");
        
        // read in ASLauncherConfig
        String launcherConfigFile=System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY)
        + File.separator + "lib" + File.separator + "processLauncher.xml";
        
        String processName=System.getProperty(LaunchConstants.PROCESS_NAME_PROP, INTERNAL_NODE_AGENT_PROFILE);
        getLogger().log(FINE_LEVEL,"Loading ProcessLauncher config from: " + launcherConfigFile +
                " - for the process named: " + processName);
        
        // see if we have a config root set
        String configRoot=System.getProperty(SystemPropertyConstants.CONFIG_ROOT_PROPERTY);
        if (configRoot == null)
        {
            // no config root try and make one from install root
            configRoot=System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY) + File.separator + "config";
        }
        //Set system properties that correspond directly to asenv.conf/bat. This
        //keeps us from having to pass them all from -D on the command line.
        //ASenvPropertyReader reader = new ASenvPropertyReader(configRoot);
        //reader.setSystemProperties();
        
        // verbose set, flag used in ServerLogManager to send logs to stderr
        if (isVerboseEnabled())
        {
            command.addSystemVariable(VERBOSE_SYSTEM_PROPERTY, "true");
            // add to System.properties for config conditional adds (could be set about if not native launcher)
            System.setProperty(VERBOSE_SYSTEM_PROPERTY, "true");
        }
        
        // get configuration
        ASLauncherConfig plConfig=new ASLauncherConfig(launcherConfigFile, processName);
        
        // take plConfig properties as the base for the system jvm args for the new process
        Properties systemProperties=plConfig.getSystemProperties();
        
        // check for log file location
        String logFile=systemProperties.getProperty(LOGFILE_SYSTEM_PROPERTY);
        if(bDebug) System.out.println("Is external command nodeagent - " + isNodeAgentProfile());
        if (isNodeAgentProfile())
        {
            // need to get log info from domain.xml
            getLogger().log(FINE_LEVEL,"BuildExternalCommand for NodeAgent");
            
            try
            {
                // derive domain.xml location and create config to be used by config api
                String domainXMLLocation=System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY)
                + RELATIVE_LOCATION_DOMAIN_XML;
                ConfigContext configCtxt=ConfigFactory.createConfigContext(domainXMLLocation);
                Domain domain=ConfigAPIHelper.getDomainConfigBean(configCtxt);
                setDomainName(domain);
                
                // get the nodeagent by name, need it as soon as possible for logging
                String nodeAgentName=System.getProperty(SystemPropertyConstants.SERVER_NAME);
                NodeAgent nodeAgent=NodeAgentHelper.getNodeAgentByName(configCtxt, nodeAgentName);
                LogService logService=nodeAgent.getLogService();
                
                if(logService != null)
                {
                    getLogger().log(FINE_LEVEL, "LogService found for nodeagent");
                    // get logservice info from config beans
                    String logFileX=logService.getFile();
                    
                    if (logFileX !=null)
                    {
                        logFile=logFileX;
                        // add log to properties so NodeAgentMain will redirect is applicable
                        systemProperties.setProperty(LOGFILE_SYSTEM_PROPERTY, logFile);
                    }
                    
                    // set log level to the level that the nodeagent is set to
                    String logLevel=logService.getModuleLogLevels().getNodeAgent();
                    getLogger().setLevel(Level.parse(logLevel));
                }
            }
            catch (ConfigException ce)
            {
                // domain.xml should not be there on first start up, just log
                getLogger().log(FINE_LEVEL,"domain.xml does not exist yet for the nodeagent");
            }
        }
        
        // set log file for logger and native launcher
        if (logFile != null)
        {
            // make sure log is writable, if not a message will be logged to the screen if in verbose mode
            // WBN March 2007 - The JVM invocation command line does NOT get written
            // anywhere if isInternalLogger() returns true.  
            // It returns true for everything -- NA, DAS, Instance
            // So why is NA getting special treatment?  I see no reason so I'm
            //removing the restriction.
            
            if(createFileStructure(logFile) /* && !isInternalLogger() */)
            {
                // add this file to the logger so at least some of the launcher info gets propagated
                addLogFileToLogger(logFile);
            }
            command.setLogFile(logFile);
        }
        
        // derive and add java command to Command
        String javaHome=System.getProperty(LaunchConstants.JAVA_HOME_PROP);
        // use javaw for windows instead of java
        String javaCall="java", javaCmd=null;
        if(OS.isWindows())
        {
            javaCall="javaw";
        }
        
        if (javaHome != null)
        {
            // use standard java home
            javaCmd=javaHome + File.separator + "bin" + File.separator + javaCall;
        }
        else
        {
            // use executed jmv location of java.home
            String javaInt=System.getProperty("java.home");
            javaCmd=javaInt + File.separator + "bin" + File.separator + javaCall;
        }
        
        command.setJavaCommand(javaCmd);
        
        //
        // add classpath
        String classpath=deriveClasspath(plConfig, null);
        command.setClasspath(classpath);
        
        //
        //add main class
        command.setMainClass(plConfig.getMainClass());
        
        //
        // add all system properties to command as system variables args
        Iterator it=systemProperties.keySet().iterator();
        String key=null;
        
        String property=null, value=null;;
        while(it.hasNext())
        {
            key=(String)it.next();
            value=systemProperties.getProperty(key);
            
            // take care of vm arg that are sent in via the processlauncher.xml file
            if (key.startsWith("-"))
            {
                property = key;
                if (value != null && !value.equals(""))
                {
                    property += "=" + value;
                }
                if ( ( key.equals("-client")) || (key.equals("-server")) )
                {
                    // If user sets server or client mode for VM
                    // then use that over default which is "client"
                    // As we want to keep this as first arg don't add
                    // to the jvmArgsList yet
                    command.setMode(key);
                }
                else
                {
                    command.addJvmOption(property);
                }
            }
            else
            {
                // regular system property
                property = "-D" + key + "=" + value;
                command.addSystemVariable(key, value);
            }
        }
        
        //
        // derive native library path for native part of launcher
        command.addSystemVariable("java.library.path", deriveNativeClasspath(command, null, null, systemProperties));
        
        //
        // add command args from script
        String[] args=getArgs();
        for(int ii=0; ii < args.length; ii++)
        {
            command.addArg(args[ii]);
        }
        return command;
    
public com.sun.enterprise.admin.servermgmt.launch.ASLauncher$CommandbuildInternalCommand(java.lang.String action)
buildInternalCommand - This Method build san internal server command from domain.xml, so this method is specifically used for server instances

        StringManager _strMgr=StringManager.getManager(ASLauncher.class);
        
        // derive domain.xml location and create config to be used by config api
        String domainXMLLocation=System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY)
        + RELATIVE_LOCATION_DOMAIN_XML;
        //ConfigContext configCtxt=ConfigFactory.createConfigContext(domainXMLLocation);
        final ConfigContext configCtxt; //if-else guarantees definite assignment of blank finals
        if (this.getRefreshConfigContext()) //refresh, hence cache = false, new CC is returned;
            configCtxt = ConfigFactory.createConfigContext(domainXMLLocation, true, false, false);
        else //use cached config context
            configCtxt = ConfigFactory.createConfigContext(domainXMLLocation, true, false, true);
        
        /* Implementation Note: For start-domain command, control should go into else clause
         * because the start-domain-command code is creating the config context and
         * passing it to launcher. In the case of instances and node agents, the
         * cached config context is NOT used.
         * This is true with changes made to launcher during Oct 2006 - April 2007.
         */
        Domain domain=ConfigAPIHelper.getDomainConfigBean(configCtxt);
        setDomainName(domain);
        // get the server's config by name, need it as soon as possible for logging
        String serverName=System.getProperty(SystemPropertyConstants.SERVER_NAME);
        Server server=ServerHelper.getServerByName(configCtxt, serverName);
        String configRef=server.getConfigRef();
        
        // create the command to execute
        Command command=new Command();
        
        // set jvmargs for thread dump to go to child process log, workaround for bug #4957071
        //command.addJvmOption("-XX:+UnlockDiagnosticVMOptions");
        //command.addJvmOption("-XX:+LogVMOutput");
        //command.addJvmOption("-XX:LogFile=" + logFile);
        //command.addJvmOption("-XX:LogFile=/tmp/threadDump.txt");
        
        // get server's config
        Config config=ServerHelper.getConfigForServer(configCtxt, serverName);
        
        // configure log service and print redirect message
        String logFile=configureLogService(config);
        if (bDebug) System.out.println("LOGFILE = " + logFile);
        
        // make sure log is writable, if not a message will be logged to the screen if in verbose mode
        createFileStructure(logFile);
        command.setLogFile(logFile);
        
        // should NOT need to addLogFileToLogger(logFile), logManager should already do this for us
        // may need to enable if log is movable ???
        
        // TODO Logging Weirdnesses
        addLogFileToLogger(logFile);
        
        // add log to properties so PEMAIN will redirect is applicable
        command.addSystemVariable(LOGFILE_SYSTEM_PROPERTY, logFile);
        
        getLogger().log(FINE_LEVEL,"Retrieved domain.xml from " + domainXMLLocation);
        getLogger().log(FINE_LEVEL,"Start building the command the to execute.");
        
        //Set system properties that correspond directly to asenv.conf/bat. This
        //keeps us from having to pass them all from -D on the command line.
        //ASenvPropertyReader reader = new ASenvPropertyReader(System.getProperty(SystemPropertyConstants.CONFIG_ROOT_PROPERTY));
        //reader.setSystemProperties();
        
        // verbose set, flag used in ServerLogManager to send logs to stderr
        if (isVerboseEnabled())
        {
            command.addSystemVariable(VERBOSE_SYSTEM_PROPERTY, "true");
            // add to System.properties for config conditional adds (could be set about if not native launcher)
            System.setProperty(VERBOSE_SYSTEM_PROPERTY, "true");
        }
        
        // read in ASLauncherConfig
        String launcherConfigFile=System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY)
        + File.separator + "lib" + File.separator + "processLauncher.xml";
        
        String processName=System.getProperty(LaunchConstants.PROCESS_NAME_PROP, INTERNAL_SERVER_PROFILE);
        getLogger().log(FINE_LEVEL,"Loading ASLauncher config from: " + launcherConfigFile
                + " - for the process named: " + processName);
        
        ASLauncherConfig plConfig=new ASLauncherConfig(launcherConfigFile, processName);
        
        // take plConfig properties as the base for the system jvm args for the new process
        Properties systemProperties=plConfig.getSystemProperties();
        
        // add domain.xml property elements to the jvm args in reverse order of precedence.
        // First add the domain properties
        addSystemProperties(domain.getSystemProperty(), systemProperties);
        
        
        
        // set config name (which is retrieved from domain.xml) into System properties to be used for path resolution
        System.setProperty(SystemPropertyConstants.CONFIG_NAME_PROPERTY, configRef);
        systemProperties.put(SystemPropertyConstants.CONFIG_NAME_PROPERTY, configRef);
        
        // get javaconfig for server that is being started
        JavaConfig javaConfig=config.getJavaConfig();
        
        // derive and add java command to Command
        String jvmCmd=javaConfig.getJavaHome() + File.separator + "bin"
                + File.separator + "java";
        
        command.setJavaCommand(jvmCmd);
        
        
        // fix for bug# 6323645
        // Do not add options which are not applicable for stop action.
        // For ex. debug options and profiler options.
        // In other words add the following options ony when the action
        // is other than stop.
        
        Profiler profiler=javaConfig.getProfiler();
        String profilerClasspath=null;
        
        if (!action.equals(LAUNCHER_STOP_ACTION))
        {
            
            // The debug options including the debug port would be added
            // to the command  when the action is start.
            // If the action is stop adding the same port to the java command
            // would stack up the ports and block until the port assigned for
            // start action is released. To avoid this we check for stop action.
            
            // If the stop action needs to be debugged then one work around is to
            // copy the java command from server.log, change the debug settings and
            // run the command.
            
            // debug options
            if ((javaConfig.isDebugEnabled() || isDebugEnabled()))
            {
                // add debug statements
                addDebugOptions(command, javaConfig.getDebugOptions());
            }
            
            // add profiler properties & jvm args
            if (profiler != null && profiler.isEnabled())
            {
                // add config properties
                addElementProperties(profiler.getElementProperty(), systemProperties);
                String [] jvmOptions=profiler.getJvmOptions();
                addJvmOptions(command, jvmOptions, action);
                profilerClasspath=profiler.getClasspath();
            }
        }
        
        // set the default locale specified in domain.xml config file
        String locale=domain.getLocale();
        if (locale == null || locale.equals(""))
        {
            // if not specified in domain try system
            locale=System.getProperty(SystemPropertyConstants.DEFAULT_LOCALE_PROPERTY);
        }
        // make sure locale is specified before setting it
        if (locale != null && !locale.equals(""))
        {
            command.addSystemVariable(SystemPropertyConstants.DEFAULT_LOCALE_PROPERTY, locale);
        }
        //
        // add jvm args, look for combined jvm options
        String[] jvmOptions=javaConfig.getJvmOptions();
        addJvmOptions(command, jvmOptions, action);
        
        //
        // add config system properties
        addSystemProperties(config.getSystemProperty(), systemProperties);
        
        //
        // add cluster system properties if the server instance is clustered
        if (ServerHelper.isServerClustered(configCtxt, server))
        {
            Cluster cluster = ClusterHelper.getClusterForInstance(configCtxt,
                    server.getName());
            addSystemProperties(cluster.getSystemProperty(), systemProperties);
        }
        
        //
        // add server system properties
        addSystemProperties(server.getSystemProperty(), systemProperties);
        
        //
        // add classpath
        // check to see if jvmCmd starts with same as processLauncher jvm.
        // if so, use the system property java-version to determine jvm version
        if(OS.isWindows())
        {
            // make sure all delimeters are the same
            jvmCmd=jvmCmd.replace('/", '\\");
        }
        
        if (jvmCmd.startsWith(System.getProperty(SystemPropertyConstants.JAVA_ROOT_PROPERTY)))
        {
            // jvm command are the same, so use processLauncher jvm version
            jvmCmd=null;
        }
        String classpath=deriveClasspath(plConfig, jvmCmd, javaConfig, profilerClasspath);
        getLogger().log(FINE_LEVEL, "Complete process classpath = " + classpath);
        command.setClasspath(classpath);
        
        //
        //add main class
        command.setMainClass(plConfig.getMainClass());
        
        //
        // native library path to java path and system properties
        deriveNativeClasspath(command, javaConfig, profiler, systemProperties);
        
        //
        // add all system properties to command as jvm args
        Iterator it=systemProperties.keySet().iterator();
        String key=null;
        String property=null, value=null;;
        while(it.hasNext())
        {
            key=(String)it.next();
            value=systemProperties.getProperty(key);
            
            // take care of vm arg that are sent in via the processlauncher.xml file
            if (key.startsWith("-"))
            {
                property = key;
                if (value != null && !value.equals(""))
                {
                    property += "=" + value;
                }
                command.addJvmOption(property);
                getLogger().log(FINE_LEVEL, "JVM Option: " + property);
            }
            else
            {
                // regular system property
                property = "-D" + key + "=" + value;
                command.addSystemVariable(key, value);
                getLogger().log(FINE_LEVEL, "System Property: " + property);
            }
        }
        
        //Add prefix and suffix for AS9Profile
        if (getProcessLauncherProfile().equals(AS9_INTERNAL_SERVER_PROFILE))
        {
            String classpathPrefix=javaConfig.getClasspathPrefix();
            String classpathSuffix=javaConfig.getClasspathSuffix();
            String serverClasspath=javaConfig.getServerClasspath();
            getLogger().log(FINE_LEVEL, " prefix :: " + classpathPrefix
                    + " suffix :: " + classpathSuffix);
            if (classpathPrefix == null) classpathPrefix = "";
            command.addSystemVariable(CLASSPATH_PREFIX_PROPERTY, classpathPrefix);
            if (classpathSuffix == null) classpathSuffix = "";
            command.addSystemVariable(CLASSPATH_SUFFIX_PROPERTY, classpathSuffix);
            if (serverClasspath == null) serverClasspath = "";
            command.addSystemVariable(SERVER_CLASSPATH_PROPERTY, serverClasspath);
        }
        
        setPromptForIdentity(command);
        
        //
        // add command args from script
        String[] args=getArgs();
        for(int ii=0; ii < args.length; ii++)
        {
            command.addArg(args[ii]);
        }
        return command;
    
protected java.lang.StringconfigureLogService(com.sun.enterprise.config.serverbeans.Config config)
configureLogService - get log information out of domain.xml and set the processLaunchers log level to that of the instance log level

param
config This represents the config element in domain.xml for the server
return
logFile Log file for server

        String logFile="";
        LogService logService=config.getLogService();
        if(logService != null)
        {
            // get logservice info from config beans
            logFile=logService.getFile();
            String logLevel=logService.getModuleLogLevels().getAdmin();
            
            // set log level to the level that the instance is set to (for internal instances only
            getLogger().setLevel(Level.parse(logLevel));
        }
        return logFile;
    
private voidcopySystemProp(java.util.Properties to, java.lang.String name)

        String val = System.getProperty(name);
        
        if(val != null)
            to.setProperty(name, val);
    
protected booleancreateFileStructure(java.lang.String logFile)
createFileStructure - This method validates that that the file can be written to. It the if the parent directory structure does not exist, it will be created

param
logFile - fully qualified path of the logfile

        boolean bRet=false;
        File outputFile=new File(logFile);
        
        try
        {
            // Verify that we can write to the output file
            File parentFile = new File(outputFile.getParent());
            // To take care of non-existent log directories
            if ( !parentFile.exists() )
            {
                // Trying to create non-existent parent directories
                parentFile.mkdirs();
            }
            // create the file if it doesn't exist
            if (!outputFile.exists())
            {
                outputFile.createNewFile();
            }
            if (outputFile.canWrite())
            {
                // everything is okay to logfile
                bRet=true;
            }
        }
        catch (IOException e)
        {
            // will only see on verbose more, so okay
            e.printStackTrace();
        }
        
        if (!bRet)
        {
            // log can't be created or isn't writtable
            getLogger().log(Level.WARNING,"launcher.logWriteFailure", logFile);
        }
        
        return bRet;
    
protected java.lang.StringderiveClasspath(ASLauncherConfig plConfig, java.lang.String jvmCmd)
This method derives the classpath by using the information from the processLauncher.xml file which gives criteria for the classpath to be derived from the library directory.

        return deriveClasspath(plConfig, jvmCmd, null, null);
    
protected java.lang.StringderiveClasspath(ASLauncherConfig plConfig, java.lang.String jvmCmd, com.sun.enterprise.config.serverbeans.JavaConfig javaConfig, java.lang.String profilerClasspath)
This method derives the classpath by using the information from the processLauncher.xml file which gives criteria for the classpath to be derived from the library directory. It also will include the javaConfig classpath and profilerClasspath if they are passed in classpath construction hierarchy: (javaConfig.getClasspathPrefix) (processLauncher.Classpath.prefix) (processLauncher.Classpath.j2se1_4_prefix or processLauncher.Classpath.j2se1_5_or_later_prefix) (derivedClasspath based on processLauncher.Classpath excludes and includes) (javaConfig.getSystemClasspath) (javaConfig.getClasspathSuffix) (javaConfig.profilerClasspath if enabled) (Environment classpath if enabled)

        // add classpath
        String libDir=RelativePathResolver.resolvePath(plConfig.getClasspathLibDir());
        
        // WBN May 18, 2007 appserv-launch.jar removed from config's system-classpath'
        String classpath = getPELauncherJarPath();

        String libClasspath =  Classpath.getLibClasspath(libDir, plConfig.getClasspathIncludes(),
                plConfig.getClasspathExcludes());
        if (isValidString(libClasspath)) {
            classpath += File.pathSeparator + libClasspath;
        }

        getLogger().log(FINE_LEVEL, "Derived Classpath from " + libDir + " - \n" + classpath);
        
        // handle processLauncher.xml j2se prefixes always go first
        // check to see what jdk we are using
        String javaVersion=System.getProperty("java.version"); // default to 1.5 or later
        if (jvmCmd != null)
        {
            try
            {
                // execute the java command with version option
                Process process=Runtime.getRuntime().exec(jvmCmd + " -version");
                // get streams and capture output
                ByteArrayOutputStream baosOut= new ByteArrayOutputStream();
                ByteArrayOutputStream baosErr= new ByteArrayOutputStream();
                StreamFlusher sfOut=new StreamFlusher(process.getInputStream(), baosOut);
                StreamFlusher sfErr=new StreamFlusher(process.getErrorStream(), baosErr);
                new Thread(sfOut, OUT_FLUSHER).start();
                new Thread(sfErr, ERROR_FLUSHER).start();
                // wait for process to end, should be fast
                process.waitFor();
                javaVersion=baosErr.toString();
            }
            catch (Exception e)
            {
                // log at fine incase of problem
                getLogger().log(FINE_LEVEL,"Java version retrieving error, will default to 1.5 or later!", e);
            }
        }
        
        // put in jdk prefix, if exits, goes before what currently has been built
        String prefix="";
        String jvmv="";
        if(javaVersion.indexOf("1.4") >= 0)
        {
            // j2se 1.4
            jvmv="j2se 1.4";
            prefix=plConfig.getClasspathJ2se14Prefix();
        }
        else
        {
            // j2se 1.5 or later
            jvmv="j2se 1.5 or later";
            prefix=plConfig.getClasspathJ2se15OrLaterPrefix();
        }
        // log java version
        getLogger().log(FINE_LEVEL,"Java version being used is: ->" + jvmv +
                "<- based on ->" + javaVersion + "<-");
        
        // set j2se prefix, this alway goes first so the components classpath doesn't interfer with
        // the j2se's requirements
        if(prefix != null && !prefix.equals(""))
        {
            
            // resolve any tokens in the prefix
            prefix=RelativePathResolver.resolvePath(prefix);
            
            // only add prefix to path if one exists.
            if(classpath.equals(""))
            {
                // no other classpath information so only use prefix, could be know classpath
                classpath=prefix;
            }
            else
            {
                // prepend prefix to path
                classpath=prefix + File.pathSeparator + classpath;
            }
        }
        
        
        // handle processLauncher.xml prefix, if exits, goes before what currently has been built
        prefix=plConfig.getClasspathPrefix();
        // set prefix, this also can be used as a method for entering a know classpath.
        if(prefix != null && !prefix.equals(""))
        {
            
            // resolve any tokens in the prefix
            prefix=RelativePathResolver.resolvePath(prefix);
            
            // only add prefix to path if one exists.
            if(classpath.equals(""))
            {
                // no other classpath information so only use prefix, could be know classpath
                classpath=prefix;
            }
            else
            {
                // prepend prefix to path
                classpath=prefix + File.pathSeparator + classpath;
            }
        }
        
        
        // add in the javaconfig paths
        if(javaConfig != null)
        {
            String classpathPrefix=javaConfig.getClasspathPrefix();
            String classpathSystem=javaConfig.getSystemClasspath();
            String classpathSuffix=javaConfig.getClasspathSuffix();
            
            if(isValidString(classpathSystem))
            {
                classpath += File.pathSeparator + classpathSystem;
            }
            
            //Classpath prefix/suffix and server classpath gets now prefixed/suffixed to
            //the shared classloader at PELaunch.java. Instead of setting it here, set
            //system properties, so that the system properties could be used to construct
            //the classpaths in PELaunch
            if (getProcessLauncherProfile().equals(INTERNAL_SERVER_PROFILE))
            {
                if(isValidString(classpathPrefix))
                {
                    classpath=classpathPrefix + File.pathSeparator + classpath;
                }
                if(isValidString(classpathSuffix))
                {
                    classpath=classpath + File.pathSeparator +  classpathSuffix;
                }
            }
            
            // add profiler information
            if(profilerClasspath != null)
            {
                classpath += File.pathSeparator + profilerClasspath;
            }
            // See if need to add user classpath
            // WBN changed to use JDK 1.5 built-in getEnv()
            if(!javaConfig.isEnvClasspathIgnored())
            {
                // Add user classpath...
                String userCP = System.getenv(CLASSPATH_ENV_NAME);
                if(userCP != null && userCP.length() > 0)
                    classpath += File.pathSeparator + userCP;
            }
        }
        
        getLogger().log(FINE_LEVEL, "Final classpath - \n" + classpath);
        if (bDebug) System.out.println("Final classpath=" + classpath);
        return classpath;
    
protected java.lang.StringderiveNativeClasspath(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command, com.sun.enterprise.config.serverbeans.JavaConfig javaConfig, com.sun.enterprise.config.serverbeans.Profiler profiler, java.util.Properties systemProperties)

        // native path works in native launcher
        String javaLibPath = System.getProperty("java.library.path");
        if (bDebug) System.out.println("Current java.library.path=" + javaLibPath + "\n");
        if (javaLibPath == null) javaLibPath="";
        String libDirFor64Bit = "";
        
        if (javaConfig != null)
        {
            String nativePrefix=javaConfig.getNativeLibraryPathPrefix();
            String nativeSuffix=javaConfig.getNativeLibraryPathSuffix();
            
            String nativeProfiler=null;
            if(profiler != null && profiler.isEnabled())
            {
                nativeProfiler=profiler.getNativeLibraryPath();
            }
            
            // put native path together in designated order
            if ( (nativePrefix != null ) && !nativePrefix.trim().equals(""))
            {
                javaLibPath=nativePrefix + (javaLibPath.equals("") ? "" : File.pathSeparator + javaLibPath);
            }
            if ( (nativeSuffix != null ) && !nativeSuffix.trim().equals(""))
            {
                javaLibPath=(javaLibPath.equals("") ? "" : javaLibPath + File.pathSeparator) + nativeSuffix ;
            }
            if (( nativeProfiler!= null ) && !nativeProfiler.trim().equals(""))
            {
                javaLibPath=(javaLibPath.equals("") ? "" : javaLibPath + File.pathSeparator) + nativeProfiler ;
            }
            
            
            String[] jvmOptions=javaConfig.getJvmOptions();
            for(String s:jvmOptions)
            {
                if(s.indexOf(JVM_OPTION_FOR_64BIT)!=-1)
                {
                    String osArch = System.getProperty("os.arch");
                    if(osArch.equals(SPARC)) libDirFor64Bit = SPARCV9;
                    else if(osArch.equals(X86))  libDirFor64Bit = AMD64;
                    
                    String nssRoot=System.getProperty(SystemPropertyConstants.NSS_ROOT_PROPERTY);
                    String installRoot=System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY);
                    String imqLib=System.getProperty(SystemPropertyConstants.IMQ_LIB_PROPERTY);
                    String java64BitLibPath = "";
                    if (installRoot != null)
                    {
                        if(imqLib != null)
                        {
                            java64BitLibPath = imqLib + File.separator + libDirFor64Bit + File.pathSeparator + java64BitLibPath;
                        }
                        
                        if(installRoot != null)
                        {
                            java64BitLibPath = installRoot + File.separator + "lib" + File.separator + libDirFor64Bit + File.pathSeparator + java64BitLibPath;
                        }
                        if(nssRoot != null)
                        {
                            java64BitLibPath= nssRoot + File.separator + libDirFor64Bit + File.pathSeparator + java64BitLibPath;
                        }
                        javaLibPath = java64BitLibPath + File.pathSeparator + javaLibPath;
                    }
                }
            }
        }
        // add nss and lib directories to from of java.library.path if windows to get around jdk
        // addition of c:\windows\system32
        if (OS.isWindows())
        {
            String nssRoot=System.getProperty(SystemPropertyConstants.NSS_ROOT_PROPERTY);
            String installRoot=System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY);
            
            if (installRoot != null && nssRoot != null)
            {
                javaLibPath= nssRoot + File.pathSeparator +
                        installRoot + File.separator + "lib" + File.pathSeparator + javaLibPath;
            }
        }
        
        if (isDisplayEnabled())
        {
            // need to add the path the correct jvm library so the native portion will
            // switch jvm modes, it should be set to client by default, but set it just in case
            
            // fix for bug# 6240672 and 6318497
            // This fix enables the use of java_home available in java-config.
            // If the java_home picked up from java-config is invalid then it falls back
            // to default java_home of config/asenv.conf
            
            String java_home = null;
            if ((javaConfig != null) && (javaConfig.getJavaHome() != null))
            {
                java_home = javaConfig.getJavaHome();
            }
            else
            {
                java_home = SystemPropertyConstants.JAVA_ROOT_PROPERTY;
            }
            String jvmLibPath = java_home +
                    System.getProperty(SystemPropertyConstants.NATIVE_LAUNCHER_LIB_PREFIX);
            
            // remove default jvm mode and add proper one
            if (command.getMode() != null)
            {
                jvmLibPath=jvmLibPath.substring(0, jvmLibPath.lastIndexOf(File.separator) + 1) +
                        command.getMode().substring(1);
            }
            
            if (javaLibPath != null)
            {
                javaLibPath=jvmLibPath + File.pathSeparator + javaLibPath;
            }
            else
            {
                javaLibPath=jvmLibPath;
            }
        }
        
        
        // now check for spaces in path
        if(javaLibPath.indexOf(" ") >= 0)
        {
            // there are spaces in the path so send warning message
            // Almost every Windows user has spaces in their path.
            // Bug 6342806 determined that this is "noise"
            // I changed the message to FINE and I added in the names of the items
            // in the path that have spaces...
            String items = getPathItemsWithSpaces(javaLibPath);
            getLogger().log(FINE_LEVEL,"launcher.spacesInPath", new Object[] { items });
            
            // remove all quotes, because either the java or native launchers will not consistenly
            // accept the mix in the java.library.path
            // This is a problem between the JNI invocation api and the straight java command.
            javaLibPath=javaLibPath.replaceAll("\"", "");
        }
        
        systemProperties.put("java.library.path" , javaLibPath);
        
        
        
        System.setProperty("java.library.path", javaLibPath );
        command.setNativeClasspath(javaLibPath);
        
        
        if (bDebug) System.out.println("Final java.library.path=" + javaLibPath + "\n");
        return javaLibPath;
    
public java.lang.ProcessexecuteBackgroundCommand(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command, boolean verbose, java.lang.String action)

        
        // execute the command as a runtime.exec and immediately return,
        // return will not pertain to the the executed process
        getLogger().log(FINE_LEVEL, "ASLauncher: executing Runtime execute...");
        
        // run command
        
        String[] cmd=command.getCommandAsArray();
        //getLogger().log(Level.INFO, "\n" + Arrays.toString(cmd));
        ProcessBuilder pb = new ProcessBuilder(cmd);
        
        File configDir = new File(System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY) + "/config");
        
        if(FileUtils.safeIsDirectory(configDir))
            pb.directory(configDir);
        
        Process process = pb.start();
        
        // See is there is input that needs to be sent to the process
        // WBN Sept 2006 -- it used to check for the EXISTENCE of the System Property -
        // now it checks on whether it exists AND is set to true.
        // note we do NOT do this if the password/user name info is sent in as a parameter to process()!!  In that
        // case we already have the info and just need to write it to the AS process...
        // this is really overly-complex because of supporting native startup (sigh)
        
        if (Boolean.getBoolean(PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY) && action.equals(LAUNCHER_START_ACTION) )
        {
            if(securityInfo == null)
                sendInputToProcessInput(System.in, process);    // ancient native launcher uses startserv script
            else
                writeSecurityInfoToProcess(process);
        }
        // start stream flusher to push output to parent streams and log if they exist
        StreamFlusher sfErr=new StreamFlusher(process.getErrorStream(), System.err, command.getLogFile());
        Thread sfErrThread = new Thread(sfErr, ERROR_FLUSHER);
        sfErrThread.setDaemon(true);
        sfErrThread.start();
        
        if (verbose || isWaitEnabled())
        {
            // need to keep client around for start
            // this should only be invoked for start-domain command
            
            // set flusher on stdout also
            StreamFlusher sfOut=new StreamFlusher(process.getInputStream(), System.out, command.getLogFile());
            Thread sfOutThread = new Thread(sfOut, OUT_FLUSHER);
            sfOutThread.setDaemon(true);
            sfOutThread.start();
            
            try
            {
                process.waitFor();
                sfOutThread.join();
                sfErrThread.join();
            }
            catch (InterruptedException ie)
            {
                // just let fall through, but log at finest level
                System.out.println("While waiting in verbose mode, an InterruptedException was thrown ");
            }
        }
        else
        {
            
            // set flusher on stdout also, if not could stop with too much output
            StreamFlusher sfOut=new StreamFlusher(process.getInputStream(), System.out);
            Thread sfOutThread = new Thread(sfOut, OUT_FLUSHER);
            sfOutThread.setDaemon(true);
            sfOutThread.start();
            
            // if executing in the background and a log exists, print log location
            String logFile=command.getLogFile();
            
            // TODO extra redirect message?
            //./admin-cli/commands/src/java/com/sun/enterprise/cli/commands/LocalStrings.properties:LogRedirectedTo=Log redirected to {0}.
            if (logFile != null)
            {
                System.out.println(StringManager.getManager(ASLauncher.class).getString("launcher.redirecting.output",
                        logFile));
            }
            // must sleep for a couple of seconds, so if there is a jvm startup error, the parent process
            // is around to catch and report it when the process in executed in verbose mode.
            // WBN  ?????? It doesn't appear that we need this ????  Verbose mode was handled in the "if"
            // above...
            //try {
            //Thread.currentThread().sleep(SLEEP_TIME_FOR_PROCESS_START);
            //} catch (InterruptedException ie) {}
        }
        return process;
    
public java.lang.ProcessexecuteCommand(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command, java.lang.String action)
executeCommand

param
cmd - command to execute
param
action - action to take, should be start or stop. defaults to "start"

        
        String[] cmd=null;
        
        // For native launcher and service, must send command to stdout in know format for
        // parsing by native code.  The purpose is to keep as much of the launcher functionality in
        // java as possible, keeping maintanance low and staying within a skillset that we have in abundance
        // It also is a easy way to show the command that is generated
        if (isDisplayEnabled() == false)
        {
            return executeBackgroundCommand(command, isVerboseEnabled(), action);
        }
        
        // First remove display argument that is used to trigger this action
        // This is the only arg that should be removed, all the rest should be passed through
        command.removeArg(COMMAND_LINE_ARG_DISPLAY);
        command.removeArg(COMMAND_LINE_ARG_NATIVE);
        
        // add launcher type for display to native exe, so the exe can desice whether to hold the child's
        // process or not.
        String launcherRet=System.getProperty(LaunchConstants.LAUNCHER_RETURN_PROP);
        if (launcherRet != null )
        {
            if (bDebug) System.out.println("-D" + LaunchConstants.LAUNCHER_RETURN_PROP + "=" + launcherRet);
            command.addSystemVariable(LaunchConstants.LAUNCHER_RETURN_PROP, launcherRet);
        }
    
        // display java command to stdout in the following format.
        // NOTE: if this becomes externally available, use xml, for now its an internal structure.
        // Class Name (path is seperated by "/" |
        // Java Args |
        // everything else (should start with a "-") |
        // classpath should be prepended with "-Djava.class.path="
        cmd=command.getCommandInJNIFormatAsArray();
        
        // Find delimiter that doesn't exist in command, just to be safe
        boolean found=false;
        String sxDelim="|";
        for(int ii=0; ii < COMMAND_DELIMITER_LIST.length; ii++)
        {
            // reset found to false for new delimiter
            found=false;
            // first character should delimiter to used to parse command
            for(int jj=0; jj < cmd.length; jj++)
            {
                if (bDebug) System.out.println(COMMAND_DELIMITER_LIST[ii] + " - " + cmd[jj]);
                if(cmd[jj].indexOf(COMMAND_DELIMITER_LIST[ii]) >= 0)
                {
                    // delimiter is found in string
                    found=true;
                    break;
                }
            }
            if (bDebug) System.out.println("\n***Delimiter = " + found + "\n");
            
            // see if char not found in any string
            if (!found)
            {
                // didn't find delimiter, so set and exit
                sxDelim=String.valueOf(COMMAND_DELIMITER_LIST[ii]);
                break;
            }
        }
        
        if(found)
        {
            // serious delimiter error, since all the delimits in the
            // COMMAND_DELIMITER_LIST array are in the java command
            // to startup the appserver then the native launcher can't
            // parse the command correctly and a jvm.dll error will arise.
            getLogger().log(Level.SEVERE, "launcher.native_launcher_delimiter_error");
        }
        
        // INCREDIBLY IMPORTANT for native processing.
        // The only data the native process expects is the commandline
        // any other data sent to stdout will throw off the command parsing
        // Needed to make the native side have a synch string, because anything could go wrong
        // with either the script that initiates this class or the preBuildProcessing.
        System.out.print("STARTOFCOMMAND" + sxDelim);
        for(int ii=0; ii < cmd.length; ii++)
        {
            System.out.print(cmd[ii] + sxDelim);
        }
        System.out.print("ENDOFCOMMAND" + sxDelim);
        // we can't return a Process because we are being CALLED by the external process.
        // only ASNativeLauncher will have a handle to the native process that called us
        return null;
    
protected java.lang.String[]getArgs()

        return _args;
    
protected java.lang.StringgetDebugProperty(java.lang.String debug_options, java.lang.String name)

        int nameIndex;
        if ( (nameIndex = debug_options.indexOf(name)) != -1 )
        {
            // format is "name=value"
            String value = debug_options.substring(nameIndex
                    + name.length() + 1);
            int commaIndex;
            if ( (commaIndex = value.indexOf(",")) != -1 )
            {
                value = value.substring(0, commaIndex);
            }
            return value;
        }
        return null;
    
protected java.lang.StringgetFiletRelativeName(java.lang.String action)

        return System.getProperty(SystemPropertyConstants.INSTANCE_ROOT_PROPERTY) + File.separator
                + LAUNCHER_SCRIPT_LOCATION + File.separator + action;
    
protected java.util.logging.LoggergetLogger()

        if (_logger == null)
        {
            // check log manager to see if it is internal or external
            // if (!isInternalLogger()) {
            // external log manager, add resource bundle for i18n
            // will associate a file to the logger if it is specified in the system args
            _logger = Logger.getLogger(LogDomains.PROCESS_LAUNCHER_LOGGER, "com.sun.logging.enterprise.system.tools.launcher.LogStrings");
            
            // check to see if in verbose mode, if not remove default console handler
            if (!isVerboseEnabled())
            {
                Handler[] h=_logger.getParent().getHandlers();
                for (int ii=0; ii < h.length; ii++)
                {
                    if (h[ii].getClass().getName().equals("java.util.logging.ConsoleHandler"))
                    {
                        _logger.getParent().removeHandler(h[ii]);
                    }
                }
            }
            
            //} else {
            // use internal log manager which associates the resource bundle and
            // log file automatically
            //    _logger = Logger.getLogger(LogDomains.PROCESS_LAUNCHER_LOGGER, "com.sun.logging.enterprise.system.tools.launcher.LogStrings");
            //}
        }
        
        // set each time reguardless of what is preset in domain.xml (for internals)
        if (bDebug) _logger.setLevel(Level.FINEST);
        return _logger;
    
private java.lang.StringgetPELauncherJarPath()

        // WBN May 18, 2007 appserv-launch.jar removed from config's system-classpath'
        return System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY) 
                + File.separator
                + "lib"
                + File.separator
                + APPSERV_LAUNCH_JAR;
    
private java.lang.StringgetPassword(java.io.BufferedReader stdin, java.lang.String prompt)

        try
        {
            NativeUtils nativeUtils = new NativeUtils();
            return nativeUtils.getPassword(prompt);
        }
        catch(Throwable t)
        {
                // fall through -- it needs to be Throwable, not Exception...
        }

        System.out.print(prompt);
       
        return stdin.readLine();    
    
private java.lang.StringgetPathItemsWithSpaces(java.lang.String path)

        StringTokenizer st = new StringTokenizer(path, File.pathSeparator);
        String ret = "";
        boolean firstItem = true;
        
        while (st.hasMoreTokens())
        {
            String item = st.nextToken();
            
            if(item.indexOf(' ") >= 0)
            {
                if(!firstItem)
                    ret += File.pathSeparator;
                else
                    firstItem = false;
                
                ret += item;
            }
        }
        
        return ret;
    
protected java.lang.StringgetProcessLauncherProfile()

        return System.getProperty(LaunchConstants.PROCESS_NAME_PROP, INTERNAL_SERVER_PROFILE);
    
public booleangetRefreshConfigContext()

        return ( refreshConfigContext );
    
intgetReturnValue()

        return _returnValue;
    
protected java.lang.StringgetScriptRelativeName(java.lang.String action)

        String sxRet=getFiletRelativeName(action);
        if(OS.isWindows())
        {
            sxRet+="_temp.bat";
        }
        else
        {
            sxRet+="_temp.sh";
        }
        return sxRet;
    
voidgetSecurityFromUser(java.lang.String[] args)

        if(System.getProperty("caller", "not-cli").equals("cli"))
         return;

        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        securityInfo = new String[3];
        System.out.print("admin username:");
        securityInfo[0] = reader.readLine();
        securityInfo[1] = getPassword(reader, "admin password:  ");
        securityInfo[2] = getPassword(reader, "master password: ");
        System.setProperty(PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY, "true");
     
protected booleanisDebugEnabled()

        return argExists(COMMAND_LINE_ARG_DEBUG);
    
protected booleanisDisplayEnabled()

        return argExists(COMMAND_LINE_ARG_DISPLAY);
    
protected booleanisInternalLogger()

        boolean bRet=false;
        // check log manager to see if it is internal or external
        String logManager=System.getProperty(LaunchConstants.LOG_MGR_PROP);
        if (logManager != null && logManager.equals(LaunchConstants.LOG_MGR_VALUE))
        {
            bRet=true;
        }
        return bRet;
    
protected booleanisNodeAgentProfile()

        String processName=getProcessLauncherProfile();
        return processName.equals(INTERNAL_NODE_AGENT_PROFILE);
    
protected booleanisServerProfile()

        String processName=getProcessLauncherProfile();
        return processName.equals(INTERNAL_SERVER_PROFILE) ||
                processName.equals(AS9_INTERNAL_SERVER_PROFILE);
    
private booleanisValidString(java.lang.String s)

        return (s != null && !s.trim().equals(""));
    
protected booleanisVerboseEnabled()

        return argExists(COMMAND_LINE_ARG_VERBOSE);
    
protected booleanisWaitEnabled()

        boolean bRet=false;
        String launcherRet=System.getProperty(LaunchConstants.LAUNCHER_RETURN_PROP);
        if(launcherRet != null && launcherRet.equals(LaunchConstants.LAUNCHER_RETURN_HOLD_VALUE))
        {
            bRet=true;
        }
        return bRet;
    
public static voidmain(java.lang.String[] args)

    
        
    
        int returnValue = 1;
        
        ASLauncher pl=null;
        try
        {
            pl=new ASLauncher();
            pl.preProcess(args);    // figure out relocatable stuff
            pl.getSecurityFromUser(args);
            Process process = pl.process(args, pl.securityInfo);
        }
        catch(Exception e)
        {
            e.printStackTrace();
        }
        finally
        {
            if ( pl != null )
            {
                returnValue = pl.getReturnValue();
            }
        }
        
        System.exit(returnValue);
    
protected voidpreBuildProcessing()

        // this is a place holder so ee can put in its
        // sychronization code
    
public voidpreProcess(java.lang.String[] args, java.util.Properties extraProps)
WBN Oct 2006 -- The startserv script has been made relocatable. But we have to be backward compatible. So look for the new args and preprocess them... Adding this allows us to remove lots of unchanging stuff from the script.

        boolean nativeLauncher = false;
        boolean verbose = false;
        
        readASEnv();
        
        for(String arg : args)
        {
            if("display".equalsIgnoreCase(arg))
                nativeLauncher = true;
            
            if("verbose".equalsIgnoreCase(arg))
                verbose = true;
        }
        
        // Set system props needed by launcher
        // first add all the ones that were passed in from a caller...
        
        Enumeration keys = extraProps.propertyNames();
        
        while(keys.hasMoreElements())
        {
            String key = (String)keys.nextElement();
            String value = extraProps.getProperty(key);
            System.setProperty(key, value);
        }
        
        
        // set props but only if NOT in extraProps already!
        setInstanceRoot(extraProps);
        
        if(extraProps.getProperty(LaunchConstants.JAVA_HOME_PROP) == null)
            System.setProperty(LaunchConstants.JAVA_HOME_PROP, System.getProperty(SystemPropertyConstants.JAVA_ROOT_PROPERTY));
        if(extraProps.getProperty(LaunchConstants.LOG_MGR_PROP) == null)
            System.setProperty(LaunchConstants.LOG_MGR_PROP, LaunchConstants.LOG_MGR_VALUE);
        if(extraProps.getProperty(LaunchConstants.ENV_FACTORY_PROP) == null)
            System.setProperty(LaunchConstants.ENV_FACTORY_PROP, LaunchConstants.ENV_FACTORY_VALUE);
        if(extraProps.getProperty(LaunchConstants.PROCESS_NAME_PROP) == null)
            System.setProperty(LaunchConstants.PROCESS_NAME_PROP, AS9_INTERNAL_SERVER_PROFILE);
        if( extraProps.getProperty(LaunchConstants.LAUNCHER_RETURN_PROP) == null)
        {
            if(verbose && nativeLauncher)
                System.setProperty(LaunchConstants.LAUNCHER_RETURN_PROP, LaunchConstants.LAUNCHER_RETURN_HOLD_VALUE);
            else
                System.setProperty(LaunchConstants.LAUNCHER_RETURN_PROP, LaunchConstants.LAUNCHER_RETURN_RETURN_VALUE);
        }
        
    
voidpreProcess(java.lang.String[] args)

        // We are being called from a script or native code
        // i.e. we are in our own JVM and we need to look at System Properties
        // and repackage them for the public preprocess method
        // These are the ONLY properties needed to start any kind of server.
        // this allows us to change the script to pass these in as args instead
        // of System Properties later -- by changing this code and the scripts at
        // the same time.
        
        // these Strings ugly-up the code so let's make nice neat abbreviations here!
        String irpTag       = SystemPropertyConstants.INSTANCE_ROOT_PROPERTY;
        String procNameTag  = LaunchConstants.PROCESS_NAME_PROP;
        String inTag        = SystemPropertyConstants.SERVER_NAME;
        String rootTag      = SystemPropertyConstants.INSTALL_ROOT_PROPERTY;
        String retTag       = LaunchConstants.LAUNCHER_RETURN_PROP;
        
        Properties props = new Properties();
        
        copySystemProp(props, irpTag);
        copySystemProp(props, procNameTag);
        copySystemProp(props, inTag);
        copySystemProp(props, rootTag);
        copySystemProp(props, retTag);
        
        preProcess(args, props);
    
public java.lang.Processprocess(java.lang.String[] args, java.lang.String[] SecurityInfo)

        Process process = null;
        try
        {
            _returnValue=1;
            securityInfo = SecurityInfo;
            
            if(securityInfo != null)
                System.setProperty(PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY, "true");
            // store args for later use (e.g. debug, verbose)
            setArgs(args);
            
            // look for Debug system property
            if (System.getProperty("Debug") != null)
            {
                // turn on debug, this option was added to help developers
                // debug the their code what adding/modifying tasks that are executed via
                // the ProcessLauncher
                bDebug=true;
            }
            
            // Set verboseMode early so logger will also show verbose output.
            // Each command type will take care of adding it again, but that is okay.
            // Only set it not being displayed for native launcher
            if (isVerboseEnabled() && !isDisplayEnabled())
            {
                // add to System.properties for config conditional adds
                System.setProperty(VERBOSE_SYSTEM_PROPERTY, "true");
            }
            
            String passArg=null;
            if (args != null && args.length >= 1)
            {
                passArg=args[0];
            }
            else
            {
                passArg=LAUNCHER_START_ACTION;
            }
            
            // Build command and pass in action
            if (bDebug) System.out.println("ASLauncher Building command ..");
            Command command=buildCommand(passArg);
            
            // execute command that was build and pass in action
            if (bDebug) System.out.println("ASLauncher Executing command ..");
            
            // if no exception, should have executed properly or logged errors
            _returnValue=0;
            
            if(externalLogfileHandler != null)
            {
                getLogger().removeHandler(externalLogfileHandler);
                externalLogfileHandler.close();
                externalLogfileHandler = null;
            }            
            
            process = executeCommand(command, passArg);
            
        }
        catch (ConfigException ce)
        {
            // try to log but the log main not be set up properly if domain.xml had a problem
            getLogger().log(Level.SEVERE, "launcher.config_exception", ce);
            ce.printStackTrace();
        }
        catch (Exception e)
        {
            // show in server log
            getLogger().log(Level.SEVERE, "enterprise.launcher_exception_startup",e);
            e.printStackTrace();
        }
        return process;
    
public voidprocess(java.lang.String[] args)
process - This is the method that performs the work of creating the java command line to execute. This is where the BootStrap launcher and general launcher execute the same track WBN Oct 2006 -- I'd like to change the signature to return int -- but it is public so I'll klunk up a instance variable instead.

        process(args, null);
    
private voidreadASEnv()

        // WBN October 2006
        // see if we have a config root set
        String configRoot=System.getProperty(SystemPropertyConstants.CONFIG_ROOT_PROPERTY);
        
        if (configRoot == null)
        {
            // no config root try and make one from install root
            configRoot=System.getProperty(SystemPropertyConstants.INSTALL_ROOT_PROPERTY) + File.separator + "config";
            // let's go ahead and set the sys prop now...
            System.setProperty(SystemPropertyConstants.CONFIG_ROOT_PROPERTY, configRoot);
        }
        
        if(!FileUtils.safeIsDirectory(configRoot))
        {
            String message = "Can't find the AS configuration script.  This script normally lives in <install>/config and is named asenv";
            
            if(OS.isWindows())
                message += ".bat";
            message += "\nYou need to set these 2 System Properties: \n" + SystemPropertyConstants.INSTALL_ROOT_PROPERTY + "=your-install-directory\n" +
                    SystemPropertyConstants.CONFIG_ROOT_PROPERTY + "=your-config-directory\n";
            throw new ASLauncherException(message);
        }
        ASenvPropertyReader reader = new ASenvPropertyReader(configRoot);
        reader.setSystemProperties();
    
private java.lang.StringremoveJVMStopOption(java.lang.String jvmOption)

        if (jvmOption.startsWith("-X"))
        {
            jvmOption = "";
        }
        if (jvmOption.startsWith("-server"))
        {
            jvmOption = "-client";
        }
        return jvmOption;
    
private voidsendInputToProcessInput(java.io.InputStream in, java.lang.Process subProcess)

        // return if no input
        if (in == null || subProcess == null) return;
        
        PrintWriter out=null;
        BufferedReader br=null;
        try
        {
            // open the output stream on the process which excepts the input
            out = new PrintWriter(new BufferedWriter(
                    new OutputStreamWriter(subProcess.getOutputStream())));
            
            // WBN October 2006
            // See if there is input available first.  If not use standard strings...
            
            
            // read in each line and resend it to sub process
            br=new BufferedReader(new InputStreamReader(System.in));
            
            if(br.ready())
            {
                String sxLine=null;
                while ((sxLine=br.readLine()) != null)
                {
                    // get input lines from process if any
                    out.println(sxLine);
                    if (bDebug) System.out.println("Feeding in Line:" + sxLine);
                }
            }
            else
            {
                out.println("");
                out.println("");
                out.println("changeit");
            }
            out.flush();
        }
        catch (Exception e)
        {
            getLogger().log(Level.INFO,"WRITE TO INPUT ERROR", e);
        }
        finally
        {
            try
            {
                if (out != null) out.close();
            }
            catch (Throwable t)
            {}
        }
    
protected voidsetArgs(java.lang.String[] args)

        ArrayList<String> processedArgs = new ArrayList<String>(args.length);
        // Process the args
        for(String arg : args)
        {
            // allow "debug" to be used as an arg in startserv script...
            if(arg.equalsIgnoreCase("debug"))
                System.setProperty("Debug", "true");
            
            processedArgs.add(arg);
        }
        _args = processedArgs.toArray(new String[processedArgs.size()]);
    
private voidsetDomainName(com.sun.enterprise.config.serverbeans.Domain domain)

        try
        {
            ElementProperty ep = domain.getElementPropertyByName(DOMAIN_NAME_XML_PROPERTY);
            
            if(ep == null)
                throw new ConfigException("The property, " + DOMAIN_NAME_XML_PROPERTY + ", was null");
            
            String domainName = ep.getValue();
            
            if(domainName == null || domainName.length() < 1)
                throw new ConfigException("The value of the property, " + DOMAIN_NAME_XML_PROPERTY + ", was null or empty");
            
            System.setProperty(DOMAIN_NAME_SYSTEM_PROPERTY, domainName);
        }
        catch(ConfigException ce)
        {
            throw ce;
        }
        catch(Exception e)
        {
            throw new ConfigException("Error getting " + DOMAIN_NAME_XML_PROPERTY + " from domain.xml", e);
        }
    
private voidsetInstanceRoot(java.util.Properties callerProps)

        String irpTag = SystemPropertyConstants.INSTANCE_ROOT_PROPERTY; // too ugly to type!
        String irp = callerProps.getProperty(irpTag);
        
        if(irp != null)
            System.setProperty(irpTag, irp);
        
        
        // if the user is running a script stand-alone the instance-root may be
        // something like "./startserv".  We need to convert it to a real path
        
        irp = System.getProperty(irpTag);
        
        if(irp == null || irp.length() <= 0 )
        {
            // if we are being called from stand-alone java or a script -- they need to
            // do a -DirpTag=...
            // if we are called from PEInstancesManager, it has been set.  If it isn't
            // set let's fail right now!
            throw new ASLauncherException("Missing System Property: " + irpTag);
        }
        
        File f = new File(irp);
        try
        {
            irp = f.getCanonicalPath();
        }
        catch(Exception e)
        {
            irp = f.getAbsolutePath();
        }
        
        System.setProperty(irpTag, irp);
    
private voidsetPromptForIdentity(com.sun.enterprise.admin.servermgmt.launch.ASLauncher$Command command)

        // WBN -- the current xml files wires in the sys prop: com.sun.aas.promptForIdentity=true
        // we may not want that so we remove it if it is false in the "real" System Properties
        // note that if it is set to ANYTHING it is taken as "true", even if it is set to "false"!
        // so it has to be gone for it to be "false"
        
        Object prompt = null;
        
        // may be null!
        String actual = System.getProperty(PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY);
        String startsWith = "-D" + PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY;
        // remove it in all cases and add it back only if actual is not null...
        
        for(Object o : command._systemVariables)
        {
            String s = (String)o;
            
            if(s.startsWith(startsWith))
            {
                prompt = o;
                break;
            }
        }
        // remove it always
        if(prompt != null)
            command._systemVariables.remove(prompt);
        
        // put it back in if it is set in System Properties
        if(actual != null)
            command.addSystemVariable(PROPMPT_FOR_IDENTITY_SYSTEM_PROPERTY, actual);
    
public voidsetRefreshConfigContext(boolean refresh)

        this.refreshConfigContext = refresh;
    
voidwriteSecurityInfoToProcess(java.lang.Process p)

        if(securityInfo == null) // impossible!
            return;
        
        PrintWriter out = null;
        try
        {
            out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(p.getOutputStream())));
            
            for(String s : securityInfo)
            {
                if(bDebug)
                {
                    System.out.println("InputLine ->" + s + "<-");
                }
                out.println(s);
            }
            out.flush();
        }
        finally
        {
            try
            {
                out.close();
            }
            catch (Throwable t)
            {
                // nothing to do
            }
        }