# Jar Dateien aus jar Datei in Classpath Aufnehmen



## Thomas Darimont (7. Juni 2005)

Hallo!

Beispielszenario:
Wir haben ein jar namens superswt.jar mit dem folgenden Aufbau:

superswt.jar/swt-win32-3063.dll
superswt.jar/META-INF/Manifest.mf
superswt.jar/lib/swt.jar
superswt.jar/de/tutorials/SWTExample.class

SWTExample.jar

```
/*
 * Created on 06.06.2005@13:46:36
 *
 * TODO Some Licence info...
 */
package de.tutorials;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLClassLoader;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
 * @author TDarimont
 * 
 * TODO Explain me
 */
public class SWTExample {

    public static void main(String[] args) throws Exception {
        final String SWT_DLL_FILENAME = "swt-win32-3063.dll";
        final File file = new File(SWT_DLL_FILENAME);
        
        ClassLoader cl = SWTExample.class.getClassLoader();
        URL url = cl.getResource("lib/swt.jar");
        
        URLClassLoader ucl = new URLClassLoader(new URL[]{url},cl);
        
        Thread.currentThread().setContextClassLoader(ucl);

        if (!file.exists()) {
            InputStream is = SWTExample.class.getClassLoader()
                    .getResourceAsStream(SWT_DLL_FILENAME);

            FileOutputStream fos = new FileOutputStream(file);
            byte[] buffer = new byte[1024];
            int len = 0;

            while ((len = is.read(buffer)) >= 0) {
                fos.write(buffer, 0, len);
            }
            is.close();
            fos.flush();
            fos.close();
        }

        Display display = new Display();
        Shell shell = new Shell(display);
        shell.setText("SWTExample");
        shell.open();

        while (!shell.isDisposed()) {
            if (!display.readAndDispatch()) {
                display.sleep();
            }
        }
        
        //Try to delete swt-lib...
        file.delete();
        
        //Oder
//        Runtime.getRuntime().addShutdownHook(new Thread(){
//           public void run(){
//               file.delete();
//           }
//        });
    }
}
```

Das "Geheimnis" besteht darin den aktuellen ContextClassLoader auf einen neuen ClassLoader zu setzen welcher Zugriff auf unser "jar im jar" hat.

Mit dem Kommando java -jar superswt.jar führen wir das ganze dann aus.l

(Beispiel stammt aus http://www.tutorials.de/tutorials207869.html )

Gruß Tom


----------



## zerix (7. Juni 2005)

*Re: Jar Dateinen aus jar Datein in Classpath Aufnehmen*

Hallo,
Ich wollte mich mal bedanken, das ist genau das was ich gebraucht habe!


----------



## Thomas Darimont (7. Juni 2005)

*Re: Jar Dateinen aus jar Datein in Classpath Aufnehmen*

Hallo!

Kommando zurück... geht so doch nicht... hatte das swt.jar noch in einem anderen Verzeichnis im Classpath liegen... shame on me...

Gruß Tom


----------



## Thomas Darimont (7. Juni 2005)

*Re: Jar Dateinen aus jar Datein in Classpath Aufnehmen*

Hallo!

Dann eben "Brute-Force" mit dynamischen hinzufügen zum Classpath der Anwendung...


```
/**
 * 
 */
package de.tutorials;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.net.URL;
import java.net.URLClassLoader;

import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

/**
 * @author Tom
 * 
 */
public class JarInJarExample {

	/**
	 * @param args
	 */
	public static void main(String[] args) throws Exception {

		// Jar File im Jar... (liegt in diesem Beispiel innerhalb des jars im
		// Verzeichnis lib
		final String SWT_LIB_FILENAME = "org.eclipse.swt.win32.win32.x86_3.1.0.jar";

		ClassLoader cl = JarInJarExample.class.getClassLoader();

		InputStream is = cl.getResourceAsStream("lib/" + SWT_LIB_FILENAME);

		File tmpLib = new File(System.getProperty("java.io.tmpdir") + "/"
				+ SWT_LIB_FILENAME);

		System.out.println(tmpLib);

		// Wir extrahieren das Jar File aus dem jar File und schreiben es in ein
		// temporäres Verzeichnis...
		if (!tmpLib.exists()) {
			FileOutputStream fos = new FileOutputStream(tmpLib);

			int len = 0;
			byte[] buffer = new byte[16384];

			while ((len = is.read(buffer)) > 0) {
				fos.write(buffer, 0, len);
			}
			fos.flush();
			fos.close();
		}

		// Wir löschen das extrahierte jar File beim beenden...
		tmpLib.deleteOnExit();

		// Wir fügen das extrahierte Jar File zum Classpath hinzu...
		Method m = URLClassLoader.class.getDeclaredMethod("addURL",
				new Class[] { URL.class });
		m.setAccessible(true);
		m.invoke(cl, new Object[] { tmpLib.toURL() });

		Display display = new Display();
		Shell shell = new Shell(display);
		shell.setText("SWTExample");
		shell.open();

		while (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
}
```

... das muss aber auch anders gehen ... die ganzen ApplicationsServer können das ja auch... na ja, irgendwann bekommen wir das auch noch hin ;-)

Gruß tom


----------



## zerix (7. Juni 2005)

*Re: Jar Dateinen aus jar Datein in Classpath Aufnehmen*

Denke ich auch.
Ich mach jetzt erstmal das ein Prog was ich hier noch hab fertig, dann setz ich mich mal wieder dran


----------



## bhuber (8. Juni 2011)

klasse beispiel.. hat mir weitergeholfen. Ist zwar ein "Hack" aber tut seine Aufgabe und ist recht übersichtlich und verständlich


----------

