Jar Dateien aus jar Datei in Classpath Aufnehmen

Thomas Darimont

Erfahrenes Mitglied
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
Code:
/*
 * 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
 
Re: Jar Dateinen aus jar Datein in Classpath Aufnehmen

Hallo,
Ich wollte mich mal bedanken, das ist genau das was ich gebraucht habe! :)
 
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
 
Re: Jar Dateinen aus jar Datein in Classpath Aufnehmen

Hallo!

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

Code:
/**
 * 
 */
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
 
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 :)
 
klasse beispiel.. hat mir weitergeholfen. Ist zwar ein "Hack" aber tut seine Aufgabe und ist recht übersichtlich und verständlich ;)
 
Zurück