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

org.objectweb.jonas.client.ClientContainer Maven / Gradle / Ivy

The newest version!
/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S.
 * Contact: [email protected]
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or 1any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id: ClientContainer.java 10678 2007-06-19 12:36:28Z sauthieg $
 * --------------------------------------------------------------------------
 */
package org.objectweb.jonas.client;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

import javax.naming.Context;
import javax.naming.LinkRef;
import javax.naming.NamingException;
import javax.naming.Reference;
import javax.naming.StringRefAddr;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.login.LoginContext;

import org.objectweb.carol.util.configuration.CarolDefaultValues;
import org.objectweb.carol.util.configuration.ConfigurationRepository;
import org.objectweb.jonas.client.naming.ClientInitialContextFactory;
import org.objectweb.jonas.common.Log;
import org.objectweb.jonas.common.cpmanager.EarClassPathManager;
import org.objectweb.jonas.common.cpmanager.EarClassPathManagerException;
import org.objectweb.jonas.common.cpmanager.JarList;
import org.objectweb.jonas.common.cpmanager.JarListException;
import org.objectweb.jonas.naming.JComponentContextFactory;
import org.objectweb.jonas.naming.JNamingManager;
import org.objectweb.jonas.naming.context.SingletonComponentContextFactory;
import org.objectweb.jonas.naming.manager.SingletonNamingManager;
import org.objectweb.jonas.security.auth.callback.NoInputCallbackHandler;
import org.objectweb.jonas.security.jacc.JPolicyUserRoleMapping;
import org.objectweb.jonas.work.EarFileManager;
import org.objectweb.jonas.ws.JServiceFactory;
import org.objectweb.jonas.ws.base.ClientJServiceFactoryFinder;
import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDesc;
import org.objectweb.jonas_client.deployment.api.ClientContainerDeploymentDescException;
import org.objectweb.jonas_client.deployment.lib.ClientDeploymentDescManager;
import org.objectweb.jonas_ear.deployment.api.EarDeploymentDesc;
import org.objectweb.jonas_ear.deployment.api.EarDeploymentDescException;
import org.objectweb.jonas_ear.deployment.lib.EarDeploymentDescManager;
import org.objectweb.jonas_ear.deployment.xml.Web;
import org.objectweb.jonas_ejb.deployment.lib.EjbDeploymentDescManager;

import org.objectweb.jonas_lib.deployment.api.IMessageDestinationRefDesc;
import org.objectweb.jonas_lib.deployment.api.IEJBRefDesc;
import org.objectweb.jonas_lib.deployment.api.IEnvEntryDesc;
import org.objectweb.jonas_lib.deployment.api.IResourceEnvRefDesc;
import org.objectweb.jonas_lib.deployment.api.IResourceRefDesc;
import org.objectweb.jonas_lib.files.FileUtils;
import org.objectweb.jonas_lib.version.Version;
import org.objectweb.jonas_web.deployment.lib.WebDeploymentDescManager;

import org.objectweb.jonas_ws.deployment.api.IServiceRefDesc;
import org.objectweb.jonas_ws.wsgen.WsGen;
import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;

/**
 * Defines the class use for the client container This class analyze the ear or
 * the jar client and launch the client
 * @author Florent Benoit
 */
public class ClientContainer {

    /**
     * Name of the carol file
     */
    private static final String CAROL_FILE = "carol.properties";

    /**
     * Main class to use to launch the application client
     */
    private String mainClass = null;

    /**
     * Temporary directory
     */
    private String tmpDir = null;

    /**
     * Jar client to use (if many)
     */
    private String jarClient = null;

    /**
     * Classpath for the application client
     */
    private String classpath = null;

    /**
     * trace.properties file to use instead of the default file.
     */
    private String clientTraceFile = null;

    /**
     * Reference on the NamingManager.
     */
    private JNamingManager naming;

    /**
     * carol.properties file to use instead of the default file.
     */
    private String carolFile = null;

    /**
     * Arguments used by the client
     */
    private String[] args = null;

    /**
     * Class loader of the EAR
     */
    private URLClassLoader earClassLoader = null;

    /**
     * Extra Arguments
     */
    private ArrayList appArgs = null;

    /**
     * URLs resolved in the case of the extension mechanism in the Ear case
     */
    private URL[] extensionsURLs = null;

    /**
     * Logger to use
     */
    private Logger logger = null;

    /**
     * true if the user want to auto generate web services artifacts
     */
    private boolean applyWsGen = true;

    /**
     * Constructor for a Client container
     * @param args the arguments of the instance of the client container
     */
    private ClientContainer(String[] args) {
        this.args = args;

        appArgs = new ArrayList();
    }

    /**
     * Call the Log class to instanciate the client container logger
     */
    private void initLogger() {
        // Allow tracing ejb/jms code
        Log.configure(clientTraceFile);
        // init the logger
        this.logger = Log.getLogger(Log.JONAS_CLIENT_PREFIX);
    }

    /**
     * Main method of the Client container
     * @param args the arguments of the client container
     */
    public static void main(String[] args) {
        // Retrieve command line parameters
        ClientContainer cc = new ClientContainer(args);

        try {
            cc.start();
        } catch (InvocationTargetException ite) {
            Throwable t = ite.getTargetException();
            String message = t.getMessage();
            if (t instanceof Error) {
                System.err.println("There was the following error : " + message);
            } else if (t instanceof Exception) {
                System.err.println("There was the following exception : " + message);
            }
            t.printStackTrace(System.err);
        } catch (Exception e) {
            System.err.println("There was the following exception : " + e.getMessage());
            e.printStackTrace();
            System.exit(-1);
        }
    }

    /**
     * Start the client container
     * @throws Exception if it fails
     */
    private void start() throws Exception {
        analyzeArgs();

        // Use the specified traceclient.properties
        if (clientTraceFile != null) {
            File tClient = new File(clientTraceFile);

            if (!tClient.exists()) {
                throw new ClientContainerException("The file '" + clientTraceFile + "' was not found.");
            }

            if (!tClient.isFile()) {
                throw new ClientContainerException("The file '" + clientTraceFile
                        + "' is not a valid file. Maybe a directory ?");
            }

            // Configure log
            System.setProperty("jonas.client.trace.file", clientTraceFile);
            Log.reset();
        } else {
            clientTraceFile = "traceclient";
        }

        initLogger();

        // Get the filename
        String userArg = null;
        String fileName = null;
        boolean fileMode = true;

        try {
            userArg = (String) appArgs.get(0);
        } catch (IndexOutOfBoundsException ioobe) {
            usage();
            throw new ClientContainerException(
                    "You haven't specify a jar, an ear file or class name as argument. See the Usage.");
        }

        String className = null;
        // Test if this is an ear or a jar file else it must be a class name
        if (!(userArg.toLowerCase().endsWith(".jar") || userArg.toLowerCase().endsWith(".ear"))) {
            className = userArg;
            fileMode = false;
        } else {
            fileMode = true;
            fileName = userArg;
        }

        // WsGen
        if (applyWsGen && fileMode) {
            try {
                File argFile = new File(fileName);

                if (!argFile.exists()) {
                    throw new ClientContainerException("The specified file '"
                            + fileName + "' doesn't exists.");
                }
                Manifest manifest = new JarFile(argFile).getManifest();

                if (manifest == null) {
                    throw new ClientContainerException(
                            "No manifest was found inside the file" + argFile);
                }

                // Extract attributes
                Attributes attributes = manifest.getMainAttributes();

                if (attributes == null) {
                    throw new ClientContainerException(
                            "No attributes were found in the manifest of the file '"
                                    + argFile + "'.");
                }
                String archiveVersion = attributes.getValue("WsGen-JOnAS-Version");
                if (!Version.getNumber().equals(archiveVersion)) {
                    this.logger.log(BasicLevel.DEBUG, "Archive was not compiled with the latest WsGen. Regenerating ...");
                    // different versions, re-generate Stuff
                    WsGen wsgen = new WsGen();
                    String[] args = {"-d", System.getProperty("java.io.tmpdir"),
                            argFile.getPath()};
                    String resultJarFile = wsgen.execute(args);

                    if (!resultJarFile.equals(argFile.getPath())) {
                        // WsGen changed the archive
                        FileUtils.copyFile(resultJarFile, argFile.getPath());
                        FileUtils.delete(resultJarFile);
                    }
                }

            } catch (Exception e) {
                throw new ClientContainerException(
                        "Cannot apply WsGen on the client archive : " + userArg, e);
            }
        }



        // Build file and test if it exists
        File clientJarFile = null;
        if (fileMode) {
            File argFile = new File(fileName);

            // Unpack and analyze EAR file if it is an ear
            if (fileName.toLowerCase().endsWith(".ear")) {
                clientJarFile = extractAndAnalyzeEar(argFile);
            } else {
                //Client jar is the given file
                clientJarFile = argFile;
            }
        }

        // Carol initialisation (property)
        System.setProperty("javax.rmi.CORBA.PortableRemoteObjectClass",
                           "org.objectweb.carol.rmi.multi.MultiPRODelegate");
         System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.org.objectweb.jotm.ots.OTSORBInitializer",
                           "");
        System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.org.objectweb.jonas.security.interceptors.iiop.SecurityInitializer",
                           "");
        System.setProperty("org.omg.CORBA.ORBClass" , "org.jacorb.orb.ORB");
        System.setProperty("org.omg.CORBA.ORBSingletonClass", "org.jacorb.orb.ORBSingleton");
        System.setProperty("org.omg.PortableInterceptor.ORBInitializerClass.standard_init" , "org.jacorb.orb.standardInterceptors.IORInterceptorInitializer");
        System.setProperty("javax.rmi.CORBA.UtilClass" , "org.objectweb.carol.util.delegate.UtilDelegateImpl");

        // Build a classloader for the initialisation of carol
        // Priority
        //    1/ file as argument
        //    2/ file in the jar client
        //    3/ file in client.jar
        URL urlCarolFile = null;

        if (carolFile != null) {
            File fCarol = new File(carolFile);

            if (!fCarol.exists()) {
                throw new ClientContainerException("The file '" + carolFile + "' was not found.");
            }

            if (!fCarol.isFile()) {
                throw new ClientContainerException("The file '" + carolFile
                        + "' is not a valid file. Maybe a directory ?");
            }

            if (!fCarol.getName().equals(CAROL_FILE)) {
                throw new ClientContainerException("The file '" + carolFile + "' must be named '" + CAROL_FILE + "'.");
            }

            try {
                urlCarolFile = fCarol.toURL();
                if (logger.isLoggable(BasicLevel.DEBUG)) {
                    logger.log(BasicLevel.DEBUG, "Using carol.properties file specified by the user on command line");
                }
            } catch (MalformedURLException mue) {
                throw new ClientContainerException("Error when building an URL for the file '" + fCarol + "'.", mue);
            }
        }

        // carol.properties file in client jar, use it if this is the case ?
        if (urlCarolFile == null && fileMode) {
            URL tmpUrl = null;
            try {
                tmpUrl = clientJarFile.toURL();
            } catch (MalformedURLException mue) {
                throw new ClientContainerException("Error when building an URL for the file '" + clientJarFile + "'.", mue);
            }
            // Build classloader with null parent CL, to see if it is in the file.
            ClassLoader tmpCl = new URLClassLoader(new URL[] {tmpUrl}, null);

            urlCarolFile = tmpCl.getResource(CarolDefaultValues.CAROL_CONFIGURATION_FILE);
            if (urlCarolFile != null) {
                if (logger.isLoggable(BasicLevel.DEBUG)) {
                    logger.log(BasicLevel.DEBUG, "Using carol.properties file of the '" + clientJarFile + "' file.");
                }
            }
        }



        if (urlCarolFile != null) {
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Init carol with URL '" + urlCarolFile + "'.");
            }
            ConfigurationRepository.init(urlCarolFile);
        } else {
            ConfigurationRepository.init();
        }
        // Add Csiv2 Interceptors
        ConfigurationRepository.addInterceptors("iiop", "org.objectweb.jonas.security.iiop.Csiv2Initializer");

        // Must be done AFTER carol init because carol set this property internally.
        System.setProperty("java.naming.factory.initial", ClientInitialContextFactory.class.getName());


        // Carol configuration is done
        // Extract Main-Class to use in the jar from the manifest
        if (fileMode) {
            Manifest manifest = new JarFile(clientJarFile).getManifest();

            if (manifest == null) {
                throw new ClientContainerException("No manifest was found inside the file" + clientJarFile);
            }

            // Extract attributes
            Attributes attributes = manifest.getMainAttributes();

            if (attributes == null) {
                throw new ClientContainerException("No attributes were found in the manifest of the file '"
                        + clientJarFile + "'.");
            }
            mainClass = attributes.getValue(Attributes.Name.MAIN_CLASS);
        } else {
            mainClass = className;
        }

        // Invoke the client if there is no need of XML parsing
        if (!fileMode) {
            ClassLoader clientCL = new URLClassLoader(getUserClasspathUrls());
            Thread.currentThread().setContextClassLoader(clientCL);
            invokeClient();
            return;
        }

        if (mainClass == null || mainClass.length() == 0) {
            throw new ClientContainerException("No main class was found inside the Manifest  of the file '"
                    + clientJarFile + "'. This attribute is required to launch the application client.");
        }

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Using Main-Class :" + mainClass);
        }

        // Convert file to URL
        URL clientJarURL = null;

        try {
            clientJarURL = clientJarFile.toURL();
        } catch (MalformedURLException mue) {
            throw new ClientContainerException("Error when building an URL with the file '" + clientJarFile + "'.", mue);
        }

        // Build the urls for the classloader
        URL[] urlsClient = null;

        // URLs for the classloader
        if (extensionsURLs != null) {
            // There were URLs with the extension mechanism in the EAR
            urlsClient = new URL[extensionsURLs.length + 1];

            for (int i = 0; i < extensionsURLs.length; i++) {
                urlsClient[i] = extensionsURLs[i];

                if (logger.isLoggable(BasicLevel.DEBUG)) {
                    logger.log(BasicLevel.DEBUG, "Adding " + extensionsURLs[i] + " to the urls of the client");
                }
            }

            urlsClient[extensionsURLs.length] = clientJarURL;
        } else {
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Only one url for urls of client");
            }

            // No extension or jar case.
            urlsClient = new URL[1];
            urlsClient[0] = clientJarURL;
        }

        // Build classloader
        URLClassLoader clientClassloader = new URLClassLoader(urlsClient, Thread.currentThread()
                .getContextClassLoader());
        Thread.currentThread().setContextClassLoader(clientClassloader);

        // Get the deployment descriptor from file
        ClientContainerDeploymentDesc clientDD = null;
        if (extensionsURLs != null) {
            EjbDeploymentDescManager.getInstance().addClassLoaderUrlMapping(clientClassloader, extensionsURLs);
        }

        try {
            clientDD = ClientDeploymentDescManager.getInstance().getDeploymentDesc(clientJarURL, clientClassloader, earClassLoader);
        } catch (ClientContainerDeploymentDescException e) {
            String err = "Cannot read the deployment descriptors '" + clientJarURL + "'";
            error(err);
            throw new ClientContainerException(err, e);
        }

        // Populate the java:comp/env (ENC) environment.
        try {
            setClientEnvironment(clientDD);
        } catch (Exception e) {
            //populating environment failed.
            String err = "Error when populating ";
            error(err);
            throw new ClientContainerException(err, e);
        }

        // JAAS
        String jaasFile = clientDD.getJaasFile();
        String jaasEntry = clientDD.getJaasEntry();
        String username = clientDD.getUsername();
        String password = clientDD.getPassword();

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Using jaas file = " + jaasFile);
        }

        String jaasConfigFile = null;

        if (jaasFile != null) {
            // Use JAAS
            jaasConfigFile = "jar:" + clientJarURL.toExternalForm() + "!/" + jaasFile;
            System.setProperty("java.security.auth.login.config", jaasConfigFile);
        }

        CallbackHandler ch = null;

        if ((username != null) && (password != null)) {
            ch = new NoInputCallbackHandler(username, password);
            info("Using the login/password specified in the jonas-client.xml file with a specific CallbackHandler");
        } else {
            // Is there a callbackHandler specified ?
            String ddCallbackHandler = clientDD.getCallbackHandler();

            if (ddCallbackHandler != null) {
                if (logger.isLoggable(BasicLevel.DEBUG)) {
                    logger.log(BasicLevel.DEBUG, "Using '" + ddCallbackHandler + "' class as CallbackHandler.");
                }

                Class clazz = null;

                //try to invoke this class
                try {
                    clazz = clientClassloader.loadClass(ddCallbackHandler);
                } catch (Exception e) {
                    throw new ClientContainerException("There was an error while trying to instantiate the class '"
                            + ddCallbackHandler
                            + "' which is specified in the application.xml as CallbackHandler class", e);
                }

                try {
                    ch = (CallbackHandler) clazz.newInstance();
                } catch (Exception e) {
                    throw new ClientContainerException(
                            "Error while triyng to cast the class '"
                                    + ddCallbackHandler
                                    + "' to CallbackHandler interface, maybe the specified class doesn't implement this interface.",
                            e);
                }
            }
        }

        // Use JAAS
        if (ch != null) {
            if (jaasFile == null) {
                throw new ClientContainerException(
                        "You have defined that you want use a CallbackHandler but you haven't specify the jaas file to use for the JAAS configuration.");
            }

            if (jaasEntry == null) {
                throw new ClientContainerException(
                        "You have defined that you want use a CallbackHandler but you haven't specify the jaas entry to use from the jaas config file.");
            }

            info("Using JAAS loginContext '" + jaasEntry + "' from the file '" + jaasConfigFile + "'.");

            try {
                LoginContext lc = new LoginContext(jaasEntry, ch);
                lc.login();
            } catch (Exception e) {
                String err = "Can not use the JAAS authentication";
                error(err);
                throw new ClientContainerException(err, e);
            }
        }

        // Start client
        invokeClient();

    }

    /**
     * Start the client on its main class with the thread class loader
     * @throws ClassNotFoundException if class is not found
     * @throws NoSuchMethodException if method (main) is not found
     * @throws IllegalAccessException if access is illegal
     * @throws InvocationTargetException if invocation failed
     */
    private void invokeClient() throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException,
            InvocationTargetException {
        ClassLoader clientClassloader = Thread.currentThread().getContextClassLoader();

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            if (clientClassloader instanceof URLClassLoader) {
                URLClassLoader urlClassLoader = (URLClassLoader) clientClassloader;
                URL[] urls = urlClassLoader.getURLs();
                logger.log(BasicLevel.DEBUG, "URLs of the classloader :");
                for (int u = 0; u < urls.length; u++) {
                    logger.log(BasicLevel.DEBUG, "URL[" + u + "] = " + urls[u]);
                }
            }
        }

        // Invoke client
        // Launch the "class_to_run" by using our classloader.
        Class clazz = clientClassloader.loadClass(mainClass);
        Class[] argList = new Class[] {args.getClass()};
        Method meth = clazz.getMethod("main", argList);

        // Remove name of the file from arguments
        String[] newArgs = new String[appArgs.size() - 1];
        String txtArgs = "";

        for (int i = 0; i < newArgs.length; i++) {
            newArgs[i] = (String) appArgs.get(i + 1);
            txtArgs += (newArgs[i] + " ");
        }

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Starting the application client with the arguments '" + txtArgs + "'.");
        }

        info("Starting client...");

        meth.invoke(null, new Object[] {newArgs});

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "End of main method");
        }

    }

    /**
     * Set the environment of this client
     * @param clientDD deployment descriptor used for build the environment
     * @throws NamingException if the creation of the environment fails
     */
    private void setClientEnvironment(ClientContainerDeploymentDesc clientDD) throws NamingException {
        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "");
        }

        //Init the naming manager
        JComponentContextFactory ccf = null;
        try {
            naming = SingletonNamingManager.getInstance();
            ccf = SingletonComponentContextFactory.getInstance();
        } catch (NamingException e) {
            throw new ClientContainerException("Error when getting the reference to the Naming manager", e);
        }

        Context javaCtx = ccf.createComponentContext("ClientContainer");
        naming.setClientContainerComponentContext(javaCtx);

        Context envCtx = javaCtx.createSubcontext("comp/env");

        // Bean Environment
        IEnvEntryDesc[] envt = clientDD.getEnvEntryDesc();

        for (int i = 0; i < envt.length; i++) {
            // get information in descriptor
            String name = envt[i].getName();
            Object obj = envt[i].getValue();

            // register object in JNDI
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Binding object " + name + " -> " + obj);
            }

            envCtx.rebind(name, obj);
        }

        // Resource References
        IResourceRefDesc[] resref = clientDD.getResourceRefDesc();

        for (int i = 0; i < resref.length; i++) {
            // get information in descriptor
            String name = resref[i].getName();
            String resname = resref[i].getJndiName();
            String type = resref[i].getTypeName();

            // build the LinkRef that will be registered:
            // FactoryClassName = null, size = 1, refAddr = resname.
            // register object in JNDI
            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Linking resource " + name + " -> " + resname);
            }

            if (type.equalsIgnoreCase("java.net.URL")) {
                // Specify the factory to use with the right URL
                Reference ref = new Reference("java.net.URL", "org.objectweb.jonas_lib.naming.factory.URLFactory", null);
                StringRefAddr refAddr = new StringRefAddr("url", resname);
                ref.add(refAddr);
                envCtx.rebind(name, ref);
            } else {
                LinkRef lref = new LinkRef(resname);
                envCtx.rebind(name, lref);
            }
        }

        // Resource Environment References
        IResourceEnvRefDesc[] resEnvref = clientDD.getResourceEnvRefDesc();

        for (int i = 0; i < resEnvref.length; i++) {
            // get information in descriptor
            String name = resEnvref[i].getName();
            String resname = resEnvref[i].getJndiName();
            LinkRef lref = new LinkRef(resname);

            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Linking resource environment " + name + " -> " + resname);
            }

            envCtx.rebind(name, lref);
        }

        // EJB References
        IEJBRefDesc[] ejbref = clientDD.getEjbRefDesc();

        for (int i = 0; i < ejbref.length; i++) {
            // get information in descriptor
            String name = ejbref[i].getEjbRefName();
            String ejbname = null;
            ejbname = ejbref[i].getJndiName();

            LinkRef lref = new LinkRef(ejbname);

            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Linking ejb " + name + " -> " + ejbname);
            }

            envCtx.rebind(name, lref);
        }

        // ServiceRef
        IServiceRefDesc[] serviceRefs = clientDD.getServiceRefDesc();
        if (serviceRefs.length != 0) {

            // get the current ClassLoader
            ClassLoader loader = Thread.currentThread().getContextClassLoader();

            // get the JServiceFactory
            JServiceFactory factory = ClientJServiceFactoryFinder.getJOnASServiceFactory();

            for (int i = 0; i < serviceRefs.length; i++) {
                // Create the Service from the ServiceRef description
                String refname = serviceRefs[i].getServiceRefName();

                Reference ref = factory.getServiceReference(serviceRefs[i], loader);
                envCtx.rebind(refname, ref);

                if (logger.isLoggable(BasicLevel.DEBUG)) {
                    logger.log(BasicLevel.DEBUG, "Adding service-ref 'java:comp/env/" + refname + "'");
                }
            }
        }

        // MessageDestination References
        IMessageDestinationRefDesc[] mdref = clientDD.getMessageDestinationRefDesc();

        for (int i = 0; i < mdref.length; i++) {
            // get information in descriptor
            String name = mdref[i].getMessageDestinationRefName();
            String mdname = null;
            mdname = mdref[i].getJndiName();

            LinkRef lref = new LinkRef(mdname);

            if (logger.isLoggable(BasicLevel.DEBUG)) {
                logger.log(BasicLevel.DEBUG, "Linking message-destination-ref " + name + " -> " + mdname);
            }

            envCtx.rebind(name, lref);
        }
    }

    /**
     * Analyze arguments and extract parameters for the client container
     * @throws Exception if there is an error when analyzing arguments
     */
    private void analyzeArgs() throws Exception {
        for (int argn = 0; argn < args.length; argn++) {
            String arg = args[argn];

            try {
                if (arg.equals("-tmpDir")) {
                    tmpDir = args[++argn];

                    continue;
                }

                if (arg.equals("-jarClient")) {
                    jarClient = args[++argn];

                    continue;
                }

                if (arg.equals("-traceFile")) {
                    clientTraceFile = args[++argn];

                    continue;
                }

                if (arg.equals("-carolFile")) {
                    carolFile = args[++argn];

                    continue;
                }

                if (arg.equals("-cp")) {
                    classpath = args[++argn];
                    continue;
                }

                if (arg.equals("-nowsgen")) {
                    applyWsGen = false;
                    continue;
                }

                if (arg.equals("--help") || arg.equals("-help") || arg.equals("-h") || arg.equals("-?")) {
                    usage();
                    System.exit(1);
                }

                // Add argument to the application arguments
                appArgs.add(arg);
            } catch (ArrayIndexOutOfBoundsException aioobe) {
                // The next argument is not in the array
                throw new ClientContainerException("A required parameter was missing after the argument" + arg);
            }
        }
    }

    /**
     * Print the usage of this client
     */
    private void usage() {
        System.out.println("Usage of this client :");
        System.out.println("-------------------------------------------------------------------");
        System.out.println("java -jar client.jar  [options]");
        System.out.println("-------------------------------------------------------------------");
        System.out.println(" -jarClient   : Specify the client jar to use of the ear if many.");
        System.out.println(" -traceFile   : Specify the configuration file to use for the traces\n"
                + "                of this client instead of the default file\n"
                + "                (traceclient.properties) present in client.jar.");
        System.out.println(" -carolFile   : Specify the carol.properties file to use instead of \n"
                + "                the default carol.properties file of the client.jar");
        System.out.println(" -tmpDir      : Specify the temp directory where unpack the ear.");
        System.out.println(" -cp          : Specify the classpath to use for the jar client.");
        System.out.println(" -nowsgen     : Specify if the Container shouldn't use Automated WsGen.");
        System.out.println("-------------------------------------------------------------------");
        System.out.println("  --help  : Display this help.");
        System.out.println("  -help   : Display this help.");
        System.out.println("  -h      : Display this help.");
        System.out.println("  -?      : Display this help.");
        System.out.println("-------------------------------------------------------------------");
    }

    /**
     * Extract the client of an ear and analyze ear too
     * @param earFile ear to be analyzed
     * @return the file of the client which was extracted
     * @throws Exception if the analyze and/or extract fails
     */
    private File extractAndAnalyzeEar(File earFile) throws Exception {
        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "");
        }

        URL earUrl = null;

        try {
            earUrl = earFile.toURL();
        } catch (MalformedURLException mue) {
            throw new ClientContainerException("Can not build an url with the filename '" + earFile + "'.", mue);
        }

        // Create classLoader
        URL[] arrURL = new URL[1];
        arrURL[0] = earUrl;

        // parent classloader is the current classloader
        ClassLoader currentLoader = Thread.currentThread().getContextClassLoader();
        URLClassLoader loaderCls = new URLClassLoader(arrURL, currentLoader);

        EarDeploymentDesc earDD = null;

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Getting the deployment descriptor of the file" + earFile.getPath());
        }

        try {
            earDD = EarDeploymentDescManager.getDeploymentDesc(earFile.getPath(), loaderCls);
        } catch (EarDeploymentDescException e) {
            String err = "Error in the Deployment descriptor '" + earFile + "'";
            throw new ClientContainerException(err, e);
        }

        Map userToRoleMapping = earDD.getUserToRoleMapping();
        // Do user-to-role mapping
        if (userToRoleMapping != null) {
            for (Iterator itMapping = userToRoleMapping.keySet().iterator(); itMapping.hasNext();) {
                String principalName = (String) itMapping.next();
                List roles = (List) userToRoleMapping.get(principalName);
                String[] roleNames = (String[]) roles.toArray(new String[roles.size()]);
                JPolicyUserRoleMapping.addGlobalUserToRoleMapping(principalName, roleNames);
            }
        }


        // Get the tags from the Deployment descriptor
        String[] ejbTags = earDD.getEjbTags();
        Web[] webs = earDD.getWebTags();
        String[] webTags = new String[webs.length];
        String[] clientTags = earDD.getClientTags();
        String[] altDDEjbs = earDD.getAltDDEjbs();
        String[] altDDWebs = earDD.getAltDDWebs();
        String[] altDDClients = earDD.getAltDDClients();

        // Check if all modules are inside the EAR file
        // no relatives mode like ../../file1.jar
        File fEar = null;
        File tmpFile = null;

        try {
            fEar = earFile.getCanonicalFile();
        } catch (IOException ioe) {
            String err = "Error : Can not get canonical file for the file '" + earFile + "'.";
            throw new ClientContainerException(err, ioe);
        }

        try {
            for (int i = 0; i < ejbTags.length; i++) {
                tmpFile = new File(fEar, ejbTags[i]);
                tmpFile = tmpFile.getCanonicalFile();
                if (!tmpFile.getPath().startsWith(fEar.getPath())) {
                    String err = "Error : The ejb-jar file " + ejbTags[i] + " is not inside the ear file " + fEar;
                    throw new ClientContainerException(err);
                }
            }

            for (int i = 0; i < webs.length; i++) {
                tmpFile = new File(fEar, webs[i].getWebUri());
                tmpFile = tmpFile.getCanonicalFile();
                if (!tmpFile.getPath().startsWith(fEar.getPath())) {
                    String err = "Error : The webapp file " + webs[i] + " is not inside the ear file " + fEar;
                    throw new ClientContainerException(err);
                }
                webTags[i] = webs[i].getWebUri();
            }

            for (int i = 0; i < clientTags.length; i++) {
                tmpFile = new File(fEar, clientTags[i]);
                tmpFile = tmpFile.getCanonicalFile();

                if (!tmpFile.getPath().startsWith(fEar.getPath())) {
                    String err = "Error : The client jar file " + clientTags[i] + " is not inside the ear file " + fEar;
                    throw new ClientContainerException(err);
                }
            }
        } catch (IOException ioe) {
            String err = "Error while trying to get the canonical file of " + tmpFile;
            throw new ClientContainerException(err, ioe);
        }

        //Changing array into JarList
        JarList ejbsList = new JarList(ejbTags);
        JarList websList = new JarList(webTags);
        JarList clientsList = new JarList(clientTags);

        // Temporary directory
        String tempDir = null;

        if (tmpDir != null) {
            // use specific directory
            tempDir = tmpDir;
            info("Use your specified temp directory '" + tempDir + "'.");
        } else {
            // use default
            tempDir = System.getProperty("java.io.tmpdir");
        }

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Using temp directory '" + tempDir + "'.");
        }

        // Can we write to ?
        File tmpFileDir = new File(tempDir);

        if (!tmpFileDir.exists() || !tmpFileDir.isDirectory()) {
            throw new ClientContainerException("The temp directory '" + tempDir
                    + "' doesn't exist or is not a directory.");
        }

        if (!tmpFileDir.canWrite()) {
            throw new ClientContainerException("Can not write to the temporary directory '" + tempDir + "'.");
        }

        // Unpack the ear file and get the unpacked dir
        URL dirUnpackURL = null;

        try {
            dirUnpackURL = EarFileManager.unpackEar(earUrl, tmpFileDir.toURL(), false);
        } catch (Exception e) {
            String err = "Error while unpacking the file '" + earUrl + "'";
            throw new ClientContainerException(err, e);
        }

        // Ear is unpacked, now analyze manifest Class-path:
        EarClassPathManager earCPManager = null;

        try {
            earCPManager = new EarClassPathManager(clientsList, dirUnpackURL);
        } catch (EarClassPathManagerException e) {
            String err = "Error while creating the Ear class path manager of the ear : '" + earUrl + "'";
            error(err + " : " + e.getMessage());
            throw new ClientContainerException(err, e);
        }

        URL[] classpathURLs = null;

        //Get the urls of the ear class path manager
        try {
            classpathURLs = earCPManager.getResolvedClassPath();
        } catch (EarClassPathManagerException e) {
            String err = "Error while trying to resolve the classpath of the ejbjars and wars of the ear : '" + earUrl
                    + "'";
            error(err + " : " + e.getMessage());
            throw new ClientContainerException(err, e);
        }

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "EAR : ejbs = " + ejbsList);
            logger.log(BasicLevel.DEBUG, "EAR : clientUrls = " + clientsList);
        }

        currentLoader = Thread.currentThread().getContextClassLoader();
        earClassLoader = new URLClassLoader(new URL[0], currentLoader);

        //Extract the urls of the jarList
        URL[] jarUrls = null;
        URL[] warUrls = null;
        URL[] clientUrls = null;

        try {
            jarUrls = ejbsList.getURLs(dirUnpackURL.toExternalForm());
            warUrls = websList.getURLs(dirUnpackURL.toExternalForm());
            clientUrls = clientsList.getURLs(dirUnpackURL.toExternalForm());
        } catch (JarListException e) {
            String err = "Error while geting the Urls from jarlist of the ear : '" + earUrl + "'";
            throw new ClientContainerException(err, e);
        }

        //Fill Alt-DD for Ejbs and Clients
        String altdd = null;
        File fAltDD = null;

        //Transorm the array altDDWebs into an array with the absolute URL to
        // the file
        URL[] clientsAltDDs = new URL[altDDClients.length];

        for (int i = 0; i < altDDClients.length; i++) {
            if (altDDClients[i] != null) {
                altdd = altDDClients[i];

                if (altdd != null) {
                    try {
                        fAltDD = new File(new URL(dirUnpackURL.toExternalForm() + File.separator + altdd).getFile());
                        clientsAltDDs[i] = fAltDD.getCanonicalFile().toURL();
                    } catch (MalformedURLException e) {
                        String err = "Can't build URL for alt-dd '" + altdd;
                        error(err + "': " + e.getMessage());
                        throw new ClientContainerException(err, e);
                    } catch (IOException ioe) {
                        String err = "Can't get canonicalFile() for the file '" + fAltDD;
                        error(err + "': " + ioe.getMessage());
                        throw new ClientContainerException(err, ioe);
                    }
                }
            }
        }

        URL[] ejbsAltDDs = new URL[altDDEjbs.length];

        for (int i = 0; i < altDDEjbs.length; i++) {
            if (altDDEjbs[i] != null) {
                altdd = altDDEjbs[i];

                if (altdd != null) {
                    try {
                        fAltDD = new File(new URL(dirUnpackURL.toExternalForm() + File.separator + altdd).getFile());
                        ejbsAltDDs[i] = fAltDD.getCanonicalFile().toURL();
                    } catch (MalformedURLException e) {
                        String err = "Can't build URL for alt-dd '" + altdd;
                        error(err + "': " + e.getMessage());
                        throw new ClientContainerException(err, e);
                    } catch (IOException ioe) {
                        String err = "Can't get canonicalFile() for the file '" + fAltDD;
                        error(err + "': " + ioe.getMessage());
                        throw new ClientContainerException(err, ioe);
                    }
                }
            }
        }

        URL[] websAltDDs = new URL[altDDWebs.length];

        for (int i = 0; i < altDDWebs.length; i++) {
            if (altDDWebs[i] != null) {
                altdd = altDDWebs[i];

                if (altdd != null) {
                    try {
                        fAltDD = new File(new URL(dirUnpackURL.toExternalForm() + File.separator + altdd).getFile());
                        websAltDDs[i] = fAltDD.getCanonicalFile().toURL();
                    } catch (MalformedURLException e) {
                        String err = "Can't build URL for alt-dd '" + altdd;
                        error(err + "': " + e.getMessage());
                        throw new ClientContainerException(err, e);
                    } catch (IOException ioe) {
                        String err = "Can't get canonicalFile() for the file '" + fAltDD;
                        error(err + "': " + ioe.getMessage());
                        throw new ClientContainerException(err, ioe);
                    }
                }
            }
        }

        EjbDeploymentDescManager.getInstance().setAvailableEjbJarsAndAltDDs(earClassLoader, jarUrls, ejbsAltDDs);
        WebDeploymentDescManager.getInstance().setAltDD(earClassLoader, warUrls, websAltDDs);
        ClientDeploymentDescManager.getInstance().setAltDD(earClassLoader, clientUrls, clientsAltDDs);

        // Construct the ejb classloader for all the ejb-jars of the same
        // ear application. Because there is one ejb classloader for all
        // the ejb-jars of the same ear application.
        URL[] userURLs = getUserClasspathUrls();
        extensionsURLs = new URL[jarUrls.length + classpathURLs.length + userURLs.length];

        System.arraycopy(jarUrls, 0, extensionsURLs, 0, jarUrls.length);
        System.arraycopy(classpathURLs, 0, extensionsURLs, jarUrls.length, classpathURLs.length);
        System.arraycopy(userURLs, 0, extensionsURLs, jarUrls.length + classpathURLs.length, userURLs.length);

        if (logger.isLoggable(BasicLevel.DEBUG)) {
            logger.log(BasicLevel.DEBUG, "Extensions urls :");

            for (int ii = 0; ii < extensionsURLs.length; ii++) {
                logger.log(BasicLevel.DEBUG, "url[" + ii + "] = " + extensionsURLs[ii]);
            }
        }

        // Choose the jar client
        if (clientUrls.length == 0) {
            throw new ClientContainerException("No java client was found in the application.xml file of the Ear '"
                    + earUrl + "'.");
        }

        File fClient = null;

        // User has specify an application client to execute
        // Search it
        if (jarClient != null) {
            int f = 0;
            File ff = null;
            boolean found = false;

            while (f < clientUrls.length && !found) {
                ff = new File(clientUrls[f].getFile());

                if (ff.getPath().endsWith(jarClient)) {
                    found = true;
                    fClient = ff;

                    if (logger.isLoggable(BasicLevel.DEBUG)) {
                        logger.log(BasicLevel.DEBUG, "Found a matching client with the name " + ff);
                    }
                }

                f++;
            }

            if (!found) {
                throw new ClientContainerException("No client with the name '" + jarClient
                        + "' was found in this Ear file");
            }
        } else {
            // Take first
            fClient = new File(clientUrls[0].getFile());

            // Warning if many
            if (clientUrls.length > 1) {
                warn("There are " + clientUrls.length + " clients in this ear, choosing the first one : "
                        + fClient.getName());
            }
        }

        info("Use the application client '" + fClient + "' of the Ear '" + earUrl + "'.");

        return fClient;
    }

    /**
     * Gets the URL of user classpath (can be empty
     * @return URL of user classpath (-cp arg)
     */
    private URL[] getUserClasspathUrls() {
        if (classpath == null) {
            return new URL[0];
        }
        String sep = File.pathSeparator;
        List clUser = new ArrayList();
        StringTokenizer tokenizer = new StringTokenizer(classpath, sep);
        while (tokenizer.hasMoreTokens()) {
            File file = new File(tokenizer.nextToken());
            try {
                clUser.add(file.toURL());
            } catch (MalformedURLException mue) {
                logger.log(BasicLevel.WARN, "Cannot transform to URL the file : '" + file + "'", mue);
            }
        }
        return (URL[]) clUser.toArray(new URL[0]);
    }

    /**
     * Display an info message with the logger
     * @param s the message
     */
    private void info(String s) {
        logger.log(BasicLevel.INFO, s);
    }

    /**
     * Display an error message with the logger
     * @param s the message
     */
    private void error(String s) {
        logger.log(BasicLevel.ERROR, s);
    }

    /**
     * Display a warn message with the logger
     * @param s the message
     */
    private void warn(String s) {
        logger.log(BasicLevel.WARN, s);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy