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);
}
}