FileDocCategorySizeDatePackage
MainWithModuleSupport.javaAPI DocGlassfish v2 API70129Tue Jul 24 05:01:32 BST 2007com.sun.enterprise.appclient

MainWithModuleSupport

public class MainWithModuleSupport extends Object
This is the main that gets invoked first. It initializes the application client container for an application client component and other related items and then invokes the real main written by the application developer. This version of the logic supports a new format of jar file as created by the revised client jar creation logic on the back-end. Under certain conditions the jar file will be expanded into a temporary directory so that, among other things, persistence unit handling can occur.

Fields Summary
private static final String
CLIENT
private static final String
NAME
private static final String
MAIN_CLASS
private static final String
TEXT_AUTH
private static final String
XML_PATH
private static final String
ACC_CONFIG_XML
private static final String
DEFAULT_CLIENT_CONTAINER_XML
private static final String
SUNACC_XML_URL
private static final String
NO_APP_INVOKE
private static final String
USER
private static final String
PASSWORD
private static final String
PASSWORD_FILE
private static final String
LOGIN_NAME
private static final String
LOGIN_PASSWORD
private static final String
DASH
private static final String
lineSep
public static final String
APPCLIENT_IIOP_DEFAULTHOST_PROPERTYNAME
Property names used on the server to send these values to a Java Web Start client and by the ACC when running under Java Web Start to retrieve them
public static final String
APPCLIENT_IIOP_DEFAULTPORT_PROPERTYNAME
public static final String
APPCLIENT_IIOP_FAILOVER_ENDPOINTS_PROPERTYNAME
public static final String
APPCLIENT_PROBE_CLASSNAME_PROPERTYNAME
public static final String
APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME
Prop name for keeping temporary files
public static final String
APPCLIENT_ISJWS_PROPERTYNAME
property name used to indicate that Java Web Start is active
public static final String
APPCLIENT_DOWNLOAD_HOST_PROPERTYNAME
property name used to indicate the Java Web Start download host name
public static final String
SUN_ACC_SECURITY_CONFIG_PROPERTY
Prop used when running under Java Web Start to point to a temporarily-created default file. This property appears in the template for the default sun-acc.xml content. Logic below assigns a value to it and then uses it to substitute in the template to create the actual content. (This is not a property set in the environment and then retrieved by Main.)
private static final String
LOGIN_CONF_FILE_PREFIX
Used for constructing the name of the temp file that will hold the login conf. content
private static final String
LOGIN_CONF_FILE_SUFFIX
private static final String
LOGIN_CONF_PROPERTY_NAME
The system property to be set that is later read by jaas
private static final String
DEFAULT_TEMPLATE_PREFIX
Names of templates for default config for Java Web Start
private static final String
SUN_ACC_DEFAULT_TEMPLATE
private static final String
WSS_CLIENT_CONFIG_TEMPLATE
private static final String
LOGIN_CONF_TEMPLATE
private static final String
WSS_CLIENT_CONFIG_PREFIX
Naming for temporary files created under Java Web Start
private static final String
WSS_CLIENT_CONFIG_SUFFIX
private static final String
SUN_ACC_PREFIX
private static final String
SUN_ACC_SUFFIX
private static final String[]
LOCAL_LAUNCH_PERSISTENCE_JAR_PATHS
Paths to persistence JARs added to the classpath for the class loader created by the ACC
private static final String
ORB_INITIAL_HOST_PROPERTYNAME
private static final String
ORB_INITIAL_PORT_PROPERTYNAME
protected static Logger
_logger
protected final boolean
debug
protected com.sun.enterprise.util.i18n.StringManager
localStrings
protected boolean
guiAuth
protected boolean
runClient
protected String
host
protected String
port
protected String[]
args
Saved arguments so they are accessible from the AWT thread if needed
protected boolean
isJWS
Records whether ACC is currently running under Java Web Start
protected boolean
retainTempFiles
Records whether temp config files created while running under Java Web Start should be retained
protected String
clientJar
protected String
displayName
protected String
mainClass
protected String
xmlPath
protected String
accConfigXml
protected String
jwsACCConfigXml
protected Vector
appArgs
protected String
classFileFromCommandLine
protected boolean
useTextAuth
private static boolean
lb_enabled
Constructors Summary
public MainWithModuleSupport(String[] args)

        /*
         *The appclient script triggers this constructor, so find the persistence
         *JARs in the local directories.  During a Java Web Start launch the
         *other constructor is invoked with the already-located JAR URLs.
         */
        this(args, locateLocalPersistenceJARs());
    
public MainWithModuleSupport(String[] args, URL[] persistenceJarURLs)

        /*
         *Temporarily use a cheap memory logger to hold any messages created
         *until we can configure the real logger using the configuration settings.
         */
        BufferedLogger tempLogger = prepareBufferedLogging();
        
        /*
         *Assign the temp logger to _logger so methods that need to log don't 
         *need to know if they are doing so before the real logger is set up.
         */
        _logger = tempLogger;
        
        prepareJWSSettings();
        
	try {
            /*
             *Handle any command line arguments intended for the ACC (as opposed to
             *the client itself) and save the returned args intended for the client.
             */
            appArgs = processCommandLine(args);

            /*
             *Find the class name to be run if the user has asked to run a .class
             *file as the client.
             */
            String classNameForClassFile = determineClassNameForClassFileLaunch(clientJar, isJWS, mainClass, classFileFromCommandLine);
        
            /*
             *Choose and validate the XML configuration file to use, which depends on the 
             *-xml and -configxml command line arguments as well as whether this
             *is a Java Web Start launch or not.
             */
            String xmlPathToUse = chooseConfigFile(xmlPath, accConfigXml, isJWS);
            validateXMLFile(xmlPathToUse);

            /*
             *The configuration file just chosen may assign logging settings.
             *Prepare logger using those settings and also flush any records sent to the 
             *temp logger to the new, real one.
             */
            _logger = prepareLogging(tempLogger, xmlPathToUse, isJWS);

            /*
             *Locate the app client: in a user-specified jar or directory,
             *an implied directory (i.e., user is running a .class file), or the
             *Java Web Start downloaded jar file.
             */
            File appClientJarOrDir = locateAppclientJarOrDir(clientJar, classNameForClassFile, isJWS);

            /*
             *Set up the default login config for a Java Web Start launch.
             */
            prepareJWSLoginConfig();

            Utility.checkJVMVersion();
            prepareSecurity();

            Throwable terminatingException = null;
            AppClientInfo appClientInfo = null;

            ClassLoader jcl = null;
        
	    Switch.getSwitch().setProviderManager(ProviderManager.getProviderManager());
            /*
             * Set the container type before initializing the ORB so that ORB 
             * initializers can correctly identify which container type this is.
             */
            Switch.getSwitch().setContainerType(Switch.APPCLIENT_CONTAINER);

	    // added for ClientContainer.xml initialization
            // The returned properties will be null if load balancing is on or
            // non-null and containing the initial host and port properties if
            // load balancing is off. 
            //
            // Note that setTargetServerProperties must be invoked before the
            // the initial context is instantiated.
	    Properties iiopProperties = setTargetServerProperties(xmlPathToUse);
	    
	    int exitCode = 0; // 0 for success
            prepareURLStreamHandling();
	    
            /*
             *The "info" object for the app client collects together common behavior
             *regardless of how the app client was specified (as an archive file,
             *as a directory, or as a .class file) and - if not a .class file - 
             *what type of module (an ear or an app client jar).
             *
             *Creating this info object also may extract the ear or jar into
             *a temporary directory, for example for use by persistence unit
             *handling, and may also prepare the persistence unit handling if
             *that is required.
             */
            // log the endpoint address(es) to be used, per Jagadesh's request
            _logger.log(Level.INFO, "acc.endpoints", 
                    lb_enabled ? System.getProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY) : 
                        iiopProperties.getProperty(ORB_INITIAL_HOST_PROPERTYNAME) + ":" + 
                        iiopProperties.getProperty(ORB_INITIAL_PORT_PROPERTYNAME));

            //ic creation for enabling the ORB intialization with the 
	    //right host:port values (bug 6397533).  The InitialContext must 
            //not be instantiated before setTargetServerProperties has run.
	    InitialContext ic = AppContainer.initializeNaming(iiopProperties);

            appClientInfo = AppClientInfoFactory.buildAppClientInfo(isJWS, _logger, appClientJarOrDir, mainClass, displayName, classFileFromCommandLine, persistenceJarURLs);
            
            ApplicationClientDescriptor appDesc = appClientInfo.getAppClient();
            
            final AppContainer container = createAppContainer(appDesc, guiAuth);
            Cleanup cleanup = prepareShutdownCleanup(container, appClientInfo);

            // Set the authenticator which is called back when a
            // protected web resource is requested and authentication data is
            // needed.
            Authenticator.setDefault(new HttpAuthenticator(container));

            /*
             *The container needs to use the new classloader to locate any
             *user-specified security callback handler.
             */
            jcl = appClientInfo.getClassLoader();
            String appMainClass = container.preInvoke(ic, jcl);
            
            /*
             *The new classloader must be set up as the current context class
             *loader for injection to work.  During a Java Web Start launch
             *the class loader in the event dispatcher thread must also be
             *changed.
             */
            Thread.currentThread().setContextClassLoader(jcl);
            if (isJWS) {
                setClassLoaderForEDT(jcl);
            }

            /*
             *Load the main class of the app client.
             */
            Class cl = loadMainClientClass(jcl, appMainClass);
            
            //This is required for us to enable interrupt jaxws service 
            //creation calls
            System.setProperty("javax.xml.ws.spi.Provider", 
                               "com.sun.enterprise.webservice.spi.ProviderImpl");
            
            // Inject the application client's injectable resources.  This
            // must be done after java:comp/env is initialized but before
            // the application client's main class is invoked.  Also make
            // sure the injection mgr will clean up during shutdown.
            InjectionManager injMgr = Switch.getSwitch().getInjectionManager();
            cleanup.setInjectionManager(injMgr, cl, appDesc);
            
            injMgr.injectClass(cl, appDesc);            
                            
            if(runClient) {
                String[] applicationArgs = appArgs.toArray(new String[appArgs.size()]);
                Utility.invokeApplicationMain(cl, applicationArgs);
                _logger.info("Application main() returned; GUI elements may be continuing to run");
            }


            // System.exit is not called if application main returned
            // without error.  Registered shutdown hook will perform
            // container cleanup
        } catch (java.lang.reflect.InvocationTargetException ite) {
            Throwable tt = ite.getTargetException();
            _logger.log(Level.WARNING, "acc.app_exception", tt);
            throw new RuntimeException(ite);
        } catch (UserError ue) {
            ue.displayAndExit();
        } catch (Throwable t) {
            if (t instanceof javax.security.auth.login.FailedLoginException){

               _logger.info("acc.login_error");
                boolean isGui =
                    Boolean.valueOf
                        (System.getProperty ("auth.gui","true")).booleanValue();
                String errorMessage =
                    localStrings.getString
                        ("main.exception.loginError",
                         "Incorrect login and/or password");

                if (isGui) {
                    GUIErrorDialog ged = new GUIErrorDialog (errorMessage);
                    ged.show ();
                }
            }

            _logger.log(Level.WARNING, "acc.app_exception", t);

            if (t instanceof javax.naming.NamingException) {
                _logger.log(Level.WARNING, "acc.naming_exception_received");
            }
            throw new RuntimeException(t);
        } finally {
	    shutDownSystemAdapters();
        }      
    
Methods Summary
private java.lang.StringchooseConfigFile(java.lang.String xmlPath, java.lang.String accConfigXml, boolean isJWS)
Selects which config file to use, based on which are specified and whether this is a Java Web Start launch.

param
xmlPath config file path as specified on the command line
param
accConfigXml fall-back config file containing defaults
param
isJWS indicates if this is a Java Web Start launch
return
the appropriate config file path

        String pathToUse = null;
        boolean isFine = _logger.isLoggable(Level.FINE);
        
        if (xmlPath != null) {
            pathToUse = xmlPath;
            if (isFine) {
                _logger.fine(localStrings.getString("appclient.configFrom", XML_PATH, pathToUse));
            }
        } else if (accConfigXml != null ) {
            pathToUse = accConfigXml; //use AS_ACC_CONFIG
            if (isFine) {
                _logger.fine(localStrings.getString("appclient.configFrom", ACC_CONFIG_XML, pathToUse));
            }
        } else if (isJWS) {
            /*
             *Neither -xml nor -configxml were present and this is a Java 
             *Web Start invocation.  Use
             *the alternate mechanism to create the default config.
             */
            try {
                String jwsACCConfigXml = prepareJWSConfig();
                if (jwsACCConfigXml != null) {
                    pathToUse = jwsACCConfigXml;
                    if (isFine) {
                        _logger.fine(localStrings.getString("appclient.configFromJWSTemplate"));
                    }
                }
            } catch (Throwable thr) {
                throw new RuntimeException(localStrings.getString("appclient.errorPrepConfig"), thr);
            }
        }
        return pathToUse;
    
private com.sun.enterprise.appclient.AppContainercreateAppContainer(ApplicationClientDescriptor appDesc, boolean guiAuth)

        AppContainer result = new AppContainer(appDesc, guiAuth);
        if(result == null) {
            _logger.log(Level.WARNING, "acc.no_client_desc",
                        (displayName == null) ? mainClass : displayName);

            System.exit(1);
        }
        return result;
    
private java.lang.StringdetermineClassNameForClassFileLaunch(java.lang.String clientJar, boolean isJWS, java.lang.String mainClass, java.lang.String classFileFromCommandLine)
Decides what class name the user specified IF the user has asked to run a .class file as the client.

param
clientJar path to the client jar from the command line processing
param
isJWS indicates if the current execution was launched via Java Web Start technology
param
mainClass main class name as possibly specified on the command line
param
classFileFromCommandLine class file spec from the command line (if present)
return
class name to be run if the user has chosen a .class file; null otherwise

        String result = null;
        boolean isFine = _logger.isLoggable(Level.FINE);
        if(clientJar == null && ! isJWS) {
            // ok, if the first parameter was the appclient class, let's check 
            // for its existence.
            String value;
            
            /*
             *To run a .class file, the user omits the -client option and 
             *specifies either -mainclass <class-name> or provides
             *the class file path as an argument.  In the second case the
             *value will have been captured as classFileFromCommandLine during
             *command line processing.
             */
            if (classFileFromCommandLine != null) {
                value = classFileFromCommandLine;
                if (isFine) {
                    _logger.fine(localStrings.getString("appclient.classNameFromArg", classFileFromCommandLine));
                }
            } else {
                value = mainClass;
                if (isFine) {
                    _logger.fine(localStrings.getString("appclient.classNameFromMainClass", mainClass));
                }
            }
            if (value.endsWith(".class")) {
                result = value.substring(0, value.length()-".class".length());
            } else {
                result = value;                
            }
            
            String path = result.replace('.", File.separatorChar) + ".class";
            File file = new File(path);
            if (!file.isAbsolute()) {
                file = new File(System.getProperty("user.dir"),  path);
            }
            /*
             *We have tried to identify the class file to use based on either
             *the -mainclass value (with -client omitted) or the value of the
             *first command-line argument.  If we cannot find the class in the user's 
             *home directory (and we already know this is not a JWS launch because
             *we are inside the "if") then the user has
             *not entered a valid command or has specified a class we cannot find.
             */
            if (!file.exists()) {
                throw new UserError(localStrings.getString("appclient.cannotFindClassFile", result, file.getAbsolutePath()));
            } else {
                if (isFine) {
                    _logger.fine(localStrings.getString("appclient.usingClassFile", file.getAbsolutePath()));
                }
            }
        }
        return result;
   
private voidensureAtMostOneOfNameAndMainClass()
Makes sure that at most one of the -name and -mainclass arguments appeared on the command line.

throws
IllegalArgumentException if both appeared

        if (mainClass != null && displayName != null) {
            throw new UserError(localStrings.getString("appclient.mainclassOrNameNotBoth"));
        }
    
private java.io.FilefindAppClientFileForJWSLaunch()
Locate the app client jar file during a Java Web Start launch.

return
File object for the client jar file

        /*
         *The JWSACCMain class has already located the downloaded app client
         *jar file and set a property pointing to it.  
         */
       File containingJar = new File(System.getProperty("com.sun.aas.downloaded.appclient.jar"));
        _logger.fine("Location of appclient jar file: " + containingJar.getAbsolutePath());
        return containingJar;
    
private java.io.FilefindContainingJar(java.lang.String target)

        File result = null;
        
        /*
         *Use the current class loader to find the resource.
         */
        URL resourceURL = getClass().getResource(target);
        if (resourceURL != null) {
            URI uri = resourceURL.toURI();
            String scheme = uri.getScheme();
            String ssp = uri.getSchemeSpecificPart();
            if (scheme.equals("jar")) {
                /*
                 *The scheme-specific part will look like "file:<file-spec>!/<path-to-class>.class"
                 *so we need to isolate the scheme and the <file-spec> part.  
                 *The subscheme (the scheme within the jar) precedes the colon
                 *and the file spec appears after it and before the exclamation point.
                 */
                int colon = ssp.indexOf(':");
                String subscheme = ssp.substring(0, colon);
                int excl = ssp.indexOf('!");
                String containingJarPath = ssp.substring(colon + 1, excl);
                result = new File(containingJarPath);
            } else if (scheme.equals("file")) {
                /*
                 *The URI is already a file, so the part we want is the part
                 *up to but not including the resource name we were looking for
                 in the first place..
                 */
                int resourceNamePosition = ssp.indexOf(target);
                String containingFilePath = ssp.substring(0, resourceNamePosition);
                result = new File(containingFilePath);
            } else {
                throw new IllegalArgumentException(resourceURL.toExternalForm());
            }
        }
        return result;
    
private java.lang.StringgetRequiredCommandOptionValue(java.lang.String[] args, java.lang.String optionName, java.util.concurrent.atomic.AtomicInteger position, java.lang.String errorKey)
Returns the next unused argument as a String value, so long as there is a next argument and it does not begin with a dash which would indicate the next argument.

param
position the mutable current position in the argument array
param
errorKey the message key for looking up the correct error if the next argument cannot be used as a value

        String result = null;
        /*
         *Make sure there is at least one more argument and that it does not
         *start with a dash.  Either of those cases means the user omitted
         *the required value.
         */
        if(position.get() < args.length && !args[position.get()].startsWith(DASH)) {
            result = args[position.getAndIncrement()];
        } else {
            throw new UserError(localStrings.getString(errorKey));
        }
        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine(localStrings.getString("appclient.optionValueIs", optionName, result));
        }
        return result;
    
private java.lang.StringgetRequiredUniqueCommandOptionValue(java.lang.String[] args, java.lang.String optionName, java.lang.String currentValue, java.util.concurrent.atomic.AtomicInteger position, java.lang.String errorKey)
Returns the next unused argument (if present and not prefixed with a dash) as a string value as long as the current value of the argument expected is not already set.

param
optionName the name of the option being processed
param
currentValue the current value of the argument
param
position the mutable current position in the argument array
param
errorKey the message key for looking up the correct error if the next argument cannot be used as a value
throws
IllegalArgumentException

        if (currentValue != null) {
            throw new UserError(localStrings.getString("appclient.duplicateValue", optionName, currentValue));
        }
        return getRequiredCommandOptionValue(args, optionName, position, errorKey);
    
private java.lang.StringgetUsage()

        return localStrings.getString(
            "main.usage",
            "appclient [ -client <appjar> | <classfile> ] [-mainclass <appClass-name>|-name <display-name>] [-xml <xml>] [-textauth] [-user <username>] [-password <password>|-passwordfile <password-file>] [app-args]");
    
public static booleanisLoadBalancingEnabled()
Indicates whether ORB load balancing is turned on.

Should not be invoked until after setTargetServerProperties has been invoked. This method is intended for use by ORB initializers, which in turn are run during the instantiation of the InitialContext. The InitialContext is created (in the constructor for this class) after setTargetServerProperties has been run, so this precondition should be met.

return
true if load balancing was specified or implied, false otherwise

    
                                                                                   
        
        return lb_enabled;
    
private java.lang.ClassloadMainClientClass(java.lang.ClassLoader jcl, java.lang.String clientMainClassName)
Loads the app client's main class given its name and the loader to use.

param
jcl the class loader to use for loading the client's main class
param
clientMainClassName the name of the client's main class
return
the Class object for the client's main class
throws
RuntimeException (wraps the ClassNotFoundException) if the main class cannot be loaded

        Class result = null;
        try {
            result = jcl.loadClass(clientMainClassName);
        } catch (java.lang.ClassNotFoundException cnf) {
            String errorMessage = localStrings.getString
                ("appclient.mainclass.not.found", clientMainClassName);
            throw new RuntimeException(errorMessage, cnf);
        }
        _logger.log(Level.INFO, "acc.load_app_class", clientMainClassName);           
        return result;
    
private java.lang.StringloadPasswordFromFile(java.lang.String fileName)

        InputStream inputStream = null;
        try {
            inputStream = new BufferedInputStream(new FileInputStream(fileName));
            Properties props = new Properties();
            props.load(inputStream);
            return props.getProperty("PASSWORD");
        } finally {
            if (inputStream != null) {
                inputStream.close();
            }
        }
    
private java.io.FilelocateAppclientJarOrDir(java.lang.String clientJar, java.lang.String className, boolean isJWS)
Locates the jar or directory that contains the app client main class.

param
clientJar path to the client jar file (if specified)
param
className the main class name for the app client
param
isJWS indicates if this is a Java Web Start launch
return
File object for the jar or directory containing the app client main class

        File result = null;
        boolean isFine = _logger.isLoggable(Level.FINE);
        /*
         *For Java Web Start launches, locate the jar file implicitly.
         *Otherwise, if the user omitted the clientjar argument (and the
         *code has gotten this far) then the user must have used the
         *first argument as the name of the class in ${user.dir} to run.  If
         *the user actually specified the clientjar argument, then use that
         *value as the file spec for the client jar.
         */
        if (isJWS) {
            /*
             *Java Web Start case.
             */
            result = findAppClientFileForJWSLaunch();
            if (isFine) {
                _logger.fine(localStrings.getString("appclient.JWSAppClientFile", result.getAbsolutePath()));
            }
        } else if (clientJar==null) {
            /*
             *First-argument-as-class-name case
             */
            File userDir = new File(System.getProperty("user.dir"));
            File appClientClass = new File(userDir, className);
            result = appClientClass.getParentFile();
            if (isFine) {
                _logger.fine(localStrings.getString("appclient.classFileAppClientFile", result.getAbsolutePath()));
            }
        } else {
            /*
             *Normal case - clientjar argument specified.
             */
            result = new File(clientJar);
            if (isFine) {
                _logger.fine(localStrings.getString("appclient.clientJarAppClientFile", result.getAbsolutePath()));
            }
            /*
             *Make sure the user-specified file - client JAR or .class - exists.
             */
            if ( ! result.exists() ) {
                UserError ue = UserError.formatUserError(
                        localStrings.getString("appclient.cannotFindJarFile"), 
                        result.getAbsolutePath());
                throw ue;
            }
            
        }
        return result;
    
private static java.net.URL[]locateLocalPersistenceJARs()

        try {
            URL[] localPersistenceJARURLs = new URL[LOCAL_LAUNCH_PERSISTENCE_JAR_PATHS.length];
            int slot = 0;
            for (String jarPath : LOCAL_LAUNCH_PERSISTENCE_JAR_PATHS) {
                File jarFile = new File(jarPath);
                localPersistenceJARURLs[slot++] = jarFile.toURI().toURL();
            }
            return localPersistenceJARURLs;
        } catch (MalformedURLException mue) {
            /*
             *This is not a recoverable error, so to minimize changes convert it
             *to an unchecked runtime exception.
             */
            throw new RuntimeException(mue);
        }
    
private voidlogArgument(java.lang.String arg)

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine(localStrings.getString("appclient.argumentValueFound", arg));
        }
    
private voidlogClassFileArgument(java.lang.String classFile)

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine(localStrings.getString("appclient.classFileUsed", classFile));
        }
    
private voidlogClientArgs(java.util.Vector clientArgs)

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine(localStrings.getString("appclient.clientArgs", clientArgs.toString()));
        }
    
private voidlogOption(java.lang.String optionName)
Reports that the specified option name has been processed from the command line.

param
optionName the String name of the option

        if (_logger.isLoggable(Level.FINE)) {
            _logger.fine(localStrings.getString("appclient.valuelessOptionFound", optionName));
        }
    
private com.sun.enterprise.appclient.MainWithModuleSupport$BufferedLoggerprepareBufferedLogging()
Creates a memory-based logger for holding log messages that may occur before the user's logging set-up is read.

return
a Logger that buffers its log records in memory.

        /*
         *The buffered logger adds a handler automatically during instantiation.
         */
        BufferedLogger logger = new BufferedLogger();
        return logger;
    
private java.lang.StringprepareJWSConfig()
Sets up the user-provided or default sun-acc.xml and wss-client-config.xml configurations.

return
the file name of the sun-acc.xml file

        return prepareJWSDefaultConfig();
    
private java.lang.StringprepareJWSDefaultConfig()
Creates temporary files for use as default sun-acc.xml and wss-client-config.xml configurations.

return
the file name of the temporary sun-acc.xml file

        String result = null;
        
        /*
         *Retrieve the sun-acc and wss-client-config templates.
         */
        String sunACCTemplate = Util.loadResource(this.getClass(), SUN_ACC_DEFAULT_TEMPLATE);
        String wssClientConfigTemplate = Util.loadResource(this.getClass(), WSS_CLIENT_CONFIG_TEMPLATE);
        
        /*
         *Prepare the property names and values for substitution in the templates.  Some
         *of the properties are specified in the environment already, so use those
         *as defaults and just add the extra ones.
         */
        Properties tokenValues = new Properties(System.getProperties());
        
        /**
         *Create the wss client config defaults, then write them to a temporary file.
         */
        String wssClientConfig = Util.replaceTokens(wssClientConfigTemplate, tokenValues);
        File wssClientConfigFile = Util.writeTextToTempFile(wssClientConfig, WSS_CLIENT_CONFIG_PREFIX, WSS_CLIENT_CONFIG_SUFFIX, retainTempFiles);
        _logger.fine("Temporary wss-client-config.xml file: " + wssClientConfigFile.getAbsolutePath() + lineSep);
//        pendingLogFine.append("Temporary wss-client-config.xml file: " + wssClientConfigFile.getAbsolutePath() + lineSep);
        
        /*
         *Now that the wss temp file is created, insert its name into the default
         *sun-acc text and write that to another temp file.
         *
         *On Windows, the backslashes in the path will be consumed by the replaceTokens method which will
         *interpret them as quoting the following character.  So replace each \ with \\ first.  All the slashes
         *have to do with quoting a slash to the Java compiler, then quoting it again to the regex
         *processor.
         */
        String quotedConfigFileSpec = wssClientConfigFile.getAbsolutePath().replaceAll("\\\\", "\\\\\\\\");
        tokenValues.setProperty(SUN_ACC_SECURITY_CONFIG_PROPERTY, quotedConfigFileSpec);
        
        String sunaccContent = Util.replaceTokens(sunACCTemplate, tokenValues);
        File sunaccFile = Util.writeTextToTempFile(sunaccContent, SUN_ACC_PREFIX, SUN_ACC_SUFFIX, retainTempFiles);
        _logger.fine("Temporary sun-acc.xml file: " + sunaccFile.getAbsolutePath());
//        pendingLogFine.append("Temporary sun-acc.xml file: " + sunaccFile.getAbsolutePath());
        
        return sunaccFile.getAbsolutePath();
    
private voidprepareJWSDefaultLoginConfig()
Extracts the default login.conf file into a temporary file and assigns the java.security.auth.login.config property accordingly.

        /*
         *For a Java Web Start launch, the default login configuration is in a
         *template bundled in the app server's jws jar file.  Putting it there
         *allows this method to locate it simply by loading it as a resource, whereas
         *the command-line appclient invocation needs to be able to find the
         *file on-disk somewhere.
         *
         *The contents of the template are loaded and then written to a temp file and
         *that temp file location is assigned to the system property that directs
         *JAAS to the login configuration.
         */
        String configContent = Util.loadResource(this.getClass(), LOGIN_CONF_TEMPLATE);
        File configFile = Util.writeTextToTempFile(configContent, LOGIN_CONF_FILE_PREFIX, LOGIN_CONF_FILE_SUFFIX, retainTempFiles);
        String configFilePath = configFile.getAbsolutePath();
        _logger.fine("Temporary appclientlogin.conf file: " + configFilePath);
        System.setProperty(LOGIN_CONF_PROPERTY_NAME, configFilePath);
    
private voidprepareJWSLoginConfig()
Prepares the JAAS login configuration for a Java Web Start invocation.

        /*
         *If this is a Java Web Start invocation, prepare the user-specified
         *or default login configuration.
         */
        if (isJWS) {
            try {
                prepareJWSDefaultLoginConfig();
            } catch (Throwable thr) {
                throw new RuntimeException(localStrings.getString("appclient.errorPrepJWSLogginConfig"), thr);
            }
        }        
    
private voidprepareJWSSettings()
Chooses behavior of a Java Web Start launch based on property settings.

Sets the instance variables isJWS and retainTempFiles as side-effects

        isJWS = Boolean.getBoolean(APPCLIENT_ISJWS_PROPERTYNAME);
        retainTempFiles = Boolean.getBoolean(APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME);
    
private java.util.logging.LoggerprepareLogging(com.sun.enterprise.appclient.MainWithModuleSupport$BufferedLogger tempLogger, java.lang.String xmlPathToUse, boolean isJWS)
Creates the appropriate logger, using any settings in the config file.

If any logging information has been buffered into the temporary memory-based logger, flush it to the newly-created log.

param
xmlPathToUse config file path
param
isJWS indicates if this is a Java Web Start launch

        // make sure the default logger for ACCLogManager is set
        Logger result = LogDomains.getLogger(LogDomains.ACC_LOGGER);

        LogManager logMgr = LogManager.getLogManager();
        if (logMgr instanceof ACCLogManager) {
            ((ACCLogManager) logMgr).init(xmlPathToUse);
        }
        
        /*
         *Transfer any records from the temporary logger to the new one.
         */
        tempLogger.pushTo(result);
        
        return result;
    
private java.lang.ClassLoaderpreparePreliminaryClassLoader(java.io.File jarOrDir)
Creates a class loader for the app client, using the jar or directory which contains the main class.

param
jarOrDir the File object for the directory or jar file containing the main class
return
ClassLoader for use by the app client

        ClassLoader result = null;
        URL[] urls = new URL[1];
        urls[0] = jarOrDir.toURI().toURL();
        /*
         *Set the parent of the new class loader to the current loader.  
         *The Java Web Start-managed class path is implemented in the 
         *current loader, so it must remain on the loader stack.
         */
        ClassLoader currentCL = Thread.currentThread().getContextClassLoader();
        result = new URLClassLoader(urls, currentCL);
//        Thread.currentThread().setContextClassLoader(jcl);
        return result;
    
private voidprepareSecurity()
Set up the security manager and keystores/truststores.

        /*
         *If -textauth was specified, no need to look for the auth.gui
         *setting since -textauth takes precedence.
         */
        if ( ! useTextAuth) {
            guiAuth = Boolean.valueOf
            (System.getProperty("auth.gui", "true")).booleanValue();
        }
        
        /* security init */
        SecurityManager secMgr = System.getSecurityManager();
        if (!isJWS && secMgr != null &&
                !(J2EESecurityManager.class.equals(secMgr.getClass()))) {
            J2EESecurityManager mgr = new J2EESecurityManager();
            System.setSecurityManager(mgr);
        }
        if (_logger.isLoggable(Level.INFO)) {
            if (secMgr != null) {
                _logger.info("acc.secmgron");
            } else {
                _logger.info("acc.secmgroff");
            }
        }

        try{
            /* setup keystores.
             * This is required, for appclients that want to use SSL, especially
             * HttpsURLConnection to perform Https.
             */
            SSLUtils.initStoresAtStartup();
        } catch (Exception e){
             /* This is not necessarily an error. This will arise
              * if the user has not specified keystore/truststore properties.
              * and does not want to use SSL.
              */
            if(_logger.isLoggable(Level.FINER)){
                // show the exact stack trace
                _logger.log(Level.FINER, "main.ssl_keystore_init_failed", e);
            } else{
                // just log it as a warning.
                _logger.log(Level.WARNING, "main.ssl_keystore_init_failed");
            }
        }

	try {
	    /* setup jsr 196 factory
	     * define default factory if it is not already defined
	     */
	    String defaultFactory = java.security.Security.getProperty
		(AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY);
	    if (defaultFactory == null) {
		java.security.Security.setProperty
		    (AuthConfigFactory.DEFAULT_FACTORY_SECURITY_PROPERTY,
		     GFAuthConfigFactory.class.getName());
	    }

	} catch (Exception e) {
	    //  XXX put string in catablog
	    _logger.log(Level.WARNING, "main.jmac_default_factory");
	}

    
private static com.sun.enterprise.appclient.MainWithModuleSupport$CleanupprepareShutdownCleanup(com.sun.enterprise.appclient.AppContainer container, AppClientInfo appClientInfo)
Adds a shutdown hook to make sure clean-up work runs at JVM exit.

        // Ensure cleanup is performed, even if
        // application client calls System.exit().
        Cleanup cleanup = new Cleanup();
        Runtime runtime = Runtime.getRuntime();
        runtime.addShutdownHook(cleanup);
        cleanup.setAppContainer(container);
        cleanup.setAppClientInfo(appClientInfo);
        return cleanup;
    
private static voidprepareURLStreamHandling()
Assigns the URL stream handler factory.

        // Set the HTTPS URL stream handler.
        java.security.AccessController.doPrivileged(new
                                       java.security.PrivilegedAction() {
                public Object run() {
                    URL.setURLStreamHandlerFactory(new
                                       HttpsURLStreamHandlerFactory());
                    return null;
                }
            });
    
private java.util.VectorprocessCommandLine(java.lang.String[] args)
Processes any command-line arguments, setting up static variables for use later in the processing.

As side-effects, these variables may be assigned values:

    clientJar displayName mainClass xmlPath accConfigXml guiAuth runClient classFileFromCommandLine System property j2eelogin.name System property j2eelogin.password

param
args the command-line arguments passed to the ACC
return
arguments to be passed to the actual client (with ACC arguments removed)

        Vector<String> clientArgs = new Vector<String>();

        AtomicInteger i = new AtomicInteger();
        String arg = null;
        
        // Parse command line arguments.
        if(args.length < 1) {
            usage();
        } else {
            while(i.get() < args.length) {
                arg = args[i.getAndIncrement()];
                if(arg.equals(CLIENT)) {
                    clientJar = getRequiredCommandOptionValue(args, CLIENT, i, "appclient.clientWithoutValue");
                } else if (arg.equals(NAME)) {
                    displayName = getRequiredCommandOptionValue(args, NAME, i, "appclient.nameWithoutValue");
                    ensureAtMostOneOfNameAndMainClass();
                } else if(arg.equals(MAIN_CLASS)) {
                    mainClass = getRequiredCommandOptionValue(args, MAIN_CLASS, i, "appclient.mainClassWithoutValue");
                    ensureAtMostOneOfNameAndMainClass();
                } else if(arg.equals(XML_PATH) ) {
                    xmlPath = getRequiredUniqueCommandOptionValue(args, XML_PATH, xmlPath, i, "appclient.xmlWithoutValue");
                } else if(arg.equals(ACC_CONFIG_XML) ) {
                    accConfigXml = getRequiredUniqueCommandOptionValue(args, ACC_CONFIG_XML, accConfigXml, i, "appclient.accConfigXmlWithoutValue");
                } else if(arg.equals(TEXT_AUTH)) {
                    // Overrides legacy auth.gui setting.
                    useTextAuth = true;
                    logOption(TEXT_AUTH);
                } else if(arg.equals(NO_APP_INVOKE)) {
                    runClient = false;
                    logOption(NO_APP_INVOKE);
                } else if(arg.equals(USER)) {
                    String userNameValue = getRequiredCommandOptionValue(args, USER, i, "appclient.userWithoutValue");
                    System.setProperty(LOGIN_NAME, userNameValue);
                } else if(arg.equals(PASSWORD)) {
                    String passwordValue = getRequiredCommandOptionValue(args, PASSWORD, i, "appclient.passwordWithoutValue");
                    System.setProperty(LOGIN_PASSWORD, passwordValue);
                } else if (arg.equals(PASSWORD_FILE)) {
                    String passwordFileValue = getRequiredCommandOptionValue(args, PASSWORD_FILE, i, "appclient.passwordFileWithoutValue");
                    try {
                        System.setProperty(LOGIN_PASSWORD,
                            loadPasswordFromFile(passwordFileValue));
                    } catch(IOException ex) {
                        throw new UserError(localStrings.getString("appclient.errorReadingFromPasswordFile", passwordFileValue), ex);
                    }
                } else {
                    clientArgs.add(arg);
                    logArgument(arg);
                }
            }
            

            String uname = System.getProperty(LOGIN_NAME);
            String upass = System.getProperty(LOGIN_PASSWORD);
            if( uname != null || upass != null ) {
                UsernamePasswordStore.set(uname, upass);
            }



            /*If this is not a Java Web Start launch, the user may have asked 
             *to execute a .class file by omitting the -client argument.  In this
             *case the user either specifies the name only of the class to run
             *using -mainclass or omits -mainclass and specifies the path to 
             *the .class file as the first command-line argument that would 
             *otherwise be passed to the actual client.  In this second
             *case, the first argument is removed from the list passed to the client.
             */
            if ((mainClass == null) && (clientJar == null) && ! isJWS) {
                /*
                 *Make sure there is at least one argument ready to be passed
                 *to the client before trying
                 *to use the first one as the class file spec.
                 */
                if (clientArgs.size() > 0) {
                    classFileFromCommandLine = clientArgs.elementAt(0);
                    clientArgs.removeElementAt(0);
                    logClassFileArgument(classFileFromCommandLine);
                } else {
                    usage();
                }
            }
        }
        logClientArgs(clientArgs);
        return clientArgs;
    
private voidsetClassLoaderForEDT(java.lang.ClassLoader loader)
Sets the class loader for the event dispatcher thread in case of a Java Web Start launch.

        SwingUtilities.invokeAndWait(new Runnable() {
            private ClassLoader theCL;
            public void run() {
                Thread.currentThread().setContextClassLoader(loader);
                Toolkit tk = Toolkit.getDefaultToolkit();
                EventQueue eq = tk.getSystemEventQueue();
                eq.push(new EventQueue());
            }
          }
        );
    
private static voidsetSSLData(com.sun.enterprise.config.clientbeans.ClientContainer cc)

        try {
            // Set the SSL related properties for ORB
            TargetServer tServer = cc.getTargetServer(0);
            // TargetServer is required.
	    //temp solution to target-server+ change in DTD
            // assuming that multiple servers can be specified but only 1st
	    // first one will be used.
	    Security security = tServer.getSecurity();
	    if (security == null) {
		_logger.fine("No Security input set in ClientContainer.xml");
		// do nothing
		return;
	    }
	    Ssl ssl = security.getSsl();
	    if (ssl == null) {
		_logger.fine("No SSL input set in ClientContainer.xml");
		// do nothing
		return;
		
	    }
	    //XXX do not use NSS in this release
	    //CertDb   certDB  = security.getCertDb();
	    SSLUtils.setAppclientSsl(ssl);	
	} catch (Exception ex) {

        }
    
private java.util.PropertiessetTargetServerProperties(java.lang.String clientXmlLocation)

        
        boolean isEndpointPropertySpecifiedByUser = false;
        String loadBalancingPolicy = null;
        
        Properties result = new Properties();
        
        StringBuilder completeEndpointList = new StringBuilder();
        
        //FIXME: may need to set the context in switch or generic context. but later
        try {
            if(clientXmlLocation == null || clientXmlLocation.equals("")) {
                clientXmlLocation = DEFAULT_CLIENT_CONTAINER_XML;
            }

	    // set for com.sun.enterprise.security.jauth.ConfigXMLParser
	    System.setProperty(SUNACC_XML_URL, clientXmlLocation);
             _logger.log(Level.INFO, "acc.using_xml_location", clientXmlLocation);
	       
            ConfigContext ctx = ConfigFactory.createConfigContext(
		clientXmlLocation, true,
		false, false,
		ClientContainer.class, 
		new ACCEntityResolver());

            ClientContainer cc = ClientBeansFactory.getClientBean(ctx);
        
	    host = cc.getTargetServer(0).getAddress();
	    port = cc.getTargetServer(0).getPort();

	    //check for targetServerEndpoints 
	    TargetServer[] tServer = cc.getTargetServer();
	    String targetServerEndpoints = null;
	    for (int i = 0; i < tServer.length; i++) {
	        if (targetServerEndpoints == null) {
		    targetServerEndpoints = tServer[i].getAddress() + 
		    ":" + tServer[i].getPort();
		} else {
		    targetServerEndpoints = targetServerEndpoints + "," + 
		      tServer[i].getAddress() + 
		      ":" + tServer[i].getPort();
                    lb_enabled = true;
		}
	    }
		
            setSSLData(cc);

            //FIXME: what do we do about realm
            ClientCredential cCrd = cc.getClientCredential();
            if(cCrd != null) {
                String uname = null;
                String upass = null;

                // if user entered user/password from command line,
                // it take percedence over the xml file. - y.l. 05/15/02
                if (System.getProperty(LOGIN_NAME) == null) {
                    _logger.config("using login name from client container xml...");
                    //System.setProperty(LOGIN_NAME, cCrd.getUserName());
                    uname = cCrd.getUserName();
                }
                if (System.getProperty(LOGIN_PASSWORD) == null) {
                    _logger.config("using password from client container xml...");
                    //System.setProperty(LOGIN_PASSWORD, cCrd.getPassword());
                    upass = cCrd.getPassword();
                }
                if( uname != null || upass != null ) {
                    UsernamePasswordStore.set(uname, upass);
                }
            }
		String endpoints_property = null;
	    // Check if client requires SSL to be used
	    ElementProperty[] props = cc.getElementProperty();
	    for ( int i=0; i<props.length; i++ ) {
		if ( props[i].getName().equals("ssl") ) {
		    if ( props[i].getValue().equals("required") ) {
			(ORBManager.getCSIv2Props()).put(ORBManager.ORB_SSL_CLIENT_REQUIRED,
				       "true");
		    }
		}
		if ( props[i].getName().equals(S1ASCtxFactory.LOAD_BALANCING_PROPERTY) ) {
                    loadBalancingPolicy = props[i].getValue();
		    lb_enabled = true;
		}	
		if ( props[i].getName().equals(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY) ) {
                    isEndpointPropertySpecifiedByUser = true;
		    endpoints_property = props[i].getValue().trim();
		    lb_enabled = true;
		}
	    }    
            
            /*
             *If the endpoints property was not set in the XML file's property
             *settings, try to set it from the server's assignment in the JNLP document.
             */
	    String jwsEndpointsProperty = System.getProperty(Main.APPCLIENT_IIOP_FAILOVER_ENDPOINTS_PROPERTYNAME);
	    if (jwsEndpointsProperty != null) {
	        targetServerEndpoints = jwsEndpointsProperty;
                completeEndpointList.append(jwsEndpointsProperty);
		lb_enabled = true;
		_logger.fine("jwsEndpointsProperty = " + jwsEndpointsProperty);
	    } else {
	        /*
		 *Suppress the warning if the endpoints_property was set
		 *from the JNLP document, since that is in fact the preferred
		 *way to set the endpoints.
		 */
	        if (isEndpointPropertySpecifiedByUser){
                    _logger.warning("acc.targetserver.endpoints.warning");
                }
            
		_logger.fine("targetServerEndpoints = " + targetServerEndpoints + 
			     "endpoints_property = " + 
			     endpoints_property);	
		
                if (lb_enabled) {
                    completeEndpointList.append(targetServerEndpoints.trim());
                    if (endpoints_property != null) {
                        completeEndpointList.append(",").append(endpoints_property);
                    }
		}
	    }
            if (lb_enabled) {
                System.setProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY, completeEndpointList.toString());
                /*
                 * Honor any explicit setting of the load-balancing policy.
                 * Otherwise just defer to whatever default the ORB uses.
                 */
                if (loadBalancingPolicy != null) {
                    System.setProperty(S1ASCtxFactory.LOAD_BALANCING_PROPERTY, loadBalancingPolicy);
                }
                /*
                 * For load-balancing the Properties object is not used.  Rather,
                 * the ORB detects the system property settings.  So return a
                 * null for the LB case.
                 */
                result = null;
            } else {
                /*
                 * For the non-load-balancing case, the Properties object must
                 * contain the initial host and port settings for the ORB.
                 */
                result.setProperty(ORB_INITIAL_HOST_PROPERTYNAME, host);
                result.setProperty(ORB_INITIAL_PORT_PROPERTYNAME, port);
            }
            return result;
	} catch (ConfigException t) {
	    _logger.log(Level.WARNING,"acc.acc_xml_file_error" ,
			new Object[] {clientXmlLocation, t.getMessage()}); 
	    _logger.log(Level.FINE, "exception : " + t.toString(), t);
	    throw t;
	}
    
private voidshutDownSystemAdapters()

       try {
	    com.sun.enterprise.PoolManager poolmgr = 
	        Switch.getSwitch().getPoolManager();
	    if ( poolmgr != null ) {	
	        Switch.getSwitch().getPoolManager().killFreeConnectionsInPools();
	    }	
	} catch( Exception e ) {
	    //ignore
	}
        
	try {
            ConnectorRegistry registry = ConnectorRegistry.getInstance();
            ActiveResourceAdapter activeRar = registry.getActiveResourceAdapter
                                         (ConnectorRuntime.DEFAULT_JMS_ADAPTER);
            if (activeRar != null) {
                activeRar.destroy();
            }
        } catch (Exception e) {
            // Some thing has gone wrong. No problem
            _logger.fine("Exception caught while shutting down system adapter:"+e.getMessage());
        }
    
private voidusage()

        System.out.println(getUsage());
	System.exit(1);
    
private voidvalidateXMLFile(java.lang.String xmlFullName)

        if(xmlFullName == null || 
           xmlFullName.startsWith("-")){ // If no file name is given after -xml argument
            usage();
        }
        try {
            File f = new File(xmlFullName);
            if((f != null) && f.exists() && f.isFile() && f.canRead()){
                return;
            }else{// If given file does not exists
                xmlMessage(xmlFullName);
            }
        } catch (Exception ex) {
            xmlMessage(xmlFullName);
        }
    
private voidxmlMessage(java.lang.String xmlFullName)

        UserError ue = new UserError(localStrings.getString("main.cannot_read_clientContainer_xml", xmlFullName,
             "Client Container xml: " + xmlFullName + " not found or unable to read.\nYou may want to use the -xml option to locate your configuration xml."));
        ue.setUsage(getUsage());
        throw ue;