<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki.byte-welt.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Knyklak</id>
	<title>Byte-Welt Wiki - Benutzerbeiträge [de]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.byte-welt.net/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Knyklak"/>
	<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php/Spezial:Beitr%C3%A4ge/Knyklak"/>
	<updated>2026-07-10T06:41:00Z</updated>
	<subtitle>Benutzerbeiträge</subtitle>
	<generator>MediaWiki 1.45.1</generator>
	<entry>
		<id>https://wiki.byte-welt.net/index.php?title=Java-Programme_durch_PlugIns_erweitern&amp;diff=9402</id>
		<title>Java-Programme durch PlugIns erweitern</title>
		<link rel="alternate" type="text/html" href="https://wiki.byte-welt.net/index.php?title=Java-Programme_durch_PlugIns_erweitern&amp;diff=9402"/>
		<updated>2021-12-10T12:15:20Z</updated>

		<summary type="html">&lt;p&gt;Knyklak: Kommentare geändert, Code bearbeitet (Variablen ausgelagert), neuen Abschnitt mit gesamter Methode angelegt&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{| align=center border=0 cellpadding=3 cellspacing=3 style=&amp;quot;border: 1px solid #E0E0E0; background-color: #F8F8F8&amp;quot;&lt;br /&gt;
|- &lt;br /&gt;
| style=&amp;quot;font-size: 90%&amp;quot; | [[Bild:Unvollstaendig.png]]  Dieser Artikel ist unvollständig. Hilf mit ihn zu verbessern, erweitere ihn oder beteilige dich an der Diskussion.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Damit [[Programm]]e leicht um neue Teile erweitert werden können, ist es hilfreich und komfortabel, diese mit einer [[Plugin]]-[[Schnittstelle]] auszustatten.&lt;br /&gt;
&lt;br /&gt;
==Voraussetzungen==&lt;br /&gt;
Als Voraussetzung für die Verwendung von Plugins sollten verschiedene [[Klasse]]n und [[Interface (Java) | Interface]]s vorhanden sein:&lt;br /&gt;
# &#039;&#039;&#039;Plugin-Interface&#039;&#039;&#039; - das die Plugins implementieren müssen. Hiermit wird festgelegt welche Funktionen das Plugin der Anwendung anbieten muss.&lt;br /&gt;
# &#039;&#039;&#039;Anwendung-Interface&#039;&#039;&#039; - das die Schnittstelle von den Plugins zur [[Anwendung]] darstellt, hiermit kann kontrolliert werden, was die Anwendungen dürfen und was sie sehen.&lt;br /&gt;
# &#039;&#039;&#039;Manager&#039;&#039;&#039; - gesonderte Klasse für das Laden, Starten und Beenden der Plugins.&lt;br /&gt;
&lt;br /&gt;
==Die Interfaces==&lt;br /&gt;
Das gesamte Plugin-System könnte auch ohne Interfaces geschrieben werden, jedoch ist dies unsicherer. Interfaces standardisieren durch vordefinierte Methoden die Entwicklung und Verwendung von Klassen, was innerhalb der Anwendung sicher stellt, dass nachgerüstete Klassen alle benötigten Methoden bereit stellen. Dadurch ist mit einfachen Mitteln eine gewisse Vielgestaltigkeit möglich.&lt;br /&gt;
&lt;br /&gt;
===Das Plugin-Interface===&lt;br /&gt;
Das Interface für die Plugins muss keine Methoden (Markerinterface), kann aber auch beliebig viele definieren. Es hat sich bewärt, dass das Plugin-Interface mindestens zwei Methoden besitzt &#039;&#039;&#039;start()&#039;&#039;&#039; und &#039;&#039;&#039;stop()&#039;&#039;&#039;. Außerdem eine Methode um die Manager-Klasse zu setzen, sollte das Plugin auf irgendwelche Eigenschaften der Anwendung zugreifen können.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
package net.byte_welt.wiki;&lt;br /&gt;
public interface PluginInterface{&lt;br /&gt;
  public boolean start();&lt;br /&gt;
  public boolean stop();&lt;br /&gt;
  public void setPluginManager(PluginManager manager);&lt;br /&gt;
  public void hello();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Zusätzlich wurde das Interface um die Methode &#039;&#039;hello&#039;&#039; erweitert, somit kann das Plugin von der Anwendung auch benachrichtigt werden.&lt;br /&gt;
&lt;br /&gt;
===Das PluginManager-Interface===&lt;br /&gt;
Das Interface für den Pluginmanager bildet die Schnittstelle vom Plugin zur Anwendung. Hier werden alle Methoden aufgeführt die das Plugin aufrufen darf.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
package net.byte_welt.wiki;&lt;br /&gt;
public interface PluginManager{&lt;br /&gt;
  public void openWindow(String msg);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Unser Plugin-Manager erlaubt nur das Öffnen eines Fensters mit einem String als Nachricht.&lt;br /&gt;
&lt;br /&gt;
==Implementierungen==&lt;br /&gt;
Durch die Interfaces muss für die Entwicklung des Plugins nur die [[Class-Datei | Class]]- oder [[Java-Dateien]] weiter gegeben  werden, die [[Implementierung]]en des PluginManagers dagegen nicht.&lt;br /&gt;
&lt;br /&gt;
===Hello-Plugin===&lt;br /&gt;
Unser Plugin soll beim Aufruf der &#039;&#039;hello()&#039;&#039;-Methode nur ein Fenster öffnen und dort &#039;&#039;Hallo&#039;&#039; ausgeben, daher fällt die Implementierung sehr einfach aus. Die &#039;&#039;start()&#039;&#039;- und &#039;&#039;stop()&#039;&#039;-Methoden werden garnicht benötigt, würde der Text aus einer [[Datenbank]] oder [[Datei]] gelesen werden könnte dies in der &#039;&#039;start&#039;&#039;-Methode erledigt werden&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
package net.byte_welt.wiki;&lt;br /&gt;
public class HelloPlugin implements PluginInterface{&lt;br /&gt;
  private PluginManager manager;&lt;br /&gt;
  public boolean start(){&lt;br /&gt;
    System.out.println(&amp;quot;ich starte&amp;quot;);&lt;br /&gt;
    return true;&lt;br /&gt;
  }&lt;br /&gt;
  public boolean stop(){&lt;br /&gt;
    System.out.println(&amp;quot;ich stoppe&amp;quot;);&lt;br /&gt;
    return true;&lt;br /&gt;
  }&lt;br /&gt;
  public void setPluginManager(PluginManager manager){&lt;br /&gt;
    this.manager = manager;&lt;br /&gt;
  }&lt;br /&gt;
  public void hello(){&lt;br /&gt;
    manager.openWindow(&amp;quot;hallo&amp;quot;);&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===PluginManager===&lt;br /&gt;
Der Plugin-Manager kann für zwei Aufgaben verwendet werden. Er kann dem Plugin übergeben werden und zusätzlich kann er die Kontrolle der Plugins übernehmen. Unser Pluginmanager übernimmt beide Aufgaben, daher implementiert er das PluginManager-Interface. Zusätzlich werden die [[Methode|Methoden]] &#039;&#039;loadPlugin&#039;&#039;, &#039;&#039;start&#039;&#039; und &#039;&#039;stop&#039;&#039; implementiert.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
package net.byte_welt.wiki;&lt;br /&gt;
import java.io.*;&lt;br /&gt;
import java.util.jar.*;&lt;br /&gt;
import java.net.*;&lt;br /&gt;
&lt;br /&gt;
public class PluginManagerImpl implements PluginManager{&lt;br /&gt;
&lt;br /&gt;
  private List&amp;lt;PluginInterface&amp;gt; loadedplugins = new ArrayLIst&amp;lt;&amp;gt;();&lt;br /&gt;
&lt;br /&gt;
  public void start(){&lt;br /&gt;
  //..&lt;br /&gt;
  }&lt;br /&gt;
  public void stop(){&lt;br /&gt;
  //..&lt;br /&gt;
  }&lt;br /&gt;
  public void loadPlugin(File file){&lt;br /&gt;
  //..&lt;br /&gt;
  }&lt;br /&gt;
  public void openWindow(String msg){&lt;br /&gt;
  //..&lt;br /&gt;
  }&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====Start-Methode====&lt;br /&gt;
Die &#039;&#039;start&#039;&#039;-Methode wird aufgerufen, wenn die Anwendung gestartet wird und alle vorhandenen Plugins geladen werden sollen. Die Pfade zu den vorhandenen Plugins lassen sich z.B. extra speichern, oder es wird gesagt, alles was im Ordner &#039;&#039;&#039;plugins&#039;&#039;&#039; liegt gilt als Plugin. In unserem Fall wird gesagt, was im Ordner &#039;&#039;&#039;plugins&#039;&#039;&#039; liegt wird geladen, dafür wird nur die &#039;&#039;loadPlugin&#039;&#039;-Methode aufgerufen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void start(){&lt;br /&gt;
  File[] files = new File(&amp;quot;plugins&amp;quot;).listFiles();&lt;br /&gt;
  for(File f : files)&lt;br /&gt;
    loadPlugin(f);&lt;br /&gt;
  for(PluginInterface pi : loadedplugins)&lt;br /&gt;
    pi.start();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Sind alle Plugins geladen, werden sie gestartet.&lt;br /&gt;
&lt;br /&gt;
====Stop-Methode====&lt;br /&gt;
Mit der &#039;&#039;stop&#039;&#039;-Methode wird den Plugins signalisiert, dass sie herunterfahren sollen. Dies ist der Fall, wenn z.B. das Programm beendet wird.&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void stop(){&lt;br /&gt;
  for(PluginInterface pi : loadedplugins)&lt;br /&gt;
    pi.stop();&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
====LoadPlugin-Methode====&lt;br /&gt;
Um Plugins zu laden, gibt es zwei Ansätze. Zum einen gibt es die Möglichkeit [[Class-Datei|Class-Dateien]] aber auch [[JAR-Datei|JAR-Dateien]] zu laden.&lt;br /&gt;
&lt;br /&gt;
=====JAR-Dateien laden=====&lt;br /&gt;
Um ein Plugin aus einer JAR-Datei zu laden, muss deren Pfad und die [[Main-Class]] bekannt sein. Im Gegensatz zu einer normalen Anwendung ist die Main-Class bei einem Plugin die [[Klasse]], die das [[Interface]] für die Plugin-Schnittstelle implementiert. Es ist aber auch möglich, alle Klassen der JAR zu durchlaufen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
//Erzeugen des JAR-Objekts durch die Eingabe der eingelesenen File in file&lt;br /&gt;
JarFile file = new JarFile(file);&lt;br /&gt;
//Laden der MANIFEST.MF&lt;br /&gt;
Manifest manifest = file.getManifest();&lt;br /&gt;
// auslesen der Attribute aus der Manifest&lt;br /&gt;
Attributes attrib = manifest.getMainAttributes();&lt;br /&gt;
// holen der Mainclass aus den Attributen&lt;br /&gt;
String main = attrib.getValue(Attributes.Name.MAIN_CLASS);&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Aus dem [[JAR-Datei#MANIFEST.MF|Manifest]]-Objekt lassen sich jetzt beliebige Daten auslesen, jedoch werden hier nur die Informationen über die Main-Class benötigt. Mit diesen Daten lässt sich jetzt das Plugin laden, dazu wird ein neuer [[ClassLoader (Java) |ClassLoader]] erzeugt.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
//Festlegen wo das PluginInterface liegt&lt;br /&gt;
String PLUGININTERFACECLASS_STRING = &amp;quot;net.byte_welt.wiki.PluginInterface&amp;quot;;&lt;br /&gt;
// Laden der Datei und Konvertierung von einer Datei, zu einer URI und dann zu einer URL&lt;br /&gt;
URL urlFile = file.toURI().toURL();&lt;br /&gt;
// Laden der Klasse durch den URLClassLoader&lt;br /&gt;
URLClassLoader classLoader = new URLClassLoader(new URL[] { urlFile });&lt;br /&gt;
// Class aus dem classLoader holen&lt;br /&gt;
Class cl = classLoader.loadClass(main);&lt;br /&gt;
// Interfaces aus der Klasse holen, die dort impementiert sind&lt;br /&gt;
Class[] interfaces = cl.getInterfaces();&lt;br /&gt;
// Durchlaufen durch die Interfaces der Klasse und nachsehen ob es das passende Plugin implementiert&lt;br /&gt;
boolean isplugin = false;&lt;br /&gt;
for(int y = 0; y &amp;lt; interfaces.length &amp;amp;&amp;amp; !isplugin; y++)&lt;br /&gt;
  if(interfaces[y].getName().equals(PLUGININTERFACECLASS_STRING))&lt;br /&gt;
    isplugin = true;&lt;br /&gt;
if(isplugin){&lt;br /&gt;
  PluginInterface plugin = (PluginInterface) cl.newInstance();&lt;br /&gt;
  loadedplugins.add(plugin);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
//Schließen von JarFile und ClassLoader um Fehler zu vermeiden&lt;br /&gt;
//jarFile.close();&lt;br /&gt;
classLoader.close();&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
Anschließend werden die Interfaces der Klasse betrachtet, ob es sich wirklich um ein Plugin handelt. Ist es ein Plugin wird eine neue Instanz erzeugt und diese abgespeichert.&lt;br /&gt;
&lt;br /&gt;
=====JAR-Dateien laden (Die Methode komplett)=====&lt;br /&gt;
Um ein Plugin aus einer JAR-Datei zu laden, muss deren Pfad und die [[Main-Class]] bekannt sein. Im Gegensatz zu einer normalen Anwendung ist die Main-Class bei einem Plugin die [[Klasse]], die das [[Interface]] für die Plugin-Schnittstelle implementiert. Es ist aber auch möglich, alle Klassen der JAR zu durchlaufen.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
&lt;br /&gt;
//Festlegen wo das PluginInterface liegt&lt;br /&gt;
private static final String PLUGININTERFACECLASS_STRING = &amp;quot;net.byte_welt.wiki.PluginInterface&amp;quot;;&lt;br /&gt;
&lt;br /&gt;
		public void loadPlugin(File file) {&lt;br /&gt;
		try {&lt;br /&gt;
			// Erzeugen des JAR-Objekts durch die Eingabe der eingelesenen File in file&lt;br /&gt;
			JarFile jarFile = new JarFile(file);&lt;br /&gt;
			// Laden der MANIFEST.MF&lt;br /&gt;
			Manifest manifest = jarFile.getManifest();&lt;br /&gt;
			// Auslesen der Attribute aus der Manifest-Datei&lt;br /&gt;
			Attributes attrib = manifest.getMainAttributes();&lt;br /&gt;
			// Mainclass aus den Attributen laden&lt;br /&gt;
			String main = attrib.getValue(Attributes.Name.MAIN_CLASS);&lt;br /&gt;
			// Laden der Datei und Konvertierung von einer Datei, zu einer URI und dann zu&lt;br /&gt;
			// einer URL&lt;br /&gt;
			URL urlFile = file.toURI().toURL();&lt;br /&gt;
			// Laden der Klasse durch den URLClassLoader&lt;br /&gt;
			URLClassLoader classLoader = new URLClassLoader(new URL[] { urlFile });&lt;br /&gt;
			// Class aus dem classLoader holen&lt;br /&gt;
			Class cl = classLoader.loadClass(main);&lt;br /&gt;
			// Interfaces aus der Klasse holen, die dort impementiert sind&lt;br /&gt;
			Class[] interfaces = cl.getInterfaces();&lt;br /&gt;
			// Durchlaufen durch die Interfaces der Klasse und nachsehen ob es das&lt;br /&gt;
			// PluginInterface implementiert und somit ein Plugin ist&lt;br /&gt;
			boolean isplugin = false;&lt;br /&gt;
			for (int y = 0; y &amp;lt; interfaces.length &amp;amp;&amp;amp; !isplugin; y++)&lt;br /&gt;
				if (interfaces[y].getName().equals(PLUGININTERFACECLASS_STRING))&lt;br /&gt;
					isplugin = true;&lt;br /&gt;
			// Wenn es ein Plugin ist, dann lade die Datei bzw. das Plugin&lt;br /&gt;
			if (isplugin) {&lt;br /&gt;
				PluginInterface plugin = (PluginInterface) cl.newInstance();&lt;br /&gt;
			        // Zu den geladenen Plugin hinzufügen&lt;br /&gt;
				loadedplugins.add(plugin);&lt;br /&gt;
			}&lt;br /&gt;
			// Schließen von JarFile und ClassLoader um Fehler zu vermeiden&lt;br /&gt;
			jarFile.close();&lt;br /&gt;
			classLoader.close();&lt;br /&gt;
		} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | IOException e) {&lt;br /&gt;
			System.out.println(&amp;quot;Plugin konnte nicht geladen werden!&amp;quot;);&lt;br /&gt;
			e.printStackTrace();&lt;br /&gt;
		}&lt;br /&gt;
	}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=====Class-Dateien laden=====&lt;br /&gt;
* wird nachgeliefert.&lt;br /&gt;
&lt;br /&gt;
===OpenWindow-Methode===&lt;br /&gt;
Die &#039;&#039;openWindow&#039;&#039;-Methode ist für die Interaktion mit den Plugins nötig, über diese Methode kann ein Fenster geöffnet werden.&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;java&amp;quot;&amp;gt;&lt;br /&gt;
public void openWindow(String msg){&lt;br /&gt;
  javax.swing.JOptionPane.showMessageDialog(null, msg);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Weblinks=&lt;br /&gt;
*[http://www.java-blog-buch.de/d-plugin-entwicklung-in-java/ Java Blog Buch: Plugin-Entwicklung in Java]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Tutorials (Java)]]&lt;br /&gt;
[[Kategorie:Java]]&lt;/div&gt;</summary>
		<author><name>Knyklak</name></author>
	</entry>
</feed>