You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@maven.apache.org by Douglas Ferguson <do...@epsiia.com> on 2006/08/23 00:19:30 UTC

Jar With Dependencies

Does anybody have a suggestion for creating a jar with dependencies that has all the dependencies exploded?

We have a module that is a composite of a bunch our other modules, the purpose of this is for our client who are using java integration rather than web integration. 

If I send them a jar with dependencies, then they would have to crack the jar open, because the classloader won't read a jar within a jar.

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: Jar With Dependencies

Posted by Arnaud Bailly <ab...@oqube.com>.
Arnaud Bailly <ab...@oqube.com> writes:

Oops ! Did not mean to clutter the list with code, sorry. 

-- 
OQube < software engineering \ génie logiciel >
Arnaud Bailly, Dr.
\web> http://www.oqube.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


RE: Jar With Dependencies

Posted by Douglas Ferguson <do...@epsiia.com>.
Ah.. that's nifty.

However, this is not a console app. These are our java apis that we are sending the client. They need to add this jar to their classpath.

Here's a simplified example what we have:

Common.jar
Persistence.jar
WSA.jar
Client.jar

Where Client.jar is just a composite module with dependencies on Common, Persistence, WSA.

I think the trick is to use the assembly plug and set unpack to true.
However, if someone else knows another trick.....

D-



-----Original Message-----
From: Arnaud Bailly [mailto:abailly@oqube.com] 
Sent: Wednesday, August 23, 2006 8:38 AM
To: Maven Users List
Subject: Re: Jar With Dependencies

Douglas Ferguson <do...@epsiia.com> writes:

> Sure, I'd love to see that script. 

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Lanceur implements Runnable {

	private static final Log LOG = LogFactory.getLog(Lanceur.class);
	
	/*
	 * the command line arguments array
	 */
	private String[] arguments;

	/*
	 * the exit status
	 * 
	 */
	private int status = 0;

	/*
	 * class loader constructed by this lanceur
	 */
	private URLClassLoader loader;

	public static void main(String[] argv) {
  		if(argv.length == 0)
		   System.exit(1); 
		/* first argument is real lanucher class */
	        String real = argv[0];
                Class realC = Class.forName(real);
		/* shift les arguments */
		String[] nargs = new String[argv.length - 1];
		if (nargs.length != 0) {
			System.arraycopy(arguments, 1, nargs, 0, nargs.length);
		}	
		Lanceur l = (Lanceur)realC.newInstance();
		l.setArguments(argv);
		l.run();
	}

	public void run() {
		/* extraction du repertoire */
		String libdir = System.getProperty("libdir","..\\lib");
		if (libdir == null) {
			LOG.error("Definir le repertoire contenant les bibliotheques : -Dlibdir=<xxxxx>");
			setStatus(1);
			return;
		}
		/* verifications */
		File f = new File(libdir);
		if (!f.exists()) {
			LOG.error("Le repertoire" + libdir + " n'existe pas");
			setStatus(2);
			return;
		}
		if (!f.isDirectory()) {
			LOG.error(libdir + " n'est pas un repertoire");
			setStatus(2);
			return;
		}
		if (!f.canRead()) {
			LOG.error("Le contenu de " + libdir + " ne peut etre lu");
			setStatus(2);
			return;
		}
		/* extraction du nom de la classe principale */
		String clname = System.getProperty("main","Main");
		if (clname == null)
			clname = "Main";
		/* construction du classpath */
		File[] jars = f.listFiles(new FileFilter() {

			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".jar")
						|| pathname.getName().endsWith(".zip");
			}

		});
		int ln = jars.length;
		URL[] urls = new URL[ln + 1];
		/* ajout du repertoire courant par defaut*/
		try {
			urls[0] = new URL("file://.");
		} catch (MalformedURLException e) {
			LOG.error("Impossible d'ajouter . au classpath : "
					+ e.getLocalizedMessage());
		}
		for (int i = 0; i < ln; i++)
			try {
				handleJar(jars[i]);
				urls[i] = new URL("file://" + jars[i].getPath());
			} catch (MalformedURLException e) {
				LOG.error("Impossible d'ajouter . au classpath : "
						+ e.getLocalizedMessage());
			}
		/* chargement */
		loader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
		try {
			Class cls = loader.loadClass(clname);
			Method main = cls.getDeclaredMethod("main", new Class[] { nargs
					.getClass() });
			LOG.debug("Execution de "+clname +".main(");
			for(int i=0;i<arguments.length;i++) {
				LOG.debug(arguments[i]);
				if(i < arguments.length -1)
					LOG.debug(','+"");
			}
			LOG.debug(")");
			main.invoke(null, new Object[] { nargs });
		} catch (ClassNotFoundException e) {
			LOG.error("Impossible de trouver la classe " + clname
					+ " : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (SecurityException e) {
			LOG.error("Erreur de securite pour charger la methode main dans "
							+ clname + " : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (NoSuchMethodException e) {
			LOG.error("Impossible de trouver la methode main dans  "
					+ clname + " : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (IllegalArgumentException e) {
			LOG.error("Argument incorrecte a l'execution de " + clname
					+ ".main() : " + e.getLocalizedMessage());
			e.printStackTrace();
			setStatus(3);
		} catch (IllegalAccessException e) {
			LOG.error("Acces interdit a l'execution de " + clname
					+ ".main() : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (InvocationTargetException e) {
			setStatus(4);
			e.printStackTrace();
		}
	}

	/**
	 * This method may be used to do something with the
	 * content of each loaded jar file before they are put into
	 * the classpath.
	 * 
	 * @param file the File object representing a jar or zip file.
	 */
	protected void handleJar(File file) {
		// NOP
	}

	public String[] getArguments() {
		return arguments;
	}

	public void setArguments(String[] arguments) {
		this.arguments = arguments;
	}

	/**
	 * @return Returns the status.
	 */
	public int getStatus() {
		return status;
	}

	/**
	 * @param status The status to set.
	 */
	public void setStatus(int status) {
		this.status = status;
	}

	/**
	 * @return Returns the loader.
	 */
	public URLClassLoader getLoader() {
		return loader;
	}

	/**
	 * @param loader The loader to set.
	 */
	public void setLoader(URLClassLoader loader) {
		this.loader = loader;
	}
}

-- 
OQube < software engineering \ génie logiciel >
Arnaud Bailly, Dr.
\web> http://www.oqube.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org



---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: Jar With Dependencies

Posted by Arnaud Bailly <ab...@oqube.com>.
Douglas Ferguson <do...@epsiia.com> writes:

> Sure, I'd love to see that script. 

import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

public class Lanceur implements Runnable {

	private static final Log LOG = LogFactory.getLog(Lanceur.class);
	
	/*
	 * the command line arguments array
	 */
	private String[] arguments;

	/*
	 * the exit status
	 * 
	 */
	private int status = 0;

	/*
	 * class loader constructed by this lanceur
	 */
	private URLClassLoader loader;

	public static void main(String[] argv) {
  		if(argv.length == 0)
		   System.exit(1); 
		/* first argument is real lanucher class */
	        String real = argv[0];
                Class realC = Class.forName(real);
		/* shift les arguments */
		String[] nargs = new String[argv.length - 1];
		if (nargs.length != 0) {
			System.arraycopy(arguments, 1, nargs, 0, nargs.length);
		}	
		Lanceur l = (Lanceur)realC.newInstance();
		l.setArguments(argv);
		l.run();
	}

	public void run() {
		/* extraction du repertoire */
		String libdir = System.getProperty("libdir","..\\lib");
		if (libdir == null) {
			LOG.error("Definir le repertoire contenant les bibliotheques : -Dlibdir=<xxxxx>");
			setStatus(1);
			return;
		}
		/* verifications */
		File f = new File(libdir);
		if (!f.exists()) {
			LOG.error("Le repertoire" + libdir + " n'existe pas");
			setStatus(2);
			return;
		}
		if (!f.isDirectory()) {
			LOG.error(libdir + " n'est pas un repertoire");
			setStatus(2);
			return;
		}
		if (!f.canRead()) {
			LOG.error("Le contenu de " + libdir + " ne peut etre lu");
			setStatus(2);
			return;
		}
		/* extraction du nom de la classe principale */
		String clname = System.getProperty("main","Main");
		if (clname == null)
			clname = "Main";
		/* construction du classpath */
		File[] jars = f.listFiles(new FileFilter() {

			public boolean accept(File pathname) {
				return pathname.getName().endsWith(".jar")
						|| pathname.getName().endsWith(".zip");
			}

		});
		int ln = jars.length;
		URL[] urls = new URL[ln + 1];
		/* ajout du repertoire courant par defaut*/
		try {
			urls[0] = new URL("file://.");
		} catch (MalformedURLException e) {
			LOG.error("Impossible d'ajouter . au classpath : "
					+ e.getLocalizedMessage());
		}
		for (int i = 0; i < ln; i++)
			try {
				handleJar(jars[i]);
				urls[i] = new URL("file://" + jars[i].getPath());
			} catch (MalformedURLException e) {
				LOG.error("Impossible d'ajouter . au classpath : "
						+ e.getLocalizedMessage());
			}
		/* chargement */
		loader = new URLClassLoader(urls, ClassLoader.getSystemClassLoader());
		try {
			Class cls = loader.loadClass(clname);
			Method main = cls.getDeclaredMethod("main", new Class[] { nargs
					.getClass() });
			LOG.debug("Execution de "+clname +".main(");
			for(int i=0;i<arguments.length;i++) {
				LOG.debug(arguments[i]);
				if(i < arguments.length -1)
					LOG.debug(','+"");
			}
			LOG.debug(")");
			main.invoke(null, new Object[] { nargs });
		} catch (ClassNotFoundException e) {
			LOG.error("Impossible de trouver la classe " + clname
					+ " : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (SecurityException e) {
			LOG.error("Erreur de securite pour charger la methode main dans "
							+ clname + " : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (NoSuchMethodException e) {
			LOG.error("Impossible de trouver la methode main dans  "
					+ clname + " : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (IllegalArgumentException e) {
			LOG.error("Argument incorrecte a l'execution de " + clname
					+ ".main() : " + e.getLocalizedMessage());
			e.printStackTrace();
			setStatus(3);
		} catch (IllegalAccessException e) {
			LOG.error("Acces interdit a l'execution de " + clname
					+ ".main() : " + e.getLocalizedMessage());
			setStatus(3);
		} catch (InvocationTargetException e) {
			setStatus(4);
			e.printStackTrace();
		}
	}

	/**
	 * This method may be used to do something with the
	 * content of each loaded jar file before they are put into
	 * the classpath.
	 * 
	 * @param file the File object representing a jar or zip file.
	 */
	protected void handleJar(File file) {
		// NOP
	}

	public String[] getArguments() {
		return arguments;
	}

	public void setArguments(String[] arguments) {
		this.arguments = arguments;
	}

	/**
	 * @return Returns the status.
	 */
	public int getStatus() {
		return status;
	}

	/**
	 * @param status The status to set.
	 */
	public void setStatus(int status) {
		this.status = status;
	}

	/**
	 * @return Returns the loader.
	 */
	public URLClassLoader getLoader() {
		return loader;
	}

	/**
	 * @param loader The loader to set.
	 */
	public void setLoader(URLClassLoader loader) {
		this.loader = loader;
	}
}

-- 
OQube < software engineering \ génie logiciel >
Arnaud Bailly, Dr.
\web> http://www.oqube.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: Jar With Dependencies

Posted by Arnaud Bailly <ab...@oqube.com>.
Douglas Ferguson <do...@epsiia.com> writes:

> Sure, I'd love to see that script. 

Just to be clear, this is not a script, this is java code for a
wrapper main application that just adds all jars it find in a list of directories
in a classloader then call the real main. I used this as a stable main
entry point for an application assembled with maven-assembly-plugin
which had a set of changing components and as a replacement for a
platform-dependent script. 

For loading jars inside jar:
http://www-128.ibm.com/developerworks/library/j-onejar/

The main wrapper is sent to you by mail.

regards.

-- 
OQube < software engineering \ génie logiciel >
Arnaud Bailly, Dr.
\web> http://www.oqube.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


RE: Jar With Dependencies

Posted by Douglas Ferguson <do...@epsiia.com>.
Sure, I'd love to see that script. 
 
----- Original Message -----
From: Arnaud Bailly 
Sent: Wed, 8/23/2006 2:01am
To: Maven Users List 
Subject: Re: Jar With Dependencies 
 
 
Douglas Ferguson <do...@epsiia.com> writes:

> Does anybody have a suggestion for creating a jar with dependencies
> that has all the dependencies exploded?

There is an <unpack> tag in assembly descriptor that does this.
http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html

>
> If I send them a jar with dependencies, then they would have to crack
> the jar open, because the classloader won't read a jar within a jar.
>

I think that classworlds can do this. You could also write a simple
wrapper classloader that launches your application. I did this once to
ensure platform-independent classpath resolution as I could not write
a script in windows that would add a list of jars in one lib to
classpath (not an expert rin windows scripting obviously). 
If you are interested by this small snippet, I can send you.

BTW, IBM released recently a tool for doing just that kind of things
(loading jars from jars). Lost references to it.

regards

-- 
OQube < software engineering \ génie logiciel >
Arnaud Bailly, Dr.
\web> http://www.oqube.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org

---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org


Re: Jar With Dependencies

Posted by Arnaud Bailly <ab...@oqube.com>.
Douglas Ferguson <do...@epsiia.com> writes:

> Does anybody have a suggestion for creating a jar with dependencies
> that has all the dependencies exploded?

There is an <unpack> tag in assembly descriptor that does this.
http://maven.apache.org/plugins/maven-assembly-plugin/assembly.html

>
> If I send them a jar with dependencies, then they would have to crack
> the jar open, because the classloader won't read a jar within a jar.
>

I think that classworlds can do this. You could also write a simple
wrapper classloader that launches your application. I did this once to
ensure platform-independent classpath resolution as I could not write
a script in windows that would add a list of jars in one lib to
classpath (not an expert rin windows scripting obviously). 
If you are interested by this small snippet, I can send you.

BTW, IBM released recently a tool for doing just that kind of things
(loading jars from jars). Lost references to it.

regards

-- 
OQube < software engineering \ génie logiciel >
Arnaud Bailly, Dr.
\web> http://www.oqube.com


---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe@maven.apache.org
For additional commands, e-mail: users-help@maven.apache.org