ZIP/JAR basierendes Plugin System

Jey

Mitglied
Hi!

Ich arbeite gerade an einem Plugin-System für eine von mir entwickelte Server-Application. Das Plugin besteht aus einer Zip Datei, in der sich zwei Unterverzeichnisse (classes, config) befinden. Das Verzeichniss "classes" enthält die class-Dateien für das Plugin ("config" enthält eine Java-Properties-Datei mit zusätzlichen Informationen).

Ich hab zwei Ansätze dafür gefunden:

Der erste basiert auf dem URLClassloader. Ich übergebe ihm den Pfad zu der Zip/Jar und er lädt die Klasse, ohne irgendwelche Probleme. Dummerweise nicht, wenn sie dich in einem Unterverzeichniss befindet!

Ansatz Nummer zwei bestand darin, mir mittels java.util.zip.ZipFile alle ZipEntry des Archives nach den beiden Dateien durchsuchen zu lassen und einen InputStream zu diesen zu öffnen (ne andere Möglickeit als diese hab ich leider nicht gefunden). Bei der Properties-Datei klappt alles problemlos, da sie den Stream als Argument übernehmen kann. Für die Klasse brauch ich zwangsweise ne URL, da ich keine Möglichkeit kenne, dem URLClassloader einen Stream zu übergeben.

Mein Problem besteht also im wesentlichen darin, dass ich eine Klasse aus dem >>Unterverzeichniss<< eines Archiv zu laden, ohne dieses zu entpacken. Hat jemand eine Idee, die mir weiterhelfen könnte?

Grüße,
Jey
 
Darf ich grundsätzlich fragen, warum du sowas selber schreibst? OSGi bietet sowas out of the box (Klassen direkt im jar, Konfigurationsinformationen im META-INF Ordner). Sehr net, vor allem, weil die Struktur kompatibel zu normalen jars ist. Es gibt desweiteren eine Serviceregistry und du kannst Bundles (Jars) zur Laufzeit starten und beenden.

Vielleicht ne Alternative zum selber coden?

Gruß
Ollie
 
Ich habe sowas mal selber geschrieben da OSGI keine Möglichkeit bietet zwei Instanzen des selben Plugins zu starten...

Dem URLClassLoader musst du den direkten Ordner zu deinen Jars übergen (können ja mehrere URLS drin sein), dann sollte das auch so klappen.
 
Danke für den Verweis aus OSGI. Macht einen guten Ersteindruck, auch wenn ich mir noch nicht sicher bin, ob es wirklich für meine Zwecke geeignet ist. Es kann jedoch nicht schaden, das Ganze mal einer näheren Überprüfung zu unterziehen.

Bis dahin möchte ich versuchen, meinen Ansatz zum Laufen zu bringen. Es folgt ein Beispielcode, den ich aus dem Netz gefischt habe.. für meine Zwecke leicht umgebaut.
Das Problem ist, dass es zu einer "ClassNotFoundException"kommt, sobald folgende Zeile erreicht wird:

Code:
final Class extClass = loader.loadClass("TestPlugin");

Code:
		File file = new File("F://plugins//TestPlugin.jar");

	    if(!file.exists())
	      throw new RuntimeException("Datei nicht vorhanden.");

	    TestPlugin plugin = new TestPlugin();
	    plugin.whoAmI();
	    
	    final URL extLibUrl = new URL("file", "localhost", file.getAbsolutePath());
	    URLClassLoader loader = new URLClassLoader(new URL[]{extLibUrl});

	    final Class extClass = loader.loadClass("TestPlugin");

	    plugin = (TestPlugin) extClass.newInstance();
	    plugin.whoAmI();
 
Hm laut Javadoc muss der Klassenname in loadClass voll qualifiziert sein, womit du ja quasi die ordner angibst. Dann musst du wohl den ordner classes in deinem jar weglassen und die packages im Root deines Jar anfangen, so wie es die Jar Konvention eigentlich vorgibt. Zusammen mit den voll qualifizierten Klassennamen sollte das dann eigentlich tun, meiner Meinung nach.

REINHAUN!
 
Hallo,

wenn du deine Klassen in einer beliebigen Verzeichnishierarchie innerhalb des jar-Files abgelegt hast bleibt dir nur dir weg einen komplett neuen ClassLoader zu schreiben (von URLClassLoader ableiten nützt hier nichts, da du den dort intern verwendeten sun.misc.URLClassPath nicht verwenden kannst, da dieser den Resource Lookup innerhalb einer Resource (Jar-Datei) über eigene Loader (FileLoader, JarLoader) abwickelt die man schlecht (per reflection...) um die dazu notwendige Funktionaltät erweitern kann.

Sehr leicht lässt sich folgendes realisieren:
Jar-File mit den in einer Verzeichnisstruktur eingebetteten Klassen wird zu den benötigten Teilen in ein temporäres Verzeichnis entpackt (e.g. beim erstmaligen Anwendungsstart). Anschließend wird der passende Pfad vom temporären Verzeichnis aus als URL dem URLClassLoader mitgegeben. Dann klappts auch mit eingebetten Resourcen. So machen das viele Application Server (beispielsweise JBoss).

Gruß Tom
 
Danke für die ausführlichen Antworten! Ich werd' dann wohl die Unzip-Methode nehmen. Die scheint am einfachsten realisierbar zu sein!

Danke allerseits!
 

Neue Beiträge

Zurück