KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > appclient > MainWithModuleSupport


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23 package com.sun.enterprise.appclient;
24
25 import com.sun.appserv.naming.S1ASCtxFactory;
26 import com.sun.enterprise.appclient.AppContainer;
27 import com.sun.enterprise.appclient.HttpAuthenticator;
28 import com.sun.enterprise.appclient.jws.TemplateCache;
29 import com.sun.enterprise.appclient.jws.Util;
30 import com.sun.enterprise.config.clientbeans.CertDb;
31 import com.sun.enterprise.config.clientbeans.ClientBeansFactory;
32 import com.sun.enterprise.config.clientbeans.ClientContainer;
33 import com.sun.enterprise.config.clientbeans.ClientCredential;
34 import com.sun.enterprise.config.clientbeans.ElementProperty;
35 import com.sun.enterprise.config.clientbeans.Security;
36 import com.sun.enterprise.config.clientbeans.Ssl;
37 import com.sun.enterprise.config.clientbeans.TargetServer;
38 import com.sun.enterprise.config.ConfigContext;
39 import com.sun.enterprise.config.ConfigException;
40 import com.sun.enterprise.config.ConfigFactory;
41 import com.sun.enterprise.connectors.ActiveResourceAdapter;
42 import com.sun.enterprise.connectors.ConnectorRegistry;
43 import com.sun.enterprise.connectors.ConnectorRuntime;
44 import com.sun.enterprise.deployment.*;
45 import com.sun.enterprise.deployment.archivist.AppClientArchivist;
46 import com.sun.enterprise.deployment.archivist.ApplicationArchivist;
47 import com.sun.enterprise.deployment.archivist.Archivist;
48 import com.sun.enterprise.deployment.archivist.ArchivistFactory;
49 import com.sun.enterprise.deployment.deploy.shared.AbstractArchive;
50 import com.sun.enterprise.deployment.deploy.shared.Archive;
51 import com.sun.enterprise.deployment.deploy.shared.ArchiveFactory;
52 import com.sun.enterprise.deployment.deploy.shared.FileArchive;
53 import com.sun.enterprise.deployment.deploy.shared.InputJarArchive;
54 import com.sun.enterprise.deployment.interfaces.SecurityRoleMapperFactory;
55 import com.sun.enterprise.deployment.interfaces.SecurityRoleMapperFactoryMgr;
56 import com.sun.enterprise.InjectionManager;
57 import com.sun.enterprise.J2EESecurityManager;
58 import com.sun.enterprise.loader.EJBClassLoader;
59 import com.sun.enterprise.loader.InstrumentableClassLoader;
60 import com.sun.enterprise.naming.ProviderManager;
61 import com.sun.enterprise.security.GUIErrorDialog;
62 import com.sun.enterprise.security.SSLUtils;
63 import com.sun.enterprise.server.logging.ACCLogManager;
64 import com.sun.enterprise.Switch;
65 import com.sun.enterprise.util.FileUtil;
66 import com.sun.enterprise.util.i18n.StringManager;
67 import com.sun.enterprise.util.JarClassLoader;
68 import com.sun.enterprise.util.ORBManager;
69 import com.sun.enterprise.util.shared.ArchivistUtils;
70 import com.sun.enterprise.util.Utility;
71 import com.sun.logging.LogDomains;
72 import com.sun.web.server.HttpsURLStreamHandlerFactory;
73
74 import java.io.*;
75 import java.net.*;
76 import java.util.Iterator JavaDoc;
77 import java.util.Set JavaDoc;
78 import java.util.concurrent.atomic.AtomicInteger JavaDoc;
79 import java.util.jar.JarFile JavaDoc;
80 import java.util.logging.Handler JavaDoc;
81 import java.util.logging.Level JavaDoc;
82 import java.util.logging.LogRecord JavaDoc;
83 import java.util.logging.Logger JavaDoc;
84 import java.util.logging.LogManager JavaDoc;
85 import java.util.Properties JavaDoc;
86 import java.util.Vector JavaDoc;
87 import java.util.logging.MemoryHandler JavaDoc;
88 import java.util.logging.SimpleFormatter JavaDoc;
89 import javax.enterprise.deploy.shared.ModuleType JavaDoc;
90 import javax.naming.InitialContext JavaDoc;
91
92 /**
93  * This is the main that gets invoked first. It initializes the application
94  * client container for an application client component
95  * and other related items and then invokes the real main written by the
96  * application developer.
97  *
98  * This version of the logic supports a new format of jar file as created
99  * by the revised client jar creation logic on the back-end. Under certain
100  * conditions the jar file will be expanded into a temporary directory so
101  * that, among other things, persistence unit handling can occur.
102  */

103 public class MainWithModuleSupport {
104     
105     private static final String JavaDoc CLIENT = "-client";
106     private static final String JavaDoc NAME = "-name";
107     private static final String JavaDoc MAIN_CLASS = "-mainclass";
108     private static final String JavaDoc TEXT_AUTH = "-textauth";
109     private static final String JavaDoc XML_PATH = "-xml";
110     private static final String JavaDoc ACC_CONFIG_XML = "-configxml";
111     private static final String JavaDoc DEFAULT_CLIENT_CONTAINER_XML = "sun-acc.xml";
112     // duplicated in com.sun.enterprise.jauth.ConfigXMLParser
113
private static final String JavaDoc SUNACC_XML_URL = "sun-acc.xml.url";
114     private static final String JavaDoc NO_APP_INVOKE = "-noappinvoke";
115     //Added for allow user to pass user name and password through command line.
116
private static final String JavaDoc USER = "-user";
117     private static final String JavaDoc PASSWORD = "-password";
118     private static final String JavaDoc PASSWORD_FILE = "-passwordfile";
119     private static final String JavaDoc LOGIN_NAME = "j2eelogin.name";
120     private static final String JavaDoc LOGIN_PASSWORD = "j2eelogin.password";
121     private static final String JavaDoc DASH = "-";
122
123     private static final String JavaDoc lineSep = System.getProperty("line.separator");
124     
125     /**
126      * Property names used on the server to send these values to a Java Web Start client
127      * and by the ACC when running under Java Web Start to retrieve them
128      */

129     public static final String JavaDoc APPCLIENT_IIOP_DEFAULTHOST_PROPERTYNAME = "com.sun.aas.jws.iiop.defaultHost";
130     public static final String JavaDoc APPCLIENT_IIOP_DEFAULTPORT_PROPERTYNAME = "com.sun.aas.jws.iiop.defaultPort";
131     public static final String JavaDoc APPCLIENT_IIOP_FAILOVER_ENDPOINTS_PROPERTYNAME = "com.sun.aas.jws.iiop.failover.endpoints";
132     public static final String JavaDoc APPCLIENT_PROBE_CLASSNAME_PROPERTYNAME = "com.sun.aas.jws.probeClassName";
133     
134     /** Prop name for keeping temporary files */
135     public static final String JavaDoc APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME = "com.sun.aas.jws.retainTempFiles";
136     
137     /** property name used to indicate that Java Web Start is active */
138     public static final String JavaDoc APPCLIENT_ISJWS_PROPERTYNAME = "com.sun.aas.jws.isJWS";
139     
140     /** property name used to indicate the Java Web Start download host name */
141     public static final String JavaDoc APPCLIENT_DOWNLOAD_HOST_PROPERTYNAME = "com.sun.aas.jws.download.host";
142     
143     /** Prop used when running under Java Web Start to point to a temporarily-created default file.
144      *This property appears in the template for the default sun-acc.xml content. Logic below
145      *assigns a value to it and then uses it to substitute in the template to create the
146      *actual content. (This is not a property set in the environment and then retrieved by Main.)
147     */

148     public static final String JavaDoc SUN_ACC_SECURITY_CONFIG_PROPERTY = "security.config.file";
149     
150     /** Used for constructing the name of the temp file that will hold the login conf. content */
151     private static final String JavaDoc LOGIN_CONF_FILE_PREFIX = "login";
152     private static final String JavaDoc LOGIN_CONF_FILE_SUFFIX = ".conf";
153     
154     /** The system property to be set that is later read by jaas */
155     private static final String JavaDoc LOGIN_CONF_PROPERTY_NAME = "java.security.auth.login.config";
156     
157     /** Names of templates for default config for Java Web Start */
158     private static final String JavaDoc DEFAULT_TEMPLATE_PREFIX = "jws/templates/";
159     private static final String JavaDoc SUN_ACC_DEFAULT_TEMPLATE = DEFAULT_TEMPLATE_PREFIX + "default-sun-accTemplate.xml";
160     private static final String JavaDoc WSS_CLIENT_CONFIG_TEMPLATE = DEFAULT_TEMPLATE_PREFIX + "default-wss-client-configTemplate.xml";
161     private static final String JavaDoc LOGIN_CONF_TEMPLATE = DEFAULT_TEMPLATE_PREFIX + "appclientlogin.conf";
162     
163     /** Naming for temporary files created under Java Web Start */
164     private static final String JavaDoc WSS_CLIENT_CONFIG_PREFIX = "wsscc";
165     private static final String JavaDoc WSS_CLIENT_CONFIG_SUFFIX = ".xml";
166     private static final String JavaDoc SUN_ACC_PREFIX = "sunacc";
167     private static final String JavaDoc SUN_ACC_SUFFIX = ".xml";
168     
169     protected static Logger JavaDoc _logger;
170
171     protected final boolean debug = false;
172     protected StringManager localStrings =
173                             StringManager.getManager(MainWithModuleSupport.class);
174     protected boolean guiAuth = false; // unless the user sets the auth.gui prop and does not use -textauth
175
protected boolean runClient=true;
176
177     protected String JavaDoc host;
178
179     protected String JavaDoc port;
180
181     /** Saved arguments so they are accessible from the AWT thread if needed */
182     protected String JavaDoc [] args;
183
184     /** Records whether ACC is currently running under Java Web Start */
185     protected boolean isJWS;
186     
187     /** Records whether temp config files created while running under Java Web Start should be retained */
188     protected boolean retainTempFiles = false;
189
190     protected String JavaDoc clientJar = null;
191     protected String JavaDoc displayName = null;
192     protected String JavaDoc mainClass = null;
193     protected String JavaDoc xmlPath = null;
194     protected String JavaDoc accConfigXml = null;
195     protected String JavaDoc jwsACCConfigXml = null;
196     protected Vector JavaDoc<String JavaDoc> appArgs = new Vector JavaDoc<String JavaDoc>();
197     protected String JavaDoc classFileFromCommandLine = null;
198     protected boolean useTextAuth = false;
199     
200     public MainWithModuleSupport(String JavaDoc[] args) {
201
202         /*
203          *Temporarily use a cheap memory logger to hold any messages created
204          *until we can configure the real logger using the configuration settings.
205          */

206         BufferedLogger tempLogger = prepareBufferedLogging();
207         
208         /*
209          *Assign the temp logger to _logger so methods that need to log don't
210          *need to know if they are doing so before the real logger is set up.
211          */

212         _logger = tempLogger;
213         
214         prepareJWSSettings();
215         
216         /*
217          *Handle any command line arguments intended for the ACC (as opposed to
218          *the client itself) and save the returned args intended for the client.
219          */

220         appArgs = processCommandLine(args);
221         
222         /*
223          *Find the class name to be run if the user has asked to run a .class
224          *file as the client.
225          */

226         String JavaDoc classNameForClassFile = determineClassNameForClassFileLaunch(clientJar, isJWS, mainClass, classFileFromCommandLine);
227         
228         /*
229          *Choose and validate the XML configuration file to use, which depends on the
230          *-xml and -configxml command line arguments as well as whether this
231          *is a Java Web Start launch or not.
232          */

233         String JavaDoc xmlPathToUse = chooseConfigFile(xmlPath, accConfigXml, isJWS);
234         validateXMLFile(xmlPathToUse);
235
236         /*
237          *The configuration file just chosen may assign logging settings.
238          *Prepare logger using those settings and also flush any records sent to the
239          *temp logger to the new, real one.
240          */

241         _logger = prepareLogging(tempLogger, xmlPathToUse, isJWS);
242         
243         /*
244          *Set up the default login config for a Java Web Start launch.
245          */

246         prepareJWSLoginConfig();
247         
248         Utility.checkJVMVersion();
249         prepareSecurity();
250         
251         Throwable JavaDoc terminatingException = null;
252         AppClientInfo appClientInfo = null;
253         
254         ClassLoader JavaDoc jcl = null;
255         
256     try {
257         Switch.getSwitch().setProviderManager(ProviderManager.getProviderManager());
258         // added for ClientContainer.xml initialization
259
setTargetServerProperties(xmlPathToUse);
260         
261         int exitCode = 0; // 0 for success
262
prepareURLStreamHandling();
263         
264             /*
265              *Locate the app client: in a user-specified jar or directory,
266              *an implied directory (i.e., user is running a .class file), or the
267              *Java Web Start downloaded jar file.
268              */

269             File JavaDoc appClientJarOrDir = locateAppclientJarOrDir(clientJar, classNameForClassFile, isJWS);
270             
271             /*
272              *The "info" object for the app client collects together common behavior
273              *regardless of how the app client was specified (as an archive file,
274              *as a directory, or as a .class file) and - if not a .class file -
275              *what type of module (an ear or an app client jar).
276              *
277              *Creating this info object also may extract the ear or jar into
278              *a temporary directory, for example for use by persistence unit
279              *handling, and may also prepare the persistence unit handling if
280              *that is required.
281              */

282         Properties JavaDoc iiopProperties = setupIIOP();
283         //dummy ic creation for enabling the ORB intialization with the
284
//right host:port values (bug 6397533)
285
InitialContext JavaDoc ic = new InitialContext JavaDoc(iiopProperties);
286
287             appClientInfo = AppClientInfoFactory.buildAppClientInfo(isJWS, _logger, appClientJarOrDir, mainClass, displayName, classFileFromCommandLine);
288             
289             ApplicationClientDescriptor appDesc = appClientInfo.getAppClient();
290             
291             AppContainer container = createAppContainer(appDesc, guiAuth);
292             Cleanup cleanup = prepareShutdownCleanup(container, appClientInfo);
293
294             // Set the authenticator which is called back when a
295
// protected web resource is requested and authentication data is
296
// needed.
297
Authenticator.setDefault(new HttpAuthenticator(container));
298
299             String JavaDoc appMainClass = container.preInvoke(iiopProperties);
300
301             /*
302              *Load the main class of the app client.
303              */

304             jcl = appClientInfo.getClassLoader();
305             Class JavaDoc cl = loadMainClientClass(jcl, appMainClass);
306
307             /*
308              *The new classloader must be set up as the current context class
309              *loader for injection to work.
310              */

311             Thread.currentThread().setContextClassLoader(jcl);
312
313             //This is required for us to enable interrupt jaxws service
314
//creation calls
315
System.setProperty("javax.xml.ws.spi.Provider",
316                                "com.sun.enterprise.webservice.spi.ProviderImpl");
317             
318             // Inject the application client's injectable resources. This
319
// must be done after java:comp/env is initialized but before
320
// the application client's main class is invoked. Also make
321
// sure the injection mgr will clean up during shutdown.
322
InjectionManager injMgr = Switch.getSwitch().getInjectionManager();
323             cleanup.setInjectionManager(injMgr, cl, appDesc);
324             
325             injMgr.injectClass(cl, appDesc);
326                             
327             if(runClient) {
328                 String JavaDoc[] applicationArgs = appArgs.toArray(new String JavaDoc[appArgs.size()]);
329                 Utility.invokeApplicationMain(cl, applicationArgs);
330                 _logger.info("Application main() returned; GUI elements may be continuing to run");
331             }
332
333
334             // System.exit is not called if application main returned
335
// without error. Registered shutdown hook will perform
336
// container cleanup
337
} catch (java.lang.reflect.InvocationTargetException JavaDoc ite) {
338             Throwable JavaDoc tt = ite.getTargetException();
339             _logger.log(Level.WARNING, "acc.app_exception", tt);
340             throw new RuntimeException JavaDoc(ite);
341         } catch (Throwable JavaDoc t) {
342             if (t instanceof javax.security.auth.login.FailedLoginException JavaDoc){
343
344                _logger.info("acc.login_error");
345                 boolean isGui =
346                     Boolean.valueOf
347                         (System.getProperty ("auth.gui","true")).booleanValue();
348                 String JavaDoc errorMessage =
349                     localStrings.getString
350                         ("main.exception.loginError",
351                          "Incorrect login and/or password");
352
353                 if (isGui) {
354                     GUIErrorDialog ged = new GUIErrorDialog (errorMessage);
355                     ged.show ();
356                 }
357             }
358
359             _logger.log(Level.WARNING, "acc.app_exception", t);
360
361             if (t instanceof javax.naming.NamingException JavaDoc) {
362                 _logger.log(Level.WARNING, "acc.naming_exception_received");
363             }
364             throw new RuntimeException JavaDoc(t);
365         } finally {
366         shutDownSystemAdapters();
367 // if (terminatingException != null) {
368
// if (isJWS) {
369
// throw new RuntimeException(terminatingException);
370
// } else{
371
// System.exit(1);
372
// }
373
// }
374
}
375     }
376
377     /**
378      *Chooses behavior of a Java Web Start launch based on property settings.
379      *<p>
380      *Sets the instance variables isJWS and retainTempFiles as side-effects
381      */

382     private void prepareJWSSettings() {
383         isJWS = Boolean.getBoolean(APPCLIENT_ISJWS_PROPERTYNAME);
384         retainTempFiles = Boolean.getBoolean(APPCLIENT_RETAIN_TEMP_FILES_PROPERTYNAME);
385     }
386     
387     /**
388      *Set up the security manager and keystores/truststores.
389      */

390     private void prepareSecurity() {
391         /*
392          *If -textauth was specified, no need to look for the auth.gui
393          *setting since -textauth takes precedence.
394          */

395         if ( ! useTextAuth) {
396             guiAuth = Boolean.valueOf
397             (System.getProperty("auth.gui", "true")).booleanValue();
398         }
399         
400         /* security init */
401         SecurityManager JavaDoc secMgr = System.getSecurityManager();
402         if (!isJWS && secMgr != null &&
403                 !(J2EESecurityManager.class.equals(secMgr.getClass()))) {
404             J2EESecurityManager mgr = new J2EESecurityManager();
405             System.setSecurityManager(mgr);
406         }
407         if (_logger.isLoggable(Level.INFO)) {
408             if (secMgr != null) {
409                 _logger.info("acc.secmgron");
410             } else {
411                 _logger.info("acc.secmgroff");
412             }
413         }
414
415         com.sun.enterprise.security.KeyTool.initProvider();
416         try{
417             /* setup keystores.
418              * This is required, for appclients that want to use SSL, especially
419              * HttpsURLConnection to perform Https.
420              */

421             SSLUtils.initStoresAtStartup();
422         } catch (Exception JavaDoc e){
423              /* This is not necessarily an error. This will arise
424               * if the user has not specified keystore/truststore properties.
425               * and does not want to use SSL.
426               */

427             if(_logger.isLoggable(Level.FINER)){
428                 // show the exact stack trace
429
_logger.log(Level.FINER, "main.ssl_keystore_init_failed", e);
430             } else{
431                 // just log it as a warning.
432
_logger.log(Level.WARNING, "main.ssl_keystore_init_failed");
433             }
434         }
435     }
436
437     /**
438      *Loads the app client's main class given its name and the loader to use.
439      *@param jcl the class loader to use for loading the client's main class
440      *@param clientMainClassName the name of the client's main class
441      *@return the Class object for the client's main class
442      *@throws RuntimeException (wraps the ClassNotFoundException) if the main class cannot be loaded
443      */

444     private Class JavaDoc loadMainClientClass(ClassLoader JavaDoc jcl, String JavaDoc clientMainClassName) {
445         Class JavaDoc result = null;
446         try {
447             result = jcl.loadClass(clientMainClassName);
448         } catch (java.lang.ClassNotFoundException JavaDoc cnf) {
449             String JavaDoc errorMessage = localStrings.getString
450                 ("appclient.mainclass.not.found", clientMainClassName);
451             throw new RuntimeException JavaDoc(errorMessage, cnf);
452         }
453         _logger.log(Level.INFO, "acc.load_app_class", clientMainClassName);
454         return result;
455     }
456     
457     /**
458      *Creates the appropriate logger, using any settings in the config file.
459      *<p>
460      *If any logging information has been buffered into the temporary memory-based
461      *logger, flush it to the newly-created log.
462      *@param xmlPathToUse config file path
463      *@param isJWS indicates if this is a Java Web Start launch
464      */

465     private Logger JavaDoc prepareLogging(BufferedLogger tempLogger, String JavaDoc xmlPathToUse, boolean isJWS) {
466         // make sure the default logger for ACCLogManager is set
467
Logger JavaDoc result = LogDomains.getLogger(LogDomains.ACC_LOGGER);
468
469         LogManager logMgr = LogManager.getLogManager();
470         if (logMgr instanceof ACCLogManager) {
471             ((ACCLogManager) logMgr).init(xmlPathToUse);
472         }
473         
474         /*
475          *Transfer any records from the temporary logger to the new one.
476          */

477         tempLogger.pushTo(result);
478         
479         return result;
480     }
481
482     /**
483      *Processes any command-line arguments, setting up static variables for use
484      *later in the processing.
485      *<p>
486      *As side-effects, these variables may be assigned values:
487      *<ul>
488      *<le>clientJar
489      *<le>displayName
490      *<le>mainClass
491      *<le>xmlPath
492      *<le>accConfigXml
493      *<le>guiAuth
494      *<le>runClient
495      *<le>classFileFromCommandLine
496      *<le>System property j2eelogin.name
497      *<le>System property j2eelogin.password
498      *</ul>
499      *@param args the command-line arguments passed to the ACC
500      *@return arguments to be passed to the actual client (with ACC arguments removed)
501      */

502     private Vector JavaDoc<String JavaDoc> processCommandLine(String JavaDoc[] args) {
503         Vector JavaDoc<String JavaDoc> clientArgs = new Vector JavaDoc<String JavaDoc>();
504
505         AtomicInteger JavaDoc i = new AtomicInteger JavaDoc();
506         String JavaDoc arg = null;
507         
508         // Parse command line arguments.
509
if(args.length < 1) {
510             usage();
511         } else {
512             while(i.get() < args.length) {
513                 arg = args[i.getAndIncrement()];
514                 if(arg.equals(CLIENT)) {
515                     clientJar = getRequiredCommandOptionValue(args, CLIENT, i, "appclient.clientWithoutValue");
516                 } else if (arg.equals(NAME)) {
517                     displayName = getRequiredCommandOptionValue(args, NAME, i, "appclient.nameWithoutValue");
518                     ensureAtMostOneOfNameAndMainClass();
519                 } else if(arg.equals(MAIN_CLASS)) {
520                     mainClass = getRequiredCommandOptionValue(args, MAIN_CLASS, i, "appclient.mainClassWithoutValue");
521                     ensureAtMostOneOfNameAndMainClass();
522                 } else if(arg.equals(XML_PATH) ) {
523                     xmlPath = getRequiredUniqueCommandOptionValue(args, XML_PATH, xmlPath, i, "appclient.xmlWithoutValue");
524                 } else if(arg.equals(ACC_CONFIG_XML) ) {
525                     accConfigXml = getRequiredUniqueCommandOptionValue(args, ACC_CONFIG_XML, accConfigXml, i, "appclient.accConfigXmlWithoutValue");
526                 } else if(arg.equals(TEXT_AUTH)) {
527                     // Overrides legacy auth.gui setting.
528
useTextAuth = true;
529                     logOption(TEXT_AUTH);
530                 } else if(arg.equals(NO_APP_INVOKE)) {
531                     runClient = false;
532                     logOption(NO_APP_INVOKE);
533                 } else if(arg.equals(USER)) {
534                     String JavaDoc userNameValue = getRequiredCommandOptionValue(args, USER, i, "appclient.userWithoutValue");
535                     System.setProperty(LOGIN_NAME, userNameValue);
536                 } else if(arg.equals(PASSWORD)) {
537                     String JavaDoc passwordValue = getRequiredCommandOptionValue(args, PASSWORD, i, "appclient.passwordWithoutValue");
538                     System.setProperty(LOGIN_PASSWORD, passwordValue);
539                 } else if (arg.equals(PASSWORD_FILE)) {
540                     String JavaDoc passwordFileValue = getRequiredCommandOptionValue(args, PASSWORD_FILE, i, "appclient.passwordFileWithoutValue");
541                     try {
542                         System.setProperty(LOGIN_PASSWORD,
543                             loadPasswordFromFile(passwordFileValue));
544                     } catch(IOException ex) {
545                         throw new IllegalArgumentException JavaDoc(localStrings.getString("appclient.errorReadingFromPasswordFile", passwordFileValue), ex);
546                     }
547                 } else {
548                     clientArgs.add(arg);
549                     logArgument(arg);
550                 }
551             }
552             
553             /*If this is not a Java Web Start launch, the user may have asked
554              *to execute a .class file by omitting the -client argument. In this
555              *case the user either specifies the name only of the class to run
556              *using -mainclass or omits -mainclass and specifies the path to
557              *the .class file as the first command-line argument that would
558              *otherwise be passed to the actual client. In this second
559              *case, the first argument is removed from the list passed to the client.
560              */

561             if ((mainClass == null) && (clientJar == null) && ! isJWS) {
562                 /*
563                  *Make sure there is at least one argument ready to be passed
564                  *to the client before trying
565                  *to use the first one as the class file spec.
566                  */

567                 if (clientArgs.size() > 0) {
568                     classFileFromCommandLine = clientArgs.elementAt(0);
569                     clientArgs.removeElementAt(0);
570                     logClassFileArgument(classFileFromCommandLine);
571                 } else {
572                     usage();
573                 }
574             }
575         }
576         logClientArgs(clientArgs);
577         return clientArgs;
578     }
579
580     /**
581      *Returns the next unused argument as a String value, so long as there is
582      *a next argument and it does not begin with a dash which would indicate
583      *the next argument.
584      *@param position the mutable current position in the argument array
585      *@param errorKey the message key for looking up the correct error if the
586      *next argument cannot be used as a value
587      */

588     private String JavaDoc getRequiredCommandOptionValue(String JavaDoc [] args, String JavaDoc optionName, AtomicInteger JavaDoc position, String JavaDoc errorKey) {
589         String JavaDoc result = null;
590         /*
591          *Make sure there is at least one more argument and that it does not
592          *start with a dash. Either of those cases means the user omitted
593          *the required value.
594          */

595         if(position.get() < args.length && !args[position.get()].startsWith(DASH)) {
596             result = args[position.getAndIncrement()];
597         } else {
598             throw new IllegalArgumentException JavaDoc(localStrings.getString(errorKey));
599         }
600         if (_logger.isLoggable(Level.FINE)) {
601             _logger.fine(localStrings.getString("appclient.optionValueIs", optionName, result));
602         }
603         return result;
604     }
605     
606     /**
607      *Returns the next unused argument (if present and not prefixed with a dash)
608      *as a string value as long as the current value of the argument expected
609      *is not already set.
610      *@param optionName the name of the option being processed
611      *@param currentValue the current value of the argument
612      *@param position the mutable current position in the argument array
613      *@param errorKey the message key for looking up the correct error if the
614      *next argument cannot be used as a value
615      *@throws IllegalArgumentException
616      */

617     private String JavaDoc getRequiredUniqueCommandOptionValue(String JavaDoc [] args, String JavaDoc optionName, String JavaDoc currentValue, AtomicInteger JavaDoc position, String JavaDoc errorKey) {
618         if (currentValue != null) {
619             throw new IllegalArgumentException JavaDoc(localStrings.getString("appclient.duplicateValue", optionName, currentValue));
620         }
621         return getRequiredCommandOptionValue(args, optionName, position, errorKey);
622     }
623     /**
624      *Makes sure that at most one of the -name and -mainclass arguments
625      *appeared on the command line.
626      *@throws IllegalArgumentException if both appeared
627      */

628     private void ensureAtMostOneOfNameAndMainClass() {
629         if (mainClass != null && displayName != null) {
630             throw new IllegalArgumentException JavaDoc(localStrings.getString("appclient.mainclassOrNameNotBoth"));
631         }
632     }
633
634     /**
635      *Reports that the specified option name has been processed from the command line.
636      *@param optionName the String name of the option
637      */

638     private void logOption(String JavaDoc optionName) {
639         if (_logger.isLoggable(Level.FINE)) {
640             _logger.fine(localStrings.getString("appclient.valuelessOptionFound", optionName));
641         }
642     }
643     
644     private void logArgument(String JavaDoc arg) {
645         if (_logger.isLoggable(Level.FINE)) {
646             _logger.fine(localStrings.getString("appclient.argumentValueFound", arg));
647         }
648     }
649     
650     private void logClassFileArgument(String JavaDoc classFile) {
651         if (_logger.isLoggable(Level.FINE)) {
652             _logger.fine(localStrings.getString("appclient.classFileUsed", classFile));
653         }
654     }
655     
656     private void logClientArgs(Vector JavaDoc<String JavaDoc> clientArgs) {
657         if (_logger.isLoggable(Level.FINE)) {
658             _logger.fine(localStrings.getString("appclient.clientArgs", clientArgs.toString()));
659         }
660     }
661     
662     /**
663      *Decides what class name the user specified IF the user has asked to run
664      *a .class file as the client.
665      *
666      *@param clientJar path to the client jar from the command line processing
667      *@param isJWS indicates if the current execution was launched via Java Web Start technology
668      *@param mainClass main class name as possibly specified on the command line
669      *@param classFileFromCommandLine class file spec from the command line (if present)
670      *@return class name to be run if the user has chosen a .class file; null otherwise
671      */

672     private String JavaDoc determineClassNameForClassFileLaunch(String JavaDoc clientJar, boolean isJWS, String JavaDoc mainClass, String JavaDoc classFileFromCommandLine) {
673         String JavaDoc result = null;
674         boolean isFine = _logger.isLoggable(Level.FINE);
675         if(clientJar == null && ! isJWS) {
676             // ok, if the first parameter was the appclient class, let's check
677
// for its existence.
678
String JavaDoc value;
679             
680             /*
681              *To run a .class file, the user omits the -client option and
682              *specifies either -mainclass <class-name> or provides
683              *the class file path as an argument. In the second case the
684              *value will have been captured as classFileFromCommandLine during
685              *command line processing.
686              */

687             if (classFileFromCommandLine != null) {
688                 value = classFileFromCommandLine;
689                 if (isFine) {
690                     _logger.fine(localStrings.getString("appclient.classNameFromArg", classFileFromCommandLine));
691                 }
692             } else {
693                 value = mainClass;
694                 if (isFine) {
695                     _logger.fine(localStrings.getString("appclient.classNameFromMainClass", mainClass));
696                 }
697             }
698             if (value.endsWith(".class")) {
699                 result = value.substring(0, value.length()-".class".length());
700             } else {
701                 result = value;
702             }
703             
704             String JavaDoc path = result.replace('.', File.separatorChar) + ".class";
705             File JavaDoc file = new File JavaDoc(path);
706             if (!file.isAbsolute()) {
707                 file = new File JavaDoc(System.getProperty("user.dir"), path);
708             }
709             /*
710              *We have tried to identify the class file to use based on either
711              *the -mainclass value (with -client omitted) or the value of the
712              *first command-line argument. If we cannot find the class in the user's
713              *home directory (and we already know this is not a JWS launch because
714              *we are inside the "if") then the user has
715              *not entered a valid command or has specified a class we cannot find.
716              */

717             if (!file.exists()) {
718                 throw new IllegalArgumentException JavaDoc(localStrings.getString("appclient.cannotFindClassFile", result, file.getAbsolutePath()));
719             } else {
720                 if (isFine) {
721                     _logger.fine(localStrings.getString("appclient.usingClassFile", file.getAbsolutePath()));
722                 }
723             }
724         }
725         return result;
726    }
727     
728     /**
729      *Selects which config file to use, based on which are specified and whether
730      *this is a Java Web Start launch.
731      *@param xmlPath config file path as specified on the command line
732      *@param accConfigXml fall-back config file containing defaults
733      *@param isJWS indicates if this is a Java Web Start launch
734      *@return the appropriate config file path
735      */

736     private String JavaDoc chooseConfigFile(String JavaDoc xmlPath, String JavaDoc accConfigXml, boolean isJWS) {
737         String JavaDoc pathToUse = null;
738         boolean isFine = _logger.isLoggable(Level.FINE);
739         
740         if (xmlPath != null) {
741             pathToUse = xmlPath;
742             if (isFine) {
743                 _logger.fine(localStrings.getString("appclient.configFrom", XML_PATH, pathToUse));
744             }
745         } else if (accConfigXml != null ) {
746             pathToUse = accConfigXml; //use AS_ACC_CONFIG
747
if (isFine) {
748                 _logger.fine(localStrings.getString("appclient.configFrom", ACC_CONFIG_XML, pathToUse));
749             }
750         } else if (isJWS) {
751             /*
752              *Neither -xml nor -configxml were present and this is a Java
753              *Web Start invocation. Use
754              *the alternate mechanism to create the default config.
755              */

756             try {
757                 String JavaDoc jwsACCConfigXml = prepareJWSConfig();
758                 if (jwsACCConfigXml != null) {
759                     pathToUse = jwsACCConfigXml;
760                     if (isFine) {
761                         _logger.fine(localStrings.getString("appclient.configFromJWSTemplate"));
762                     }
763                 }
764             } catch (Throwable JavaDoc thr) {
765                 throw new RuntimeException JavaDoc(localStrings.getString("appclient.errorPrepConfig"), thr);
766             }
767         }
768         return pathToUse;
769     }
770     
771     /**
772      *Locates the jar or directory that contains the app client main class.
773      *@param clientJar path to the client jar file (if specified)
774      *@param className the main class name for the app client
775      *@param isJWS indicates if this is a Java Web Start launch
776      *
777      *@return File object for the jar or directory containing the app client main class
778      */

779     private File JavaDoc locateAppclientJarOrDir(String JavaDoc clientJar, String JavaDoc className, boolean isJWS) throws ClassNotFoundException JavaDoc, URISyntaxException {
780         File JavaDoc result = null;
781         boolean isFine = _logger.isLoggable(Level.FINE);
782         /*
783          *For Java Web Start launches, locate the jar file implicitly.
784          *Otherwise, if the user omitted the clientjar argument (and the
785          *code has gotten this far) then the user must have used the
786          *first argument as the name of the class in ${user.dir} to run. If
787          *the user actually specified the clientjar argument, then use that
788          *value as the file spec for the client jar.
789          */

790         if (isJWS) {
791             /*
792              *Java Web Start case.
793              */

794             result = findAppClientFileForJWSLaunch();
795             if (isFine) {
796                 _logger.fine(localStrings.getString("appclient.JWSAppClientFile", result.getAbsolutePath()));
797             }
798         } else if (clientJar==null) {
799             /*
800              *First-argument-as-class-name case
801              */

802             File JavaDoc userDir = new File JavaDoc(System.getProperty("user.dir"));
803             File JavaDoc appClientClass = new File JavaDoc(userDir, className);
804             result = appClientClass.getParentFile();
805             if (isFine) {
806                 _logger.fine(localStrings.getString("appclient.classFileAppClientFile", result.getAbsolutePath()));
807             }
808         } else {
809             /*
810              *Normal case - clientjar argument specified.
811              */

812             result = new File JavaDoc(clientJar);
813             if (isFine) {
814                 _logger.fine(localStrings.getString("appclient.clientJarAppClientFile", result.getAbsolutePath()));
815             }
816         }
817         return result;
818     }
819     
820     /**
821      *Creates a class loader for the app client, using the jar or directory
822      *which contains the main class.
823      *@param jarOrDir the File object for the directory or jar file containing the main class
824      *@return ClassLoader for use by the app client
825      */

826     private ClassLoader JavaDoc preparePreliminaryClassLoader(File JavaDoc jarOrDir) throws MalformedURLException {
827         ClassLoader JavaDoc result = null;
828         URL[] urls = new URL[1];
829         urls[0] = jarOrDir.toURI().toURL();
830         /*
831          *Set the parent of the new class loader to the current loader.
832          *The Java Web Start-managed class path is implemented in the
833          *current loader, so it must remain on the loader stack.
834          */

835         ClassLoader JavaDoc currentCL = Thread.currentThread().getContextClassLoader();
836         result = new URLClassLoader(urls, currentCL);
837 // Thread.currentThread().setContextClassLoader(jcl);
838
return result;
839     }
840
841     private AppContainer createAppContainer(ApplicationClientDescriptor appDesc, boolean guiAuth) {
842         AppContainer result = new AppContainer(appDesc, guiAuth);
843         if(result == null) {
844             _logger.log(Level.WARNING, "acc.no_client_desc",
845                         (displayName == null) ? mainClass : displayName);
846
847             System.exit(1);
848         }
849         return result;
850     }
851             
852
853     /**
854      *Adds a shutdown hook to make sure clean-up work runs at JVM exit.
855      */

856     private static Cleanup prepareShutdownCleanup(
857         AppContainer container, AppClientInfo appClientInfo) {
858         // Ensure cleanup is performed, even if
859
// application client calls System.exit().
860
Cleanup cleanup = new Cleanup();
861         Runtime JavaDoc runtime = Runtime.getRuntime();
862         runtime.addShutdownHook(cleanup);
863         cleanup.setAppContainer(container);
864         cleanup.setAppClientInfo(appClientInfo);
865         return cleanup;
866     }
867
868     /**
869      *Assigns the URL stream handler factory.
870      */

871     private static void prepareURLStreamHandling() {
872         // Set the HTTPS URL stream handler.
873
java.security.AccessController.doPrivileged(new
874                                        java.security.PrivilegedAction JavaDoc() {
875                 public Object JavaDoc run() {
876                     URL.setURLStreamHandlerFactory(new
877                                        HttpsURLStreamHandlerFactory());
878                     return null;
879                 }
880             });
881     }
882
883     private Properties JavaDoc setupIIOP() {
884         // log a machine name, port number per Jagadesh's request
885
_logger.log(Level.INFO, "acc.orb_host_name", host);
886         _logger.log(Level.INFO, "acc.orb_port_number", port);
887
888         Properties JavaDoc props = new Properties JavaDoc();
889         props.put("org.omg.CORBA.ORBInitialHost", host);
890         props.put("org.omg.CORBA.ORBInitialPort", port);
891         return props;
892     }
893
894     private void addPersistenceSupport(File JavaDoc location, ApplicationClientDescriptor appDesc, InstrumentableClassLoader ldr) {
895         
896     }
897     
898     private void setTargetServerProperties(String JavaDoc clientXmlLocation)
899     throws ConfigException {
900         //FIXME: may need to set the context in switch or generic context. but later
901
try {
902             if(clientXmlLocation == null || clientXmlLocation.equals("")) {
903                 clientXmlLocation = DEFAULT_CLIENT_CONTAINER_XML;
904             }
905
906         // set for com.sun.enterprise.security.jauth.ConfigXMLParser
907
System.setProperty(SUNACC_XML_URL, clientXmlLocation);
908              _logger.log(Level.INFO, "acc.using_xml_location", clientXmlLocation);
909            
910             ConfigContext ctx = ConfigFactory.createConfigContext(
911         clientXmlLocation, true,
912         false, false,
913         ClientContainer.class,
914         new ACCEntityResolver());
915
916             ClientContainer cc = ClientBeansFactory.getClientBean(ctx);
917         
918         host = cc.getTargetServer(0).getAddress();
919         port = cc.getTargetServer(0).getPort();
920
921         //check for targetServerEndpoints
922
TargetServer[] tServer = cc.getTargetServer();
923         String JavaDoc targetServerEndpoints = null;
924         if (tServer.length > 1) {
925         for (int i = 0; i < tServer.length; i++) {
926             if (targetServerEndpoints == null) {
927             targetServerEndpoints = tServer[i].getAddress() +
928                 ":" + tServer[i].getPort();
929             } else {
930             targetServerEndpoints = targetServerEndpoints + "," +
931                 tServer[i].getAddress() +
932                 ":" + tServer[i].getPort();
933             }
934         }
935         }
936
937             setSSLData(cc);
938
939             //FIXME: what do we do about realm
940
ClientCredential cCrd = cc.getClientCredential();
941             if(cCrd != null) {
942                 // if user entered user/password from command line,
943
// it take percedence over the xml file. - y.l. 05/15/02
944
if (System.getProperty(LOGIN_NAME) == null) {
945                     _logger.config("using login name from client container xml...");
946                     System.setProperty(LOGIN_NAME, cCrd.getUserName());
947                 }
948                 if (System.getProperty(LOGIN_PASSWORD) == null) {
949                     _logger.config("using password from client container xml...");
950                     System.setProperty(LOGIN_PASSWORD, cCrd.getPassword());
951                 }
952             }
953         String JavaDoc endpoints_property = null;
954         // Check if client requires SSL to be used
955
ElementProperty[] props = cc.getElementProperty();
956         for ( int i=0; i<props.length; i++ ) {
957         if ( props[i].getName().equals("ssl") ) {
958             if ( props[i].getValue().equals("required") ) {
959             (ORBManager.getCSIv2Props()).put(ORBManager.ORB_SSL_CLIENT_REQUIRED,
960                        "true");
961             }
962         }
963         if ( props[i].getName().equals(S1ASCtxFactory.LOAD_BALANCING_PROPERTY) ) {
964             System.setProperty(props[i].getName(),props[i].getValue());
965         }
966         if ( props[i].getName().equals(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY) ) {
967             endpoints_property = props[i].getValue().trim();
968             
969         }
970         }
971             
972             /*
973              *If the endpoints property was not set in the XML file's property
974              *settings, try to set it from the server's assignment in the JNLP document.
975              */

976             String JavaDoc jwsEndpointsProperty = null;
977             if (endpoints_property == null) {
978                 jwsEndpointsProperty = System.getProperty(Main.APPCLIENT_IIOP_FAILOVER_ENDPOINTS_PROPERTYNAME);
979                 endpoints_property = jwsEndpointsProperty;
980             }
981             
982         _logger.fine("targetServerEndpoints = " + targetServerEndpoints +
983              "endpoints_property = " +
984              endpoints_property);
985         if (targetServerEndpoints == null && endpoints_property != null) {
986         System.setProperty(
987                    S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY,
988                    endpoints_property);
989
990         /*
991                  *Suppress the warning if the endpoints_property was set
992                  *from the JNLP document, since that is in fact the preferred
993                  *way to set the endpoints.
994                  */

995                 if (jwsEndpointsProperty == null) {
996                     _logger.warning("acc.targetserver.endpoints.warning");
997                 }
998         } else if (targetServerEndpoints != null && endpoints_property == null) {
999         System.setProperty(
1000                   S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY,
1001                   targetServerEndpoints.trim());
1002        } else if (targetServerEndpoints != null && endpoints_property != null) {
1003        System.setProperty(
1004                   S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY,
1005                   targetServerEndpoints.trim() + "," +
1006                   endpoints_property);
1007                /*
1008                 *Suppress the warning if the endpoints_property was set
1009                 *from the JNLP document, since that is in fact the preferred
1010                 *way to set the endpoints.
1011                 */

1012        if (jwsEndpointsProperty == null) {
1013                                    _logger.warning("acc.targetserver.endpoints.warning");
1014                }
1015        _logger.fine("System.getProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY) ==> " + System.getProperty(S1ASCtxFactory.IIOP_ENDPOINTS_PROPERTY));
1016        }
1017    } catch (ConfigException t) {
1018        _logger.log(Level.WARNING,"acc.acc_xml_file_error" ,
1019            new Object JavaDoc[] {clientXmlLocation, t.getMessage()});
1020        _logger.log(Level.FINE, "exception : " + t.toString(), t);
1021        throw t;
1022    }
1023    }
1024
1025    private static void setSSLData(ClientContainer cc) {
1026        try {
1027            // Set the SSL related properties for ORB
1028
TargetServer tServer = cc.getTargetServer(0);
1029            // TargetServer is required.
1030
//temp solution to target-server+ change in DTD
1031
// assuming that multiple servers can be specified but only 1st
1032
// first one will be used.
1033
Security security = tServer.getSecurity();
1034        if (security == null) {
1035        _logger.fine("No Security input set in ClientContainer.xml");
1036        // do nothing
1037
return;
1038        }
1039        Ssl ssl = security.getSsl();
1040        if (ssl == null) {
1041        _logger.fine("No SSL input set in ClientContainer.xml");
1042        // do nothing
1043
return;
1044        
1045        }
1046        //XXX do not use NSS in this release
1047
//CertDb certDB = security.getCertDb();
1048
SSLUtils.setAppclientSsl(ssl);
1049    } catch (Exception JavaDoc ex) {
1050
1051        }
1052    }
1053
1054    
1055    private void validateXMLFile(String JavaDoc xmlFullName)
1056    {
1057        if(xmlFullName == null ||
1058           xmlFullName.startsWith("-")){ // If no file name is given after -xml argument
1059
usage();
1060        }
1061        try {
1062            File JavaDoc f = new File JavaDoc(xmlFullName);
1063            if((f != null) && f.exists() && f.isFile() && f.canRead()){
1064                return;
1065            }else{// If given file does not exists
1066
xmlMessage(xmlFullName);
1067                usage();
1068            }
1069        } catch (Exception JavaDoc ex) {
1070            xmlMessage(xmlFullName);
1071            usage();
1072        }
1073    }
1074
1075    // Shut down system resource adapters. Currently it is
1076
// only JMS.
1077
private void shutDownSystemAdapters() {
1078       try {
1079        com.sun.enterprise.PoolManager poolmgr =
1080            Switch.getSwitch().getPoolManager();
1081        if ( poolmgr != null ) {
1082            Switch.getSwitch().getPoolManager().killFreeConnectionsInPools();
1083        }
1084    } catch( Exception JavaDoc e ) {
1085        //ignore
1086
}
1087        
1088    try {
1089            ConnectorRegistry registry = ConnectorRegistry.getInstance();
1090            ActiveResourceAdapter activeRar = registry.getActiveResourceAdapter
1091                                         (ConnectorRuntime.DEFAULT_JMS_ADAPTER);
1092            if (activeRar != null) {
1093                activeRar.destroy();
1094            }
1095        } catch (Exception JavaDoc e) {
1096            // Some thing has gone wrong. No problem
1097
_logger.fine("Exception caught while shutting down system adapter:"+e.getMessage());
1098        }
1099    }
1100
1101    private void usage() {
1102        System.out.println(localStrings.getString("main.usage",
1103            "appclient [ -client <appjar> | <classfile> ] [-mainclass <appClass-name>|-name <display-name>] [-xml <xml>] [-textauth] [-user <username>] [-password <password>|-passwordfile <password-file>] [app-args]"));
1104    System.exit(1);
1105    }
1106    
1107    private void xmlMessage(String JavaDoc xmlFullName)
1108    {
1109        System.out.println(localStrings.getString("main.cannot_read_clientContainer_xml", xmlFullName,
1110             "Client Container xml: " + xmlFullName + " not found or unable to read.\nYou may want to use the -xml option to locate your configuration xml."));
1111       
1112    }
1113
1114    private String JavaDoc loadPasswordFromFile(String JavaDoc fileName)
1115            throws IOException {
1116        InputStream inputStream = null;
1117        try {
1118            inputStream = new BufferedInputStream(new FileInputStream(fileName));
1119            Properties JavaDoc props = new Properties JavaDoc();
1120            props.load(inputStream);
1121            return props.getProperty("PASSWORD");
1122        } finally {
1123            if (inputStream != null) {
1124                inputStream.close();
1125            }
1126        }
1127    }
1128
1129    private static class Cleanup extends Thread JavaDoc {
1130        private AppContainer appContainer = null;
1131        private AppClientInfo appClientInfo = null;
1132        private boolean cleanedUp = false;
1133        private InjectionManager injectionMgr = null;
1134        private ApplicationClientDescriptor appClient = null;
1135        private Class JavaDoc cls = null;
1136
1137        public Cleanup() {
1138        }
1139
1140        public void setAppContainer(AppContainer container) {
1141            appContainer = container;
1142        }
1143
1144        public void setAppClientInfo(AppClientInfo info) {
1145            appClientInfo = info;
1146        }
1147
1148        public void setInjectionManager(InjectionManager injMgr, Class JavaDoc cls, ApplicationClientDescriptor appDesc) {
1149            injectionMgr = injMgr;
1150            this.cls = cls;
1151            appClient = appDesc;
1152        }
1153        
1154        public void run() {
1155            _logger.info("Clean-up starting");
1156            cleanUp();
1157        }
1158
1159        public void cleanUp() {
1160            if( !cleanedUp ) {
1161                try {
1162                    if( appContainer != null ) {
1163                        appContainer.postInvoke();
1164                    }
1165                    if ( appClientInfo != null ) {
1166                        appClientInfo.close();
1167                    }
1168                    if ( injectionMgr != null) {
1169                        // inject the pre-destroy methods before shutting down
1170
injectionMgr.invokeClassPreDestroy(cls, appClient);
1171                        injectionMgr = null;
1172                    }
1173                }
1174                catch(Throwable JavaDoc t) {
1175                }
1176                finally {
1177                    cleanedUp = true;
1178                }
1179            } // End if -- cleanup required
1180
}
1181    }
1182    /**
1183     *Sets up the user-provided or default sun-acc.xml and
1184     *wss-client-config.xml configurations.
1185     *@return the file name of the sun-acc.xml file
1186     */

1187    private String JavaDoc prepareJWSConfig() throws IOException, FileNotFoundException {
1188        return prepareJWSDefaultConfig();
1189    }
1190    
1191    /**
1192     *Creates temporary files for use as default sun-acc.xml and
1193     *wss-client-config.xml configurations.
1194     *@return the file name of the temporary sun-acc.xml file
1195     */

1196    private String JavaDoc prepareJWSDefaultConfig() throws IOException, FileNotFoundException {
1197        String JavaDoc result = null;
1198        
1199        /*
1200         *Retrieve the sun-acc and wss-client-config templates.
1201         */

1202        String JavaDoc sunACCTemplate = Util.loadResource(this.getClass(), SUN_ACC_DEFAULT_TEMPLATE);
1203        String JavaDoc wssClientConfigTemplate = Util.loadResource(this.getClass(), WSS_CLIENT_CONFIG_TEMPLATE);
1204        
1205        /*
1206         *Prepare the property names and values for substitution in the templates. Some
1207         *of the properties are specified in the environment already, so use those
1208         *as defaults and just add the extra ones.
1209         */

1210        Properties JavaDoc tokenValues = new Properties JavaDoc(System.getProperties());
1211        
1212        /**
1213         *Create the wss client config defaults, then write them to a temporary file.
1214         */

1215        String JavaDoc wssClientConfig = Util.replaceTokens(wssClientConfigTemplate, tokenValues);
1216        File JavaDoc wssClientConfigFile = Util.writeTextToTempFile(wssClientConfig, WSS_CLIENT_CONFIG_PREFIX, WSS_CLIENT_CONFIG_SUFFIX, retainTempFiles);
1217        _logger.fine("Temporary wss-client-config.xml file: " + wssClientConfigFile.getAbsolutePath() + lineSep);
1218// pendingLogFine.append("Temporary wss-client-config.xml file: " + wssClientConfigFile.getAbsolutePath() + lineSep);
1219

1220        /*
1221         *Now that the wss temp file is created, insert its name into the default
1222         *sun-acc text and write that to another temp file.
1223         *
1224         *On Windows, the backslashes in the path will be consumed by the replaceTokens method which will
1225         *interpret them as quoting the following character. So replace each \ with \\ first. All the slashes
1226         *have to do with quoting a slash to the Java compiler, then quoting it again to the regex
1227         *processor.
1228         */

1229        String JavaDoc quotedConfigFileSpec = wssClientConfigFile.getAbsolutePath().replaceAll("\\\\", "\\\\\\\\");
1230        tokenValues.setProperty(SUN_ACC_SECURITY_CONFIG_PROPERTY, quotedConfigFileSpec);
1231        
1232        String JavaDoc sunaccContent = Util.replaceTokens(sunACCTemplate, tokenValues);
1233        File JavaDoc sunaccFile = Util.writeTextToTempFile(sunaccContent, SUN_ACC_PREFIX, SUN_ACC_SUFFIX, retainTempFiles);
1234        _logger.fine("Temporary sun-acc.xml file: " + sunaccFile.getAbsolutePath());
1235// pendingLogFine.append("Temporary sun-acc.xml file: " + sunaccFile.getAbsolutePath());
1236

1237        return sunaccFile.getAbsolutePath();
1238    }
1239
1240    /**
1241     *Prepares the JAAS login configuration for a Java Web Start invocation.
1242     *
1243     */

1244    private void prepareJWSLoginConfig() {
1245        /*
1246         *If this is a Java Web Start invocation, prepare the user-specified
1247         *or default login configuration.
1248         */

1249        if (isJWS) {
1250            try {
1251                prepareJWSDefaultLoginConfig();
1252            } catch (Throwable JavaDoc thr) {
1253                throw new RuntimeException JavaDoc(localStrings.getString("appclient.errorPrepJWSLogginConfig"), thr);
1254            }
1255        }
1256    }
1257    
1258    /**
1259     *Extracts the default login.conf file into a temporary file and assigns the
1260     *java.security.auth.login.config property accordingly.
1261     */

1262    private void prepareJWSDefaultLoginConfig() throws IOException, FileNotFoundException {
1263        /*
1264         *For a Java Web Start launch, the default login configuration is in a
1265         *template bundled in the app server's jws jar file. Putting it there
1266         *allows this method to locate it simply by loading it as a resource, whereas
1267         *the command-line appclient invocation needs to be able to find the
1268         *file on-disk somewhere.
1269         *
1270         *The contents of the template are loaded and then written to a temp file and
1271         *that temp file location is assigned to the system property that directs
1272         *JAAS to the login configuration.
1273         */

1274        String JavaDoc configContent = Util.loadResource(this.getClass(), LOGIN_CONF_TEMPLATE);
1275        File JavaDoc configFile = Util.writeTextToTempFile(configContent, LOGIN_CONF_FILE_PREFIX, LOGIN_CONF_FILE_SUFFIX, retainTempFiles);
1276        String JavaDoc configFilePath = configFile.getAbsolutePath();
1277        _logger.fine("Temporary appclientlogin.conf file: " + configFilePath);
1278        System.setProperty(LOGIN_CONF_PROPERTY_NAME, configFilePath);
1279    }
1280    
1281    /*
1282     *Returns the jar or directory that contains the specified resource.
1283     *@param target entry name to look for
1284     *@return URI object for the jar or directory containing the entry
1285     */

1286    private File JavaDoc findContainingJar(String JavaDoc target) throws IllegalArgumentException JavaDoc, URISyntaxException {
1287        File JavaDoc result = null;
1288        
1289        /*
1290         *Use the current class loader to find the resource.
1291         */

1292        URL resourceURL = getClass().getResource(target);
1293        if (resourceURL != null) {
1294            URI uri = resourceURL.toURI();
1295            String JavaDoc scheme = uri.getScheme();
1296            String JavaDoc ssp = uri.getSchemeSpecificPart();
1297            if (scheme.equals("jar")) {
1298                /*
1299                 *The scheme-specific part will look like "file:<file-spec>!/<path-to-class>.class"
1300                 *so we need to isolate the scheme and the <file-spec> part.
1301                 *The subscheme (the scheme within the jar) precedes the colon
1302                 *and the file spec appears after it and before the exclamation point.
1303                 */

1304                int colon = ssp.indexOf(':');
1305                String JavaDoc subscheme = ssp.substring(0, colon);
1306                int excl = ssp.indexOf('!');
1307                String JavaDoc containingJarPath = ssp.substring(colon + 1, excl);
1308                result = new File JavaDoc(containingJarPath);
1309            } else if (scheme.equals("file")) {
1310                /*
1311                 *The URI is already a file, so the part we want is the part
1312                 *up to but not including the resource name we were looking for
1313                 in the first place..
1314                 */

1315                int resourceNamePosition = ssp.indexOf(target);
1316                String JavaDoc containingFilePath = ssp.substring(0, resourceNamePosition);
1317                result = new File JavaDoc(containingFilePath);
1318            } else {
1319                throw new IllegalArgumentException JavaDoc(resourceURL.toExternalForm());
1320            }
1321        }
1322        return result;
1323    }
1324    
1325    /**
1326     *Locate the app client jar file during a Java Web Start launch.
1327     *@return File object for the client jar file
1328     */

1329    private File JavaDoc findAppClientFileForJWSLaunch() throws URISyntaxException {
1330        /*
1331         *The JWSACCMain class has already located the downloaded app client
1332         *jar file and set a property pointing to it.
1333         */

1334       File JavaDoc containingJar = new File JavaDoc(System.getProperty("com.sun.aas.downloaded.appclient.jar"));
1335        _logger.fine("Location of appclient jar file: " + containingJar.getAbsolutePath());
1336        return containingJar;
1337    }
1338    
1339    /**
1340     *Creates a memory-based logger for holding log messages that may occur before
1341     *the user's logging set-up is read.
1342     *@return a Logger that buffers its log records in memory.
1343     */

1344    private BufferedLogger prepareBufferedLogging() {
1345        /*
1346         *The buffered logger adds a handler automatically during instantiation.
1347         */

1348        BufferedLogger logger = new BufferedLogger();
1349        return logger;
1350    }
1351
1352    /**
1353     *Logger implementation that records its log records in memory. Normally
1354     *the logger will be flushed to another logger once the second logger has
1355     *been configured appropriately.
1356     */

1357    private class BufferedLogger extends Logger JavaDoc {
1358       
1359        /**
1360         *Creates a new instance of the buffered logger.
1361         */

1362        public BufferedLogger() {
1363            super(null, null);
1364            addHandler(new BufferedHandler());
1365        }
1366        
1367        /**
1368         *Flushes any accumulated log messages to the specified target logger.
1369         *@param target the Logger to receive any buffered messages
1370         */

1371        public void pushTo(Logger JavaDoc target) {
1372            for (Handler JavaDoc handler : getHandlers()) {
1373                if (handler instanceof BufferedHandler) {
1374                    ((BufferedHandler) handler).pushTo(target);
1375                }
1376            }
1377        }
1378    }
1379    
1380    /**
1381     *Log handler that accumulates each log record sent to it into memory and
1382     *flushes those records to another logger when asked. Once this handler is
1383     *flushed it can no longer be used.
1384     */

1385    private class BufferedHandler extends Handler JavaDoc {
1386       
1387        /** holds log records until flushed to another logger */
1388        private Vector JavaDoc<LogRecord JavaDoc> buffer = new Vector JavaDoc<LogRecord JavaDoc>();
1389        
1390        /**
1391         *Creates a new instance of the buffered log handler.
1392         */

1393        public BufferedHandler() {
1394            setLevel(Level.ALL);
1395            setFilter(null);
1396            setFormatter(new SimpleFormatter JavaDoc());
1397        }
1398        
1399        /**
1400         *Publishes a log record to the handler.
1401         *<p>
1402         *In this handler, the log record is saved in the memory buffer.
1403         *@paran record the LogRecord to be written
1404         */

1405        public synchronized void publish(LogRecord JavaDoc record) {
1406            if (buffer == null) {
1407                throw new IllegalStateException JavaDoc("Handler asked to publish log record after pushTo invoked");
1408            }
1409            buffer.add(record);
1410        }
1411        
1412        /**
1413         *Flushes any accumulated log information to the specified target Logger.
1414         *@param target the Logger to receive buffered messages
1415         */

1416        public synchronized void pushTo(Logger JavaDoc target) {
1417            if (buffer == null) {
1418                throw new IllegalStateException JavaDoc("Handler asked to push to target more than once");
1419            }
1420            for (LogRecord JavaDoc record : buffer) {
1421                target.log(record);
1422            }
1423            close();
1424        }
1425
1426        /**
1427         *Closes the handler to further use.
1428         */

1429        public void close() throws SecurityException JavaDoc {
1430            buffer.clear();
1431            buffer = null;
1432        }
1433
1434        /**
1435         *Does nothing because there is no intermediate buffer between the
1436         *handler and its storage - the storage is itself a memory buffer.
1437         */

1438        public void flush() {
1439        }
1440    }
1441}
1442
Popular Tags