ClientContainer.java

00001 
00026 package org.objectweb.jonas.client;
00027 
00028 import java.io.File;
00029 import java.io.IOException;
00030 import java.lang.reflect.InvocationTargetException;
00031 import java.lang.reflect.Method;
00032 import java.net.MalformedURLException;
00033 import java.net.URL;
00034 import java.net.URLClassLoader;
00035 import java.util.ArrayList;
00036 import java.util.Iterator;
00037 import java.util.List;
00038 import java.util.Map;
00039 import java.util.StringTokenizer;
00040 import java.util.jar.Attributes;
00041 import java.util.jar.JarFile;
00042 import java.util.jar.Manifest;
00043 
00044 import javax.naming.Context;
00045 import javax.naming.LinkRef;
00046 import javax.naming.NamingException;
00047 import javax.naming.Reference;
00048 import javax.naming.StringRefAddr;
00049 import javax.security.auth.callback.CallbackHandler;
00050 import javax.security.auth.login.LoginContext;
00051 
00052 import org.objectweb.carol.util.configuration.CarolConfiguration;
00053 
00054 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDesc;
00055 import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDescException;
00056 import org.objectweb.jonas_client.deployment.lib.ClientDeploymentDescManager;
00057 
00058 import org.objectweb.jonas_ear.deployment.api.EarDeploymentDesc;
00059 import org.objectweb.jonas_ear.deployment.api.EarDeploymentDescException;
00060 import org.objectweb.jonas_ear.deployment.lib.EarDeploymentDescManager;
00061 import org.objectweb.jonas_ear.deployment.xml.Web;
00062 
00063 import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;
00064 
00065 import org.objectweb.jonas_lib.deployment.api.EjbRefDesc;
00066 import org.objectweb.jonas_lib.deployment.api.EnvEntryDesc;
00067 import org.objectweb.jonas_lib.deployment.api.MessageDestinationRefDesc;
00068 import org.objectweb.jonas_lib.deployment.api.ResourceEnvRefDesc;
00069 import org.objectweb.jonas_lib.deployment.api.ResourceRefDesc;
00070 import org.objectweb.jonas_lib.deployment.work.EarFileManager;
00071 import org.objectweb.jonas_lib.naming.ContainerNaming;
00072 
00073 import org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager;
00074 
00075 import org.objectweb.jonas_ws.deployment.api.ServiceRefDesc;
00076 
00077 import org.objectweb.jonas.common.Log;
00078 import org.objectweb.jonas.ear.lib.EarClassPathManager;
00079 import org.objectweb.jonas.ear.lib.EarClassPathManagerException;
00080 import org.objectweb.jonas.ear.lib.JarList;
00081 import org.objectweb.jonas.ear.lib.JarListException;
00082 import org.objectweb.jonas.naming.NamingManager;
00083 import org.objectweb.jonas.security.auth.callback.NoInputCallbackHandler;
00084 import org.objectweb.jonas.security.jacc.JPolicyUserRoleMapping;
00085 import org.objectweb.jonas.ws.ClientJServiceFactoryFinder;
00086 import org.objectweb.jonas.ws.JServiceFactory;
00087 
00088 import org.objectweb.util.monolog.api.BasicLevel;
00089 import org.objectweb.util.monolog.api.Logger;
00090 
00096 public class ClientContainer {
00097 
00101     private static final String CAROL_FILE = "carol.properties";
00102 
00106     private String mainClass = null;
00107 
00111     private String tmpDir = null;
00112 
00116     private String jarClient = null;
00117 
00121     private String classpath = null;
00122 
00126     private String clientTraceFile = null;
00127 
00131     private ContainerNaming naming;
00132 
00136     private String carolFile = null;
00137 
00141     private String[] args = null;
00142 
00146     private URLClassLoader earClassLoader = null;
00147 
00151     private ArrayList appArgs = null;
00152 
00156     private URL[] extensionsURLs = null;
00157 
00161     private Logger logger = null;
00162 
00167     private ClientContainer(String[] args) {
00168         this.args = args;
00169 
00170         appArgs = new ArrayList();
00171     }
00172 
00176     private void initLogger() {
00177         // Allow tracing ejb/jms code
00178         Log.configure(clientTraceFile);
00179         // init the logger
00180         this.logger = Log.getLogger(Log.JONAS_CLIENT_PREFIX);
00181     }
00182 
00187     public static void main(String[] args) {
00188         // Retrieve command line parameters
00189         ClientContainer cc = new ClientContainer(args);
00190 
00191         try {
00192             cc.start();
00193         } catch (InvocationTargetException ite) {
00194             Throwable t = ite.getTargetException();
00195             String message = t.getMessage();
00196             if (t instanceof Error) {
00197                 System.err.println("There was the following error : " + message);
00198             } else if (t instanceof Exception) {
00199                 System.err.println("There was the following exception : " + message);
00200             }
00201             t.printStackTrace(System.err);
00202         } catch (Exception e) {
00203             System.err.println("There was the following exception : " + e.getMessage());
00204             e.printStackTrace();
00205             System.exit(-1);
00206         }
00207     }
00208 
00213     private void start() throws Exception {
00214         analyzeArgs();
00215 
00216         // Use the specified traceclient.properties
00217         if (clientTraceFile != null) {
00218             File tClient = new File(clientTraceFile);
00219 
00220             if (!tClient.exists()) {
00221                 throw new ClientContainerException("The file '" + clientTraceFile + "' was not found.");
00222             }
00223 
00224             if (!tClient.isFile()) {
00225                 throw new ClientContainerException("The file '" + clientTraceFile
00226                         + "' is not a valid file. Maybe a directory ?");
00227             }
00228 
00229             // Configure log
00230             System.setProperty("jonas.client.trace.file", clientTraceFile);
00231             Log.reset();
00232         } else {
00233             clientTraceFile = "traceclient";
00234         }
00235 
00236         initLogger();
00237 
00238         // Get the filename
00239         String userArg = null;
00240         String fileName = null;
00241         boolean fileMode = true;
00242 
00243         try {
00244             userArg = (String) appArgs.get(0);
00245         } catch (IndexOutOfBoundsException ioobe) {
00246             usage();
00247             throw new ClientContainerException(
00248                     "You haven't specify a jar, an ear file or class name as argument. See the Usage.");
00249         }
00250 
00251         String className = null;
00252         // Test if this is an ear or a jar file else it must be a class name
00253         if (!(userArg.toLowerCase().endsWith(".jar") || userArg.toLowerCase().endsWith(".ear"))) {
00254             className = userArg;
00255             fileMode = false;
00256         } else {
00257             fileMode = true;
00258             fileName = userArg;
00259         }
00260 
00261         // Build file and test if it exists
00262         File clientJarFile = null;
00263         if (fileMode) {
00264             File argFile = new File(fileName);
00265 
00266             if (!argFile.exists()) {
00267                 throw new ClientContainerException("The specified file '" + fileName + "' doesn't exists.");
00268             }
00269 
00270             // Unpack and analyze EAR file if it is an ear
00271             if (fileName.toLowerCase().endsWith(".ear")) {
00272                 clientJarFile = extractAndAnalyzeEar(argFile);
00273             } else {
00274                 //Client jar is the given file
00275                 clientJarFile = argFile;
00276             }
00277         }
00278 
00279         // Carol initialisation (property)
00280         System.setProperty("javax.rmi.CORBA.PortableRemoteObjectClass",
00281                            "org.objectweb.carol.rmi.multi.MultiPRODelegate");
00282         System.setProperty("java.naming.factory.initial", "org.objectweb.carol.jndi.spi.MultiOrbInitialContextFactory");
00283         System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.org.objectweb.jotm.ots.OTSORBInitializer",
00284                            "");
00285         System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.org.objectweb.jonas.security.interceptors.iiop.SecurityInitializer",
00286                            "");
00287         System.setProperty("org.omg.CORBA.ORBClass" , "org.jacorb.orb.ORB");
00288         System.setProperty("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton");
00289         System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.standard_init" , "org.jacorb.orb.standardInterceptors.IORInterceptorInitializer");
00290 
00291         // force JAX-RPC 1.1 Axis compliance
00292         System.setProperty("axis.jaxrpc11Compliance", "true");
00293 
00294         // Build a classloader for the initialisation of carol
00295         // Priority
00296         //    1/ file as argument
00297         //    2/ file in the jar client
00298         //    3/ file in client.jar
00299         URL urlCarolFile = null;
00300 
00301         if (carolFile != null) {
00302             File fCarol = new File(carolFile);
00303 
00304             if (!fCarol.exists()) {
00305                 throw new ClientContainerException("The file '" + carolFile + "' was not found.");
00306             }
00307 
00308             if (!fCarol.isFile()) {
00309                 throw new ClientContainerException("The file '" + carolFile
00310                         + "' is not a valid file. Maybe a directory ?");
00311             }
00312 
00313             if (!fCarol.getName().equals(CAROL_FILE)) {
00314                 throw new ClientContainerException("The file '" + carolFile + "' must be named '" + CAROL_FILE + "'.");
00315             }
00316 
00317             try {
00318                 urlCarolFile = fCarol.getParentFile().toURL();
00319             } catch (MalformedURLException mue) {
00320                 throw new ClientContainerException("Error when building an URL for the file '" + fCarol + "'.");
00321             }
00322         }
00323 
00324         ArrayList sysCP = getSystemClassPath();
00325         URL[] urlsCarol = null;
00326         int urlInd = 0;
00327 
00328         // number of url to add to the classpath
00329         // if it is not a file, add nothing
00330         int argNumberFile = 0;
00331         if (fileMode) {
00332             argNumberFile++;
00333         }
00334 
00335         if (urlCarolFile != null) {
00336             // url of carol file + url of client jar file(if any) + classpath
00337             urlsCarol = new URL[sysCP.size() + 1 + argNumberFile];
00338             urlsCarol[urlInd] = urlCarolFile;
00339             urlInd++;
00340         } else {
00341             // url of client jar file(if any) + classpath
00342             urlsCarol = new URL[sysCP.size() + argNumberFile];
00343         }
00344 
00345         try {
00346             //Add the jar file url
00347             if (fileMode) {
00348                 urlsCarol[urlInd] = clientJarFile.toURL();
00349                 urlInd++;
00350             }
00351             int classPathSize = sysCP.size();
00352             for (int j = 0; j < classPathSize; j++) {
00353                 urlsCarol[urlInd] = new File(((String) sysCP.get(j))).toURL();
00354                 urlInd++;
00355             }
00356         } catch (MalformedURLException mue) {
00357             throw new ClientContainerException("Error when building an URL for the classpath.");
00358         }
00359 
00360         ClassLoader oldCL = Thread.currentThread().getContextClassLoader();
00361         URLClassLoader newCL = new URLClassLoader(urlsCarol, null);
00362         Thread.currentThread().setContextClassLoader(newCL);
00363 
00364         if (logger.isLoggable(BasicLevel.DEBUG)) {
00365             URL[] urls = newCL.getURLs();
00366             logger.log(BasicLevel.DEBUG, "URLs of the classloader for Carol :");
00367             for (int u = 0; u < urls.length; u++) {
00368                 logger.log(BasicLevel.DEBUG, "URL[" + u + "] = " + urls[u]);
00369             }
00370         }
00371 
00372         // Init carol with the properties file
00373         CarolConfiguration.init(Log.getLoggerFactory());
00374         Thread.currentThread().setContextClassLoader(oldCL);
00375 
00376         // Add Csiv2 Interceptors
00377         CarolConfiguration.addInterceptors("iiop", "org.objectweb.jonas.security.iiop.Csiv2Initializer");
00378 
00379 
00380         // Carol configuration is done
00381         // Extract Main-Class to use in the jar from the manifest
00382         if (fileMode) {
00383             Manifest manifest = new JarFile(clientJarFile).getManifest();
00384 
00385             if (manifest == null) {
00386                 throw new ClientContainerException("No manifest was found inside the file" + clientJarFile);
00387             }
00388 
00389             // Extract attributes
00390             Attributes attributes = manifest.getMainAttributes();
00391 
00392             if (attributes == null) {
00393                 throw new ClientContainerException("No attributes were found in the manifest of the file '"
00394                         + clientJarFile + "'.");
00395             }
00396             mainClass = attributes.getValue(Attributes.Name.MAIN_CLASS);
00397         } else {
00398             mainClass = className;
00399         }
00400 
00401         // Invoke the client if there is no need of XML parsing
00402         if (!fileMode) {
00403             ClassLoader clientCL = new URLClassLoader(getUserClasspathUrls());
00404             Thread.currentThread().setContextClassLoader(clientCL);
00405             invokeClient();
00406             return;
00407         }
00408 
00409         if (mainClass == null || mainClass.length() == 0) {
00410             throw new ClientContainerException("No main class was found inside the Manifest  of the file '"
00411                     + clientJarFile + "'. This attribute is required to launch the application client.");
00412         }
00413 
00414         if (logger.isLoggable(BasicLevel.DEBUG)) {
00415             logger.log(BasicLevel.DEBUG, "Using Main-Class :" + mainClass);
00416         }
00417 
00418         // Convert file to URL
00419         URL clientJarURL = null;
00420 
00421         try {
00422             clientJarURL = clientJarFile.toURL();
00423         } catch (MalformedURLException mue) {
00424             throw new ClientContainerException("Error when building an URL with the file '" + clientJarFile + "'.");
00425         }
00426 
00427         // Build the urls for the classloader
00428         URL[] urlsClient = null;
00429 
00430         // URLs for the classloader
00431         if (extensionsURLs != null) {
00432             // There were URLs with the extension mechanism in the EAR
00433             urlsClient = new URL[extensionsURLs.length + 1];
00434 
00435             for (int i = 0; i < extensionsURLs.length; i++) {
00436                 urlsClient[i] = extensionsURLs[i];
00437 
00438                 if (logger.isLoggable(BasicLevel.DEBUG)) {
00439                     logger.log(BasicLevel.DEBUG, "Adding " + extensionsURLs[i] + " to the urls of the client");
00440                 }
00441             }
00442 
00443             urlsClient[extensionsURLs.length] = clientJarURL;
00444         } else {
00445             if (logger.isLoggable(BasicLevel.DEBUG)) {
00446                 logger.log(BasicLevel.DEBUG, "Only one url for urls of client");
00447             }
00448 
00449             // No extension or jar case.
00450             urlsClient = new URL[1];
00451             urlsClient[0] = clientJarURL;
00452         }
00453 
00454         // Build classloader
00455         URLClassLoader clientClassloader = new URLClassLoader(urlsClient, Thread.currentThread()
00456                 .getContextClassLoader());
00457         Thread.currentThread().setContextClassLoader(clientClassloader);
00458 
00459         // Get the deployment descriptor from file
00460         ClientContainerDeploymentDesc clientDD = null;
00461         if (extensionsURLs != null) {
00462             EjbDeploymentDescManager.getInstance().addClassLoaderUrlMapping(clientClassloader, extensionsURLs);
00463         }
00464 
00465         try {
00466             clientDD = ClientDeploymentDescManager.getInstance().getDeploymentDesc(clientJarURL, clientClassloader, earClassLoader);
00467         } catch (ClientContainerDeploymentDescException e) {
00468             String err = "Cannot read the deployment descriptors '" + clientJarURL + "'";
00469             error(err + ": " + e);
00470             throw new ClientContainerException(err + e.getMessage());
00471         }
00472 
00473         // Populate the java:comp/env (ENC) environment.
00474         try {
00475             setClientEnvironment(clientDD);
00476         } catch (Exception e) {
00477             //populating environment failed.
00478             String err = "Error when populating ";
00479             error(err + e.getMessage());
00480             throw new ClientContainerException(err, e);
00481         }
00482 
00483         // JAAS
00484         String jaasFile = clientDD.getJaasFile();
00485         String jaasEntry = clientDD.getJaasEntry();
00486         String username = clientDD.getUsername();
00487         String password = clientDD.getPassword();
00488 
00489         if (logger.isLoggable(BasicLevel.DEBUG)) {
00490             logger.log(BasicLevel.DEBUG, "Using jaas file = " + jaasFile);
00491         }
00492 
00493         String jaasConfigFile = null;
00494 
00495         if (jaasFile != null) {
00496             // Use JAAS
00497             jaasConfigFile = "jar:" + clientJarURL.toExternalForm() + "!/" + jaasFile;
00498             System.setProperty("java.security.auth.login.config", jaasConfigFile);
00499         }
00500 
00501         CallbackHandler ch = null;
00502 
00503         if ((username != null) && (password != null)) {
00504             ch = new NoInputCallbackHandler(username, password);
00505             info("Using the login/password specified in the jonas-client.xml file with a specific CallbackHandler");
00506         } else {
00507             // Is there a callbackHandler specified ?
00508             String ddCallbackHandler = clientDD.getCallbackHandler();
00509 
00510             if (ddCallbackHandler != null) {
00511                 if (logger.isLoggable(BasicLevel.DEBUG)) {
00512                     logger.log(BasicLevel.DEBUG, "Using '" + ddCallbackHandler + "' class as CallbackHandler.");
00513                 }
00514 
00515                 Class clazz = null;
00516 
00517                 //try to invoke this class
00518                 try {
00519                     clazz = clientClassloader.loadClass(ddCallbackHandler);
00520                 } catch (Exception e) {
00521                     throw new ClientContainerException("There was an error while trying to instantiate the class '"
00522                             + ddCallbackHandler
00523                             + "' which is specified in the application.xml as CallbackHandler class", e);
00524                 }
00525 
00526                 try {
00527                     ch = (CallbackHandler) clazz.newInstance();
00528                 } catch (Exception e) {
00529                     throw new ClientContainerException(
00530                             "Error while triyng to cast the class '"
00531                                     + ddCallbackHandler
00532                                     + "' to CallbackHandler interface, maybe the specified class doesn't implement this interface.",
00533                             e);
00534                 }
00535             }
00536         }
00537 
00538         // Use JAAS
00539         if (ch != null) {
00540             if (jaasFile == null) {
00541                 throw new ClientContainerException(
00542                         "You have defined that you want use a CallbackHandler but you haven't specify the jaas file to use for the JAAS configuration.");
00543             }
00544 
00545             if (jaasEntry == null) {
00546                 throw new ClientContainerException(
00547                         "You have defined that you want use a CallbackHandler but you haven't specify the jaas entry to use from the jaas config file.");
00548             }
00549 
00550             info("Using JAAS loginContext '" + jaasEntry + "' from the file '" + jaasConfigFile + "'.");
00551 
00552             try {
00553                 LoginContext lc = new LoginContext(jaasEntry, ch);
00554                 lc.login();
00555             } catch (Exception e) {
00556                 String err = "Can not use the JAAS authentication";
00557                 error(err);
00558                 throw new ClientContainerException(err, e);
00559             }
00560         }
00561 
00562         // Start client
00563         invokeClient();
00564 
00565     }
00566 
00574     private void invokeClient() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
00575             InvocationTargetException {
00576         ClassLoader clientClassloader = Thread.currentThread().getContextClassLoader();
00577 
00578         if (logger.isLoggable(BasicLevel.DEBUG)) {
00579             if (clientClassloader instanceof URLClassLoader) {
00580                 URLClassLoader urlClassLoader = (URLClassLoader) clientClassloader;
00581                 URL[] urls = urlClassLoader.getURLs();
00582                 logger.log(BasicLevel.DEBUG, "URLs of the classloader :");
00583                 for (int u = 0; u < urls.length; u++) {
00584                     logger.log(BasicLevel.DEBUG, "URL[" + u + "] = " + urls[u]);
00585                 }
00586             }
00587         }
00588 
00589         // Invoke client
00590         // Launch the "class_to_run" by using our classloader.
00591         Class clazz = clientClassloader.loadClass(mainClass);
00592         Class[] argList = new Class[] {args.getClass()};
00593         Method meth = clazz.getMethod("main", argList);
00594 
00595         // Remove name of the file from arguments
00596         String[] newArgs = new String[appArgs.size() - 1];
00597         String txtArgs = "";
00598 
00599         for (int i = 0; i < newArgs.length; i++) {
00600             newArgs[i] = (String) appArgs.get(i + 1);
00601             txtArgs += (newArgs[i] + " ");
00602         }
00603 
00604         if (logger.isLoggable(BasicLevel.DEBUG)) {
00605             logger.log(BasicLevel.DEBUG, "Starting the application client with the arguments '" + txtArgs + "'.");
00606         }
00607 
00608         info("Starting client...");
00609 
00610         meth.invoke(null, new Object[] {newArgs});
00611 
00612         if (logger.isLoggable(BasicLevel.DEBUG)) {
00613             logger.log(BasicLevel.DEBUG, "End of main method");
00614         }
00615 
00616     }
00617 
00623     private void setClientEnvironment(ClientContainerDeploymentDesc clientDD) throws NamingException {
00624         if (logger.isLoggable(BasicLevel.DEBUG)) {
00625             logger.log(BasicLevel.DEBUG, "");
00626         }
00627 
00628         //Init the naming manager
00629         try {
00630             naming = NamingManager.getInstance();
00631         } catch (NamingException e) {
00632             throw new ClientContainerException("Error when getting the reference to the Naming manager", e);
00633         }
00634 
00635         Context javaCtx = naming.createEnvironmentContext("ClientContainer");
00636         naming.setClientContainerComponentContext(javaCtx);
00637 
00638         Context envCtx = javaCtx.createSubcontext("comp/env");
00639 
00640         // Bean Environment
00641         EnvEntryDesc[] envt = clientDD.getEnvEntryDesc();
00642 
00643         for (int i = 0; i < envt.length; i++) {
00644             // get information in descriptor
00645             String name = envt[i].getName();
00646             Object obj = envt[i].getValue();
00647 
00648             // register object in JNDI
00649             if (logger.isLoggable(BasicLevel.DEBUG)) {
00650                 logger.log(BasicLevel.DEBUG, "Binding object " + name + " -> " + obj);
00651             }
00652 
00653             envCtx.rebind(name, obj);
00654         }
00655 
00656         // Resource References
00657         ResourceRefDesc[] resref = clientDD.getResourceRefDesc();
00658 
00659         for (int i = 0; i < resref.length; i++) {
00660             // get information in descriptor
00661             String name = resref[i].getName();
00662             String resname = resref[i].getJndiName();
00663             String type = resref[i].getTypeName();
00664 
00665             // build the LinkRef that will be registered:
00666             // FactoryClassName = null, size = 1, refAddr = resname.
00667             // register object in JNDI
00668             if (logger.isLoggable(BasicLevel.DEBUG)) {
00669                 logger.log(BasicLevel.DEBUG, "Linking resource " + name + " -> " + resname);
00670             }
00671 
00672             if (type.equalsIgnoreCase("java.net.URL")) {
00673                 // Specify the factory to use with the right URL
00674                 Reference ref = new Reference("java.net.URL", "org.objectweb.jonas_lib.naming.factory.URLFactory", null);
00675                 StringRefAddr refAddr = new StringRefAddr("url", resname);
00676                 ref.add(refAddr);
00677                 envCtx.rebind(name, ref);
00678             } else {
00679                 LinkRef lref = new LinkRef(resname);
00680                 envCtx.rebind(name, lref);
00681             }
00682         }
00683 
00684         // Resource Environment References
00685         ResourceEnvRefDesc[] resEnvref = clientDD.getResourceEnvRefDesc();
00686 
00687         for (int i = 0; i < resEnvref.length; i++) {
00688             // get information in descriptor
00689             String name = resEnvref[i].getName();
00690             String resname = resEnvref[i].getJndiName();
00691             LinkRef lref = new LinkRef(resname);
00692 
00693             if (logger.isLoggable(BasicLevel.DEBUG)) {
00694                 logger.log(BasicLevel.DEBUG, "Linking resource environment " + name + " -> " + resname);
00695             }
00696 
00697             envCtx.rebind(name, lref);
00698         }
00699 
00700         // EJB References
00701         EjbRefDesc[] ejbref = clientDD.getEjbRefDesc();
00702 
00703         for (int i = 0; i < ejbref.length; i++) {
00704             // get information in descriptor
00705             String name = ejbref[i].getEjbRefName();
00706             String ejbname = null;
00707             ejbname = ejbref[i].getJndiName();
00708 
00709             LinkRef lref = new LinkRef(ejbname);
00710 
00711             if (logger.isLoggable(BasicLevel.DEBUG)) {
00712                 logger.log(BasicLevel.DEBUG, "Linking ejb " + name + " -> " + ejbname);
00713             }
00714 
00715             envCtx.rebind(name, lref);
00716         }
00717 
00718         // ServiceRef
00719         ServiceRefDesc[] serviceRefs = clientDD.getServiceRefDesc();
00720         if (serviceRefs.length != 0) {
00721 
00722             // get the current ClassLoader
00723             ClassLoader loader = Thread.currentThread().getContextClassLoader();
00724 
00725             // get the JServiceFactory
00726             JServiceFactory factory = ClientJServiceFactoryFinder.getJOnASServiceFactory();
00727 
00728             for (int i = 0; i < serviceRefs.length; i++) {
00729                 // Create the Service from the ServiceRef description
00730                 String refname = serviceRefs[i].getServiceRefName();
00731 
00732                 Reference ref = factory.getServiceReference(serviceRefs[i], loader);
00733                 envCtx.rebind(refname, ref);
00734 
00735                 if (logger.isLoggable(BasicLevel.DEBUG)) {
00736                     logger.log(BasicLevel.DEBUG, "Adding service-ref 'java:comp/env/" + refname + "'");
00737                 }
00738             }
00739         }
00740 
00741         // MessageDestination References
00742         MessageDestinationRefDesc[] mdref = clientDD.getMessageDestinationRefDesc();
00743 
00744         for (int i = 0; i < mdref.length; i++) {
00745             // get information in descriptor
00746             String name = mdref[i].getMessageDestinationRefName();
00747             String mdname = null;
00748             mdname = mdref[i].getJndiName();
00749 
00750             LinkRef lref = new LinkRef(mdname);
00751 
00752             if (logger.isLoggable(BasicLevel.DEBUG)) {
00753                 logger.log(BasicLevel.DEBUG, "Linking message-destination-ref " + name + " -> " + mdname);
00754             }
00755 
00756             envCtx.rebind(name, lref);
00757         }
00758     }
00759 
00764     private void analyzeArgs() throws Exception {
00765         for (int argn = 0; argn < args.length; argn++) {
00766             String arg = args[argn];
00767 
00768             try {
00769                 if (arg.equals("-tmpDir")) {
00770                     tmpDir = args[++argn];
00771 
00772                     continue;
00773                 }
00774 
00775                 if (arg.equals("-jarClient")) {
00776                     jarClient = args[++argn];
00777 
00778                     continue;
00779                 }
00780 
00781                 if (arg.equals("-traceFile")) {
00782                     clientTraceFile = args[++argn];
00783 
00784                     continue;
00785                 }
00786 
00787                 if (arg.equals("-carolFile")) {
00788                     carolFile = args[++argn];
00789 
00790                     continue;
00791                 }
00792 
00793                 if (arg.equals("-cp")) {
00794                     classpath = args[++argn];
00795                     continue;
00796                 }
00797 
00798                 if (arg.equals("--help") || arg.equals("-help") || arg.equals("-h") || arg.equals("-?")) {
00799                     usage();
00800                     System.exit(1);
00801                 }
00802 
00803                 // Add argument to the application arguments
00804                 appArgs.add(arg);
00805             } catch (ArrayIndexOutOfBoundsException aioobe) {
00806                 // The next argument is not in the array
00807                 throw new ClientContainerException("A required parameter was missing after the argument" + arg);
00808             }
00809         }
00810     }
00811 
00815     private void usage() {
00816         System.out.println("Usage of this client :");
00817         System.out.println("-------------------------------------------------------------------");
00818         System.out.println("java -jar client.jar <client.jar|app.ear|className> [options]");
00819         System.out.println("-------------------------------------------------------------------");
00820         System.out.println(" -jarClient   : Specify the client jar to use of the ear if many.");
00821         System.out.println(" -traceFile   : Specify the configuration file to use for the traces\n"
00822                 + "                of this client instead of the default file\n"
00823                 + "                (traceclient.properties) present in client.jar.");
00824         System.out.println(" -carolFile   : Specify the carol.properties file to use instead of \n"
00825                 + "                the default carol.properties file of the client.jar");
00826         System.out.println(" -tmpDir      : Specify the temp directory where unpack the ear.");
00827         System.out.println(" -cp          : Specify the classpath to use for the jar client.");
00828         System.out.println("-------------------------------------------------------------------");
00829         System.out.println("  --help  : Display this help.");
00830         System.out.println("  -help   : Display this help.");
00831         System.out.println("  -h      : Display this help.");
00832         System.out.println("  -?      : Display this help.");
00833         System.out.println("-------------------------------------------------------------------");
00834     }
00835 
00842     private File extractAndAnalyzeEar(File earFile) throws Exception {
00843         if (logger.isLoggable(BasicLevel.DEBUG)) {
00844             logger.log(BasicLevel.DEBUG, "");
00845         }
00846 
00847         URL earUrl = null;
00848 
00849         try {
00850             earUrl = earFile.toURL();
00851         } catch (MalformedURLException mue) {
00852             throw new ClientContainerException("Can not build an url with the filename '" + earFile + "'.");
00853         }
00854 
00855         // Create classLoader
00856         URL[] arrURL = new URL[1];
00857         arrURL[0] = earUrl;
00858 
00859         // parent classloader is the current classloader
00860         ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
00861         URLClassLoader loaderCls = new URLClassLoader(arrURL, currentLoader);
00862 
00863         EarDeploymentDesc earDD = null;
00864 
00865         if (logger.isLoggable(BasicLevel.DEBUG)) {
00866             logger.log(BasicLevel.DEBUG, "Getting the deployment descriptor of the file" + earFile.getPath());
00867         }
00868 
00869         try {
00870             earDD = EarDeploymentDescManager.getDeploymentDesc(earFile.getPath(), loaderCls);
00871         } catch (EarDeploymentDescException e) {
00872             String err = "Error in the Deployment descriptor '" + earFile + "': " + e;
00873 
00874             //error( err);
00875             throw new ClientContainerException(err, e);
00876         }
00877 
00878         Map userToRoleMapping = earDD.getUserToRoleMapping();
00879         // Do user-to-role mapping
00880         if (userToRoleMapping != null) {
00881             for (Iterator itMapping = userToRoleMapping.keySet().iterator(); itMapping.hasNext();) {
00882                 String principalName = (String) itMapping.next();
00883                 List roles = (List) userToRoleMapping.get(principalName);
00884                 String[] roleNames = (String[]) roles.toArray(new String[roles.size()]);
00885                 JPolicyUserRoleMapping.addGlobalUserToRoleMapping(principalName, roleNames);
00886             }
00887         }
00888 
00889 
00890         // Get the tags from the Deployment descriptor
00891         String[] ejbTags = earDD.getEjbTags();
00892         Web[] webTags = earDD.getWebTags();
00893         String[] clientTags = earDD.getClientTags();
00894         String[] altDDEjbs = earDD.getAltDDEjbs();
00895         String[] altDDWebs = earDD.getAltDDWebs();
00896         String[] altDDClients = earDD.getAltDDClients();
00897 
00898         // Check if all modules are inside the EAR file
00899         // no relatives mode like ../../file1.jar
00900         File fEar = null;
00901         File tmpFile = null;
00902 
00903         try {
00904             fEar = earFile.getCanonicalFile();
00905         } catch (IOException ioe) {
00906             String err = "Error : Can not get canonical file for the file '" + earFile + "'.";
00907             throw new ClientContainerException(err);
00908         }
00909 
00910         try {
00911             for (int i = 0; i < ejbTags.length; i++) {
00912                 tmpFile = new File(fEar, ejbTags[i]);
00913                 tmpFile = tmpFile.getCanonicalFile();
00914                 if (!tmpFile.getPath().startsWith(fEar.getPath())) {
00915                     String err = "Error : The ejb-jar file " + ejbTags[i] + " is not inside the ear file " + fEar;
00916                     throw new ClientContainerException(err);
00917                 }
00918             }
00919 
00920             for (int i = 0; i < webTags.length; i++) {
00921                 tmpFile = new File(fEar, webTags[i].getWebUri());
00922                 tmpFile = tmpFile.getCanonicalFile();
00923                 if (!tmpFile.getPath().startsWith(fEar.getPath())) {
00924                     String err = "Error : The webapp file " + webTags[i] + " is not inside the ear file " + fEar;
00925                     throw new ClientContainerException(err);
00926                 }
00927             }
00928 
00929             for (int i = 0; i < clientTags.length; i++) {
00930                 tmpFile = new File(fEar, clientTags[i]);
00931                 tmpFile = tmpFile.getCanonicalFile();
00932 
00933                 if (!tmpFile.getPath().startsWith(fEar.getPath())) {
00934                     String err = "Error : The client jar file " + clientTags[i] + " is not inside the ear file " + fEar;
00935                     throw new ClientContainerException(err);
00936                 }
00937             }
00938         } catch (IOException ioe) {
00939             String err = "Error while trying to get the canonical file of " + tmpFile;
00940             throw new ClientContainerException(err, ioe);
00941         }
00942 
00943         //Changing array into JarList
00944         JarList ejbsList = new JarList(ejbTags);
00945         JarList websList = new JarList(webTags);
00946         JarList clientsList = new JarList(clientTags);
00947 
00948         // Temporary directory
00949         String tempDir = null;
00950 
00951         if (tmpDir != null) {
00952             // use specific directory
00953             tempDir = tmpDir;
00954             info("Use your specified temp directory '" + tempDir + "'.");
00955         } else {
00956             // use default
00957             tempDir = System.getProperty("java.io.tmpdir");
00958         }
00959 
00960         if (logger.isLoggable(BasicLevel.DEBUG)) {
00961             logger.log(BasicLevel.DEBUG, "Using temp directory '" + tempDir + "'.");
00962         }
00963 
00964         // Can we write to ?
00965         File tmpFileDir = new File(tempDir);
00966 
00967         if (!tmpFileDir.exists() || !tmpFileDir.isDirectory()) {
00968             throw new ClientContainerException("The temp directory '" + tempDir
00969                     + "' doesn't exist or is not a directory.");
00970         }
00971 
00972         if (!tmpFileDir.canWrite()) {
00973             throw new ClientContainerException("Can not write to the temporary directory '" + tempDir + "'.");
00974         }
00975 
00976         // Unpack the ear file and get the unpacked dir
00977         URL dirUnpackURL = null;
00978 
00979         try {
00980             dirUnpackURL = EarFileManager.unpackEar(earUrl, tmpFileDir.toURL(), false);
00981         } catch (Exception e) {
00982             String err = "Error while unpacking the file '" + earUrl + "'";
00983             throw new ClientContainerException(err, e);
00984         }
00985 
00986         // Ear is unpacked, now analyze manifest Class-path:
00987         EarClassPathManager earCPManager = null;
00988 
00989         try {
00990             earCPManager = new EarClassPathManager(clientsList, dirUnpackURL);
00991         } catch (EarClassPathManagerException e) {
00992             String err = "Error while creating the Ear class path manager of the ear : '" + earUrl + "'";
00993             error(err + " : " + e.getMessage());
00994             throw new ClientContainerException(err, e);
00995         }
00996 
00997         URL[] classpathURLs = null;
00998 
00999         //Get the urls of the ear class path manager
01000         try {
01001             classpathURLs = earCPManager.getResolvedClassPath();
01002         } catch (EarClassPathManagerException e) {
01003             String err = "Error while trying to resolve the classpath of the ejbjars and wars of the ear : '" + earUrl
01004                     + "'";
01005             error(err + " : " + e.getMessage());
01006             throw new ClientContainerException(err, e);
01007         }
01008 
01009         if (logger.isLoggable(BasicLevel.DEBUG)) {
01010             logger.log(BasicLevel.DEBUG, "EAR : ejbs = " + ejbsList);
01011             logger.log(BasicLevel.DEBUG, "EAR : clientUrls = " + clientsList);
01012         }
01013 
01014         currentLoader = Thread.currentThread().getContextClassLoader();
01015         earClassLoader = new URLClassLoader(new URL[0], currentLoader);
01016 
01017         //Extract the urls of the jarList
01018         URL[] jarUrls = null;
01019         URL[] warUrls = null;
01020         URL[] clientUrls = null;
01021 
01022         try {
01023             jarUrls = ejbsList.getURLs(dirUnpackURL.toExternalForm());
01024             warUrls = websList.getURLs(dirUnpackURL.toExternalForm());
01025             clientUrls = clientsList.getURLs(dirUnpackURL.toExternalForm());
01026         } catch (JarListException e) {
01027             String err = "Error while geting the Urls from jarlist of the ear : '" + earUrl + "'";
01028             throw new ClientContainerException(err, e);
01029         }
01030 
01031         //Fill Alt-DD for Ejbs and Clients
01032         String altdd = null;
01033         File fAltDD = null;
01034 
01035         //Transorm the array altDDWebs into an array with the absolute URL to
01036         // the file
01037         URL[] clientsAltDDs = new URL[altDDClients.length];
01038 
01039         for (int i = 0; i < altDDClients.length; i++) {
01040             if (altDDClients[i] != null) {
01041                 altdd = altDDClients[i];
01042 
01043                 if (altdd != null) {
01044                     try {
01045                         fAltDD = new File(new URL(dirUnpackURL.toExternalForm() + File.separator + altdd).getFile());
01046                         clientsAltDDs[i] = fAltDD.getCanonicalFile().toURL();
01047                     } catch (MalformedURLException e) {
01048                         String err = "Can't build URL for alt-dd '" + altdd;
01049                         error(err + "': " + e.getMessage());
01050                         throw new ClientContainerException(err, e);
01051                     } catch (IOException ioe) {
01052                         String err = "Can't get canonicalFile() for the file '" + fAltDD;
01053                         error(err + "': " + ioe.getMessage());
01054                         throw new ClientContainerException(err, ioe);
01055                     }
01056                 }
01057             }
01058         }
01059 
01060         URL[] ejbsAltDDs = new URL[altDDEjbs.length];
01061 
01062         for (int i = 0; i < altDDEjbs.length; i++) {
01063             if (altDDEjbs[i] != null) {
01064                 altdd = altDDEjbs[i];
01065 
01066                 if (altdd != null) {
01067                     try {
01068                         fAltDD = new File(new URL(dirUnpackURL.toExternalForm() + File.separator + altdd).getFile());
01069                         ejbsAltDDs[i] = fAltDD.getCanonicalFile().toURL();
01070                     } catch (MalformedURLException e) {
01071                         String err = "Can't build URL for alt-dd '" + altdd;
01072                         error(err + "': " + e.getMessage());
01073                         throw new ClientContainerException(err, e);
01074                     } catch (IOException ioe) {
01075                         String err = "Can't get canonicalFile() for the file '" + fAltDD;
01076                         error(err + "': " + ioe.getMessage());
01077                         throw new ClientContainerException(err, ioe);
01078                     }
01079                 }
01080             }
01081         }
01082 
01083         URL[] websAltDDs = new URL[altDDWebs.length];
01084 
01085         for (int i = 0; i < altDDWebs.length; i++) {
01086             if (altDDWebs[i] != null) {
01087                 altdd = altDDWebs[i];
01088 
01089                 if (altdd != null) {
01090                     try {
01091                         fAltDD = new File(new URL(dirUnpackURL.toExternalForm() + File.separator + altdd).getFile());
01092                         websAltDDs[i] = fAltDD.getCanonicalFile().toURL();
01093                     } catch (MalformedURLException e) {
01094                         String err = "Can't build URL for alt-dd '" + altdd;
01095                         error(err + "': " + e.getMessage());
01096                         throw new ClientContainerException(err, e);
01097                     } catch (IOException ioe) {
01098                         String err = "Can't get canonicalFile() for the file '" + fAltDD;
01099                         error(err + "': " + ioe.getMessage());
01100                         throw new ClientContainerException(err, ioe);
01101                     }
01102                 }
01103             }
01104         }
01105 
01106         EjbDeploymentDescManager.getInstance().setAvailableEjbJarsAndAltDDs(earClassLoader, jarUrls, ejbsAltDDs);
01107         WebDeploymentDescManager.getInstance().setAltDD(earClassLoader, warUrls, websAltDDs);
01108         ClientDeploymentDescManager.getInstance().setAltDD(earClassLoader, clientUrls, clientsAltDDs);
01109 
01110         // Construct the ejb classloader for all the ejb-jars of the same
01111         // ear application. Because there is one ejb classloader for all
01112         // the ejb-jars of the same ear application.
01113         URL[] userURLs = getUserClasspathUrls();
01114         extensionsURLs = new URL[jarUrls.length + classpathURLs.length + userURLs.length];
01115 
01116         System.arraycopy(jarUrls, 0, extensionsURLs, 0, jarUrls.length);
01117         System.arraycopy(classpathURLs, 0, extensionsURLs, jarUrls.length, classpathURLs.length);
01118         System.arraycopy(userURLs, 0, extensionsURLs, jarUrls.length + classpathURLs.length, userURLs.length);
01119 
01120         if (logger.isLoggable(BasicLevel.DEBUG)) {
01121             logger.log(BasicLevel.DEBUG, "Extensions urls :");
01122 
01123             for (int ii = 0; ii < extensionsURLs.length; ii++) {
01124                 logger.log(BasicLevel.DEBUG, "url[" + ii + "] = " + extensionsURLs[ii]);
01125             }
01126         }
01127 
01128         // Choose the jar client
01129         if (clientUrls.length == 0) {
01130             throw new ClientContainerException("No java client was found in the application.xml file of the Ear '"
01131                     + earUrl + "'.");
01132         }
01133 
01134         File fClient = null;
01135 
01136         // User has specify an application client to execute
01137         // Search it
01138         if (jarClient != null) {
01139             int f = 0;
01140             File ff = null;
01141             boolean found = false;
01142 
01143             while (f < clientUrls.length && !found) {
01144                 ff = new File(clientUrls[f].getFile());
01145 
01146                 if (ff.getPath().endsWith(jarClient)) {
01147                     found = true;
01148                     fClient = ff;
01149 
01150                     if (logger.isLoggable(BasicLevel.DEBUG)) {
01151                         logger.log(BasicLevel.DEBUG, "Found a matching client with the name " + ff);
01152                     }
01153                 }
01154 
01155                 f++;
01156             }
01157 
01158             if (!found) {
01159                 throw new ClientContainerException("No client with the name '" + jarClient
01160                         + "' was found in this Ear file");
01161             }
01162         } else {
01163             // Take first
01164             fClient = new File(clientUrls[0].getFile());
01165 
01166             // Warning if many
01167             if (clientUrls.length > 1) {
01168                 warn("There are " + clientUrls.length + " clients in this ear, choosing the first one : "
01169                         + fClient.getName());
01170             }
01171         }
01172 
01173         info("Use the application client '" + fClient + "' of the Ear '" + earUrl + "'.");
01174 
01175         return fClient;
01176     }
01177 
01182     private URL[] getUserClasspathUrls() {
01183         if (classpath == null) {
01184             return new URL[0];
01185         }
01186         String sep = File.pathSeparator;
01187         List clUser = new ArrayList();
01188         StringTokenizer tokenizer = new StringTokenizer(classpath, sep);
01189         while (tokenizer.hasMoreTokens()) {
01190             File file = new File(tokenizer.nextToken());
01191             try {
01192                 clUser.add(file.toURL());
01193             } catch (MalformedURLException mue) {
01194                 warn("Cannot transform to URL the file : '" + file + "'");
01195             }
01196         }
01197         return (URL[]) clUser.toArray(new URL[0]);
01198     }
01199 
01203     private ArrayList getSystemClassPath() {
01204         String cpValue = System.getProperty("java.class.path");
01205 
01206         if (logger.isLoggable(BasicLevel.DEBUG)) {
01207             logger.log(BasicLevel.DEBUG, "java.class.path = " + cpValue);
01208         }
01209 
01210         String sep = File.pathSeparator;
01211         ArrayList h = new ArrayList();
01212         StringTokenizer st = new StringTokenizer(cpValue, sep);
01213 
01214         while (st.hasMoreTokens()) {
01215             h.add(st.nextToken());
01216         }
01217 
01218         return h;
01219     }
01220 
01225     private void info(String s) {
01226         logger.log(BasicLevel.INFO, s);
01227     }
01228 
01233     private void error(String s) {
01234         logger.log(BasicLevel.ERROR, s);
01235     }
01236 
01241     private void warn(String s) {
01242         logger.log(BasicLevel.WARN, s);
01243     }
01244 }

Generated on Tue Feb 15 15:05:14 2005 for JOnAS by  doxygen 1.3.9.1