tutorials.de Buch-Aktion 05/2012
Like Tree2Danke
  • 1 Beitrag von Kai008
  • 1 Beitrag von miffi
ERLEDIGT
NEIN
ANTWORTEN
14
ZUGRIFFE
554
EMPFEHLEN
  • An Twitter übertragen
  • An Facebook übertragen
AUF DIESES THEMA
ANTWORTEN
  1. #1
    Unicate Unicate ist offline Mitglied Brokat
    Registriert seit
    Apr 2005
    Beiträge
    358
    Hi alle zusammen!

    Ich habe ein Programm, welches ich gern per Plugin erweiterbar machen möchte. (ala Firefox,Eclipse oder so ähnlich)
    Wie setze ich sowas um?

    Weiß jemand wie man's macht oder hat jemand vllt. nen Link?

    Danke schonnema!
     
    /* no comment */

  2. #2
    Kai008 Kai008 ist offline Mitglied Brillant
    Registriert seit
    May 2008
    Ort
    Brunn/Geb. (Niederösterreich)
    Beiträge
    944
    Blog-Einträge
    1
    Geht ganz einfach. Ich definiere zuerst ein Interface oder eine abstrakte Klasse. Erzeuge ein neues Projekt, füge eine Klasse ein die davon erbt oder es implemententiert (um Parameter übergeben zu können).
    In Eclipse lege ich das Hauptprojekt als Projektverknüpfung fest, damit ich auf die Klasse/Interface zugreifen kann. Dann mache ich aus dem Plugin eine jar, lade ichs einfach per URLClassLoader von der HDD im Hauptprojekt und rufe die geerbte/implementierte Klasse davon auf.
     
    Mein kleiner webstart Projektplaner:
    http://178.77.101.236/ppws/
    Ideen, Verbesserungsvorschläge, Bugsmeldungen und allg. Kritik erwünscht und erbeten.

    Danke. :)

  3. #3
    Avatar von Artorius
    Artorius Artorius ist offline Mitglied Plutonium
    Registriert seit
    Feb 2010
    Beiträge
    222
    Hi!
    Hier findet man auche in kleiens Beispielprojekt: http://www.java-blog-buch.de/d-plugi...klung-in-java/

    Es gibt aber auch Frameworks, die es einem erleichtern, Plugin-fähige Anwendungen zu erstellen:
    http://jpf.sourceforge.net/
    Grüße!
     
    Wenn du eine weise Antwort verlangst, musst du vernünftig fragen.
    (Johann Wolfgang von Goethe)
    ----------------------------------------------------------------------
    FLEXibler Java Entwickler

  4. #4
    Unicate Unicate ist offline Mitglied Brokat
    Registriert seit
    Apr 2005
    Beiträge
    358
    OK, ich danke Dir!

    Hier Beispielcode für alle die den Thread finden

    Zuerst das Interface im Hauptprojekt:
    Code java:
    1
    2
    3
    4
    5
    6
    
    package de.unicate.playground;
     
    public interface IPlugin {
        
        public String getName();
    }
    Jetzt das Hauptprojekt, wo das Plugin geladen werden soll:
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    
    package de.unicate.playground;
     
    import java.io.File;
    import java.net.URL;
    import java.net.URLClassLoader;
     
     
    public class Playground {
     
        private IPlugin plugin; 
        private Playground() {
            plugin = null;
        }   
        public static void main(String[] args) throws Exception{
            Playground main = new Playground();
            main.init();
            main.start();
        }
        private void start() {
            if(null != plugin) {
                System.out.println(plugin.getName());
            } else {
                System.err.println("Pluginerror");
            }
        }
        private void init() throws Exception {
            URL pluginFile = null;
            File file = new File("TestPlugin.jar");
            if(!file.exists())
                return;
            pluginFile = new URL("file", "localhost", file.getAbsolutePath());
            URL[] urls = {pluginFile};
            URLClassLoader loader = new URLClassLoader(urls,Thread.currentThread().getContextClassLoader());
            plugin =  (IPlugin)loader.loadClass("de.unicate.playground.plugin.PlaygroundPlugin").newInstance();
        
        }       
    }

    Und zu guter letzt noch das Plugin, was ich in einem eigenen Projekt erstellt habe und das Hauptprojekt verknüpft habe, damit das Interface auffindbar ist:
    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    
    package de.unicate.playground.plugin;
     
    import de.unicate.playground.IPlugin;
     
    public class PlaygroundPlugin implements IPlugin{
     
        public PlaygroundPlugin() {
            
        }
        @Override
        public String getName() {
            return  "Ich bin ein Plugin";
            
        }
     
    }

    Relativ einfach und funktioniert!


    Danke nochmal an Kai008!
     
    /* no comment */

  5. #5
    Kai008 Kai008 ist offline Mitglied Brillant
    Registriert seit
    May 2008
    Ort
    Brunn/Geb. (Niederösterreich)
    Beiträge
    944
    Blog-Einträge
    1
    Du kannst eine File auch mit toURI.toURL (oder toURL, aber veraltet, weil keine Sonderzeichen escaped werden) umwandeln. Der 2. Parameter bei der Intialisierung des URLClassLoader ist nicht notwendig. (Constructs a new URLClassLoader for the specified URLs using the default delegation parent ClassLoader.)
     
    Mein kleiner webstart Projektplaner:
    http://178.77.101.236/ppws/
    Ideen, Verbesserungsvorschläge, Bugsmeldungen und allg. Kritik erwünscht und erbeten.

    Danke. :)

  6. #6
    Registriert seit
    Jun 2002
    Ort
    Saarbrücken (Saarland)
    Beiträge
    9.886
    Blog-Einträge
    29
     
    Java rocks!
    How to become a good Java Programmer?
    Does IT in Java and .Net
    The only valid measurement of code quality: WTFs / minute
    Blog
    Xing
    Twitter

  7. #7
    Unicate Unicate ist offline Mitglied Brokat
    Registriert seit
    Apr 2005
    Beiträge
    358
    OK Danke der ServiceLoader ist glaub ich genau nach was ich suche.

    Aber: Wie kann ich Services dann dynamisch aus 2 oder mehr Projekten laden?
    Geändert von Unicate (21.04.10 um 10:12 Uhr)
     
    /* no comment */

  8. #8
    Avatar von miffi
    miffi miffi ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Ravensburg (BW)
    Beiträge
    139
    Howdie.

    Ich hab praktisch identischen Code, wie du in deinem Beispielcode gezeigt hast, Unicate. Momentan arbeite ich an einem größeren Projekt, in dem einzelne Module nachladbar sein sollen.
    Bei mir ist jetzt das Problem, dass ein AbstractMethodError geworfen wird, obwohl ich über
    Code java:
    1
    2
    
    // RCBModule ist das Interface, das ich für ladbare Module benutze
    RCBModule module = (RCBModule)classLoader.loadClass(modulePackagePath).newInstance();
    eigentlich eine Instanz erzeugt haben müsste, oder? Dieser Fehler wird ja eigentlich nur geworfen, wenn eine nicht überschriebene Methode einer abstrakten Klasse (oder wie hier eines Interfaces) aufgerufen wird.
    Oder muss ich den Konstruktur der implementierenden Klasse auf irgendeine Art und Weise explizit aufrufen?

    Falls alle Stricke reißen muss ich halt doch auch den ServiceLoader benutzen... Wäre aber dankbar für Tipps.

    Gruß
    miffi
     
    "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
    Douglas Adams

  9. #9
    Kai008 Kai008 ist offline Mitglied Brillant
    Registriert seit
    May 2008
    Ort
    Brunn/Geb. (Niederösterreich)
    Beiträge
    944
    Blog-Einträge
    1
    Thrown when an application tries to call an abstract method. Normally, this error is caught by the compiler; this error can only occur at run time if the definition of some class has incompatibly changed since the currently executing method was last compiled.

    Ich lade die Klassen Problemlos mit dem URLClassLoader aus einer Jar, die ich aus einen übertragenen String der ein Server an den/die Clienten übermittelt.

    Code java:
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    
    public Plugin(File pluginFile)
    {
        super();
        
        try
        {
            //TODO Hardcodet, read the Classes from File in Jar
            URLClassLoader classLoader = new URLClassLoader(new URL[] {
                pluginFile.toURI().toURL()
            });
            Class<?> loadetClass = classLoader.loadClass("core.JobExecuter");
            abstractJobExecuter = (AbstractJobExecuter) loadetClass.newInstance();
        }
        catch (MalformedURLException e)
        {
            e.printStackTrace();
        }
        catch (ClassNotFoundException e)
        {
            e.printStackTrace();
        }
        catch (InstantiationException e)
        {
            e.printStackTrace();
        }
        catch (IllegalAccessException e)
        {
            e.printStackTrace();
        }
    }

    Ist das dass, was du unter dynamischen Nachladen verstehst?
     
    Mein kleiner webstart Projektplaner:
    http://178.77.101.236/ppws/
    Ideen, Verbesserungsvorschläge, Bugsmeldungen und allg. Kritik erwünscht und erbeten.

    Danke. :)

  10. #10
    Avatar von miffi
    miffi miffi ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Ravensburg (BW)
    Beiträge
    139
    Hallo Kai,

    hab den Teil der Exception-Beschreibung wohl überlesen, dass der Fehler zur Laufzeit eine andere Bedeutung hat. Wobei es eigentlich logisch ist, bei dem Zugriff auf die Member einer abstrakten Klasse hätte der Compiler ja schon gemeckert.

    Hab alle Module gecleant und neu kompiliert, jetzt geht alles.
    Danke

    Gruß
    miffi
     
    "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
    Douglas Adams

  11. #11
    Avatar von Jellysheep
    Jellysheep Jellysheep ist offline Mitglied Platin
    Registriert seit
    Jan 2009
    Ort
    Arbeitsspeicher
    Beiträge
    689
    Ich habe etwas ähnliches ausprobiert und mit diesem Code eine Klasse geladen:
    Code java:
    1
    2
    3
    4
    
    URL url = jarFile.toURI().toURL();
    URLClassLoader classLoader = new URLClassLoader(new URL[]{url});
    Class<?> loadedClass = classLoader.loadClass(className);
    Plugin plugin = (Plugin)loadedClass.newInstance();
    Danach lässt sich das jarFile aber nicht mehr löschen. Wie kann ich die Schreibrechte darauf wieder erlauben?
    (Wenn ich die letzten beiden Zeilen weglasse, funktioniert das Löschen)
     
    Grüße, Jellysheep

    Jeder Helfer freut sich über eine Bewertung oder ein Danke.

    Freiheit für die Gummibärchen, nieder mit den Tüten!
    Link :D

  12. #12
    Kai008 Kai008 ist offline Mitglied Brillant
    Registriert seit
    May 2008
    Ort
    Brunn/Geb. (Niederösterreich)
    Beiträge
    944
    Blog-Einträge
    1
    Versuche es mal mit deleteOnExit(). Vorsicht, Memleak.
    Jellysheep bedankt sich. 
    Mein kleiner webstart Projektplaner:
    http://178.77.101.236/ppws/
    Ideen, Verbesserungsvorschläge, Bugsmeldungen und allg. Kritik erwünscht und erbeten.

    Danke. :)

  13. #13
    Avatar von miffi
    miffi miffi ist offline Mitglied Gold
    Registriert seit
    Jul 2009
    Ort
    Ravensburg (BW)
    Beiträge
    139
    Das Problem wird wohl sein, dass die Klasse aus dem Jar wegen des loadClass Aufrufs noch geladen ist.
    Warum willst du denn das JAR zur Laufzeit löschen? Ich weiß nicht, ob es eine Möglichkeit zum "Entladen" einer Klasse gibt. Wenn du den Default-ClassLoader genommen hast, müsste dieser IMHO doch bis zur Terminierung der JVM erhalten bleiben. D.h., du müsstest die geladenen Klassen wieder rauswerfen, sonst geht das vermutlich nicht...
    Würde mich auf jeden Fall auch interessieren, wenn du eine Lösung gefunden hast.

    Gruß
    miffi
    Jellysheep bedankt sich. 
    "A common mistake that people make when trying to design something completely foolproof is to underestimate the ingenuity of complete fools."
    Douglas Adams

  14. #14
    Avatar von Jellysheep
    Jellysheep Jellysheep ist offline Mitglied Platin
    Registriert seit
    Jan 2009
    Ort
    Arbeitsspeicher
    Beiträge
    689
    Danke für die schnellen Antworten.
    Anscheinend kann man einmal geladene Klassen nie mehr entladen.
    An deleteOnExit() hab ich auch schon gedacht, es funktioniert aber widererwartend nicht.

    Ich wollte das jar-File nur temporär aus einer eigenen Plugin-Datei entpacken und so schnell wie möglich wieder löschen.
    Ich speichere jetzt aber alle Plugins in einem extra Ordner, in dem sie bleiben können.
     
    Grüße, Jellysheep

    Jeder Helfer freut sich über eine Bewertung oder ein Danke.

    Freiheit für die Gummibärchen, nieder mit den Tüten!
    Link :D

  15. #15
    Kai008 Kai008 ist offline Mitglied Brillant
    Registriert seit
    May 2008
    Ort
    Brunn/Geb. (Niederösterreich)
    Beiträge
    944
    Blog-Einträge
    1
    Würde ich sowieso so machen, nächstes mal musst du nur Filesize und/oder Checksum vergleichen.
     
    Mein kleiner webstart Projektplaner:
    http://178.77.101.236/ppws/
    Ideen, Verbesserungsvorschläge, Bugsmeldungen und allg. Kritik erwünscht und erbeten.

    Danke. :)

Ähnliche Themen

  1. Konzept Newssammler
    Von topf im Forum PHP
    Antworten: 1
    Letzter Beitrag: 03.03.09, 22:24
  2. Vorlage für ein DV Konzept
    Von hauke1981 im Forum Smalltalk
    Antworten: 0
    Letzter Beitrag: 11.04.07, 10:31
  3. Konzept
    Von webhoster im Forum PHP
    Antworten: 1
    Letzter Beitrag: 10.07.04, 02:59
  4. Konzept W-LAN
    Von blonde im Forum Netzwerke
    Antworten: 0
    Letzter Beitrag: 06.03.04, 14:24
  5. Programmier Konzept
    Von webhoster im Forum PHP
    Antworten: 5
    Letzter Beitrag: 09.09.02, 15:12