begin process at 2010 03 21 01:27:46
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Api

 > PLUG-IN ET CHARGEMENT DYNAMIQUE DE MODULES, INTROSPECTION

PLUG-IN ET CHARGEMENT DYNAMIQUE DE MODULES, INTROSPECTION


 Information sur la source

Note :
Aucune note
Catégorie :Api Classé sous :plugin, module dynamique, reflexion, instrospection Niveau :Initié Date de création :20/02/2008 Date de mise à jour :20/02/2008 17:43:32 Vu / téléchargé :5 075 / 136

Auteur : HeeroYuhi

Ecrire un message privé
Commentaire sur cette source (5)
Ajouter un commentaire et/ou une note

 Description

Package qui gère le chargement dynamique de modules.
Ces modules se présente sous forme d'un .class.
Les classes sont stockées dans un vecteur, soit sous forme de d'objet (de type java.lang.Class), soit d'instances (type java.lang.Object).
Les classes chargées doivent être utilisables directement, avec seulement un cast. En effet, le Loader ne charge pas les méthodes de la classe, peut-être dans une future évolution.

J'ai mis les deux fichiers du package :
- DynamiqueLoader, qui gère le chargement
- PlugInStorage, qui stocke les classes et permet la recherche par nom.

Source

  • /*** Fichier DynamicLoader.java ***/
  • package mylib.dynamicloader;
  • import java.util.*;
  • import java.io.*;
  • //import java.lang.* //Systematically loaded by java.
  • /**
  • * <p>Class to load dynamic plug-ins using introspection and reflexion.
  • * Plug-ins are java class files (compiled files) and they must be stored in the
  • * same directory. After loading, classes are associated to an unique name and
  • * stored onto an array. You can either store the class definition or objects
  • * created from a loaded class. If you use instance option (that build object
  • * from the class), your class must have a default constructor
  • * (with no parameters).</p>
  • *
  • * <p>Initially created for the software Patty, where it's used to
  • * add aircraft or entity specifications to the program.</p>
  • *
  • * @author VALENTIN Joachim
  • */
  • public class DynamicLoader {
  • String PlugInDirectory; //Source directory for plug-ins.
  • String PackagePath; //Package path of the plug-ins. Must be the same that defined with the 'package' command into the plug-ins class.
  • Vector ClassArray; //Class or instance storage.
  • boolean OptionInstance; //If true, the loader create and store an instance of the class, rather than the class itself.
  • public DynamicLoader() {
  • PlugInDirectory = "";
  • PackagePath = "";
  • ClassArray = new Vector();
  • OptionInstance = false;
  • }
  • /**Constructor that initialize the plug-in directory and the loading option.*/
  • public DynamicLoader(String dir, String pack, boolean option) {
  • PlugInDirectory = new String(dir);
  • SetPackagePath(pack);
  • ClassArray = new Vector();
  • OptionInstance = option;
  • }
  • /**Defines the plug-in directory.*/
  • public void SetDirectory(String dir) {
  • PlugInDirectory = new String(dir);
  • }
  • /**Returns the plug-in directory.*/
  • public String GetDirectory() {
  • return PlugInDirectory;
  • }
  • /**Defines the package path. Test if it ends with a '.'.*/
  • public void SetPackagePath(String pack) {
  • PackagePath = pack;
  • if (!(pack.endsWith("."))) {
  • PackagePath += ".";
  • }
  • }
  • /**Returns the package path.*/
  • public String GetPackagePath() {
  • return PackagePath;
  • }
  • /**Defines class instance storage option.*/
  • public void SetInstanceOption() {
  • OptionInstance = true;
  • }
  • /**Defines class storage option.*/
  • public void UnsetInstanceOption() {
  • OptionInstance = false;
  • }
  • /**Returns storage option (class or instance).*/
  • public boolean GetInstanceOption() {
  • return OptionInstance;
  • }
  • /**Defines the plug-in directory and load them.*/
  • public int LoadPlugIn(String dir) {
  • PlugInDirectory = new String(dir);
  • return LoadPlugIn();
  • }
  • /**Load plug-ins from the previously defined directory.*/
  • public int LoadPlugIn() {
  • File directory;
  • FilenameFilter classFilter;
  • String[] classFiles;
  • Class tmp_class;
  • PlugInStorage stored;
  • //Create the file system object for the plug in directory.
  • directory = new File(PlugInDirectory);
  • //Create a filter to get only class files from the directory.
  • classFilter = new FilenameFilter() {
  • public boolean accept(File dir, String name) {
  • return name.endsWith(".class");
  • }
  • };
  • //Get the list of all filtered filename of the directory.
  • //In fact, all *.class files.
  • if ((classFiles = directory.list(classFilter)) == null) {
  • System.err.println("Nothing to load.");
  • return -1;
  • }
  • //Get all classes associated with *.class files and put them into the array.
  • for (int index = 0; index < classFiles.length; ++index) {
  • stored = new PlugInStorage();
  • try {
  • //Remove the extension of filename.
  • classFiles[index] = classFiles[index].substring(0, classFiles[index].indexOf(".class"));
  • //Load the class from the filename. Send ClassNotFoundException or NoClassDefFoundError on error.
  • tmp_class = Class.forName(PackagePath + classFiles[index]);
  • if (OptionInstance) {
  • //Create a new instance of the class. Send Exception on error.
  • stored.Set(tmp_class.newInstance());
  • } else {
  • stored.Set(tmp_class);
  • }
  • //Add the object to the array.
  • ClassArray.add(stored);
  • } catch (ClassNotFoundException e) {
  • System.err.println("Unable to load class \"" + classFiles[index] + "\". " + e.getMessage());
  • return -1;
  • } catch (NoClassDefFoundError e) {
  • System.err.println("Unable to find the class into the package : " + PackagePath);
  • return -1;
  • } catch (Exception e) {
  • System.err.println("Unable to create instance of the class \"" + classFiles[index] + "\"");
  • return -1;
  • }
  • }
  • //Lexicographically sort the array of plug-ins.
  • SortPlugIns();
  • return 0;
  • }
  • /**Returns the instance of the class named 'name'.*/
  • public Object GetInstance(String name) throws ArrayIndexOutOfBoundsException {
  • if (OptionInstance) {
  • return ((PlugInStorage) ClassArray.get(GetIdFromName(name))).PlugInObject;
  • } else {
  • return null;
  • }
  • }
  • /**Returns the class that is named 'name'.*/
  • public Object GetClass(String name) throws ArrayIndexOutOfBoundsException {
  • if (!OptionInstance) {
  • return ((Class) ((PlugInStorage) ClassArray.get(GetIdFromName(name))).PlugInObject);
  • } else {
  • return null;
  • }
  • }
  • /**Return the position (index) into the array from the name.*/
  • public int GetIdFromName(String name) {
  • int lower = 0;
  • int upper = 0;
  • int index = 0;
  • int test = 0;
  • upper = ClassArray.size() - 1;
  • if (upper < 0) { //No elements into the array.
  • return -1;
  • }
  • //Last element of the will never be tested, then we test it first.
  • if (((PlugInStorage) ClassArray.lastElement()).Compare(name) == 0) {
  • return upper;
  • }
  • /**Loop for element seeking. Our array is lexicographically sorted by name (PlugInStorage.ObjectName).
  • * See PlugInStorage.Compare() to know its return values.
  • * We compare the middle element of the range with the name to reach.
  • * Then we know in which part of the range the name is.
  • * And we loop unless we find the element or the range is equal to 1.
  • */
  • do {
  • index = (lower + upper) / 2; //Element to test.
  • test = ((PlugInStorage) ClassArray.get(index)).Compare(name);
  • if (((upper - lower) <= 1) && (test != 0)) {
  • return -1; //name doesn't match anything.
  • }
  • if (test < 0) { //name is in the upper part of the range.
  • lower = index;
  • } else if (test < 0) { //name is in the upper part of the range.
  • upper = index;
  • }
  • } while (test != 0);
  • return index;
  • }
  • /**Sort plug-ins array by name.*/
  • void SortPlugIns() {
  • int index = 0; //Current element to sort.
  • int index2 = 0; //Current element to test with.
  • for (index = 1; index < ClassArray.size(); ++index) {
  • index2 = index - 1;
  • //Compare the current element (index) to the one at index2.
  • //While the first one lexicographically precede the second one, it continues.
  • while (((PlugInStorage) ClassArray.get(index)).Compare(((PlugInStorage) ClassArray.get(index2)).GetName()) < 0) {
  • if (index2 == 0) { //Stop the loop if we compare with the first element.
  • break;
  • }
  • index2 = index2 - 1;
  • }
  • //We remove it from its previous position...
  • //And we use the returned object to put it to the new position.
  • //(i.e. : Vector.remove(index) return the deleted object.)
  • ClassArray.add(index2, ClassArray.remove(index));
  • }
  • }
  • }
/*** Fichier DynamicLoader.java ***/

package mylib.dynamicloader;

import java.util.*;
import java.io.*;
//import java.lang.*    //Systematically loaded by java.
/**
 * <p>Class to load dynamic plug-ins using introspection and reflexion.
 * Plug-ins are java class files (compiled files) and they must be stored in the
 * same directory. After loading, classes are associated to an unique name and 
 * stored onto an array. You can either store the class definition or objects
 * created from a loaded class. If you use instance option (that build object
 * from the class), your class must have a default constructor
 * (with no parameters).</p>
 * 
 * <p>Initially created for the software Patty, where it's used to
 * add aircraft or entity specifications to the program.</p>
 * 
 * @author VALENTIN Joachim
 */
public class DynamicLoader {

    String PlugInDirectory;     //Source directory for plug-ins.
    String PackagePath;         //Package path of the plug-ins. Must be the same that defined with the 'package' command into the plug-ins class.
    Vector ClassArray;          //Class or instance storage.
    boolean OptionInstance;     //If true, the loader create and store an instance of the class, rather than the class itself.

    public DynamicLoader() {
        PlugInDirectory = "";
        PackagePath = "";
        ClassArray = new Vector();
        OptionInstance = false;
    }

    /**Constructor that initialize the plug-in directory and the loading option.*/
    public DynamicLoader(String dir, String pack, boolean option) {
        PlugInDirectory = new String(dir);
        SetPackagePath(pack);
        ClassArray = new Vector();
        OptionInstance = option;
    }

    /**Defines the plug-in directory.*/
    public void SetDirectory(String dir) {
        PlugInDirectory = new String(dir);
    }

    /**Returns the plug-in directory.*/
    public String GetDirectory() {
        return PlugInDirectory;
    }

    /**Defines the package path. Test if it ends with a '.'.*/
    public void SetPackagePath(String pack) {
        PackagePath = pack;
        if (!(pack.endsWith("."))) {
            PackagePath += ".";
        }
    }

    /**Returns the package path.*/
    public String GetPackagePath() {
        return PackagePath;
    }

    /**Defines class instance storage option.*/
    public void SetInstanceOption() {
        OptionInstance = true;
    }

    /**Defines class storage option.*/
    public void UnsetInstanceOption() {
        OptionInstance = false;
    }

    /**Returns storage option (class or instance).*/
    public boolean GetInstanceOption() {
        return OptionInstance;
    }

    /**Defines the plug-in directory and load them.*/
    public int LoadPlugIn(String dir) {
        PlugInDirectory = new String(dir);
        return LoadPlugIn();
    }

    /**Load plug-ins from the previously defined directory.*/
    public int LoadPlugIn() {
        File directory;
        FilenameFilter classFilter;
        String[] classFiles;
        Class tmp_class;
        PlugInStorage stored;

        //Create the file system object for the plug in directory.
        directory = new File(PlugInDirectory);

        //Create a filter to get only class files from the directory.
        classFilter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".class");
            }
        };

        //Get the list of all filtered filename of the directory.
        //In fact, all *.class files.
        if ((classFiles = directory.list(classFilter)) == null) {
            System.err.println("Nothing to load.");
            return -1;
        }

        //Get all classes associated with *.class files and put them into the array.
        for (int index = 0; index < classFiles.length; ++index) {
            stored = new PlugInStorage();
            try {
                //Remove the extension of filename.
                classFiles[index] = classFiles[index].substring(0, classFiles[index].indexOf(".class"));

                //Load the class from the filename. Send ClassNotFoundException or NoClassDefFoundError on error.
                tmp_class = Class.forName(PackagePath + classFiles[index]);

                if (OptionInstance) {
                    //Create a new instance of the class. Send Exception on error.
                    stored.Set(tmp_class.newInstance());
                } else {
                    stored.Set(tmp_class);
                }

                //Add the object to the array.
                ClassArray.add(stored);

            } catch (ClassNotFoundException e) {
                System.err.println("Unable to load class \"" + classFiles[index] + "\". " + e.getMessage());
                return -1;
            } catch (NoClassDefFoundError e) {
                System.err.println("Unable to find the class into the package : " + PackagePath);
                return -1;
            } catch (Exception e) {
                System.err.println("Unable to create instance of the class \"" + classFiles[index] + "\"");
                return -1;
            }
        }

        //Lexicographically sort the array of plug-ins.
        SortPlugIns();
        
        return 0;
    }

    /**Returns the instance of the class named 'name'.*/
    public Object GetInstance(String name) throws ArrayIndexOutOfBoundsException {
        if (OptionInstance) {
            return ((PlugInStorage) ClassArray.get(GetIdFromName(name))).PlugInObject;
        } else {
            return null;
        }
    }

    /**Returns the class that is named 'name'.*/
    public Object GetClass(String name) throws ArrayIndexOutOfBoundsException {
        if (!OptionInstance) {
            return ((Class) ((PlugInStorage) ClassArray.get(GetIdFromName(name))).PlugInObject);
        } else {
            return null;
        }
    }

    /**Return the position (index) into the array from the name.*/
    public int GetIdFromName(String name) {
        int lower = 0;
        int upper = 0;
        int index = 0;
        int test = 0;

        upper = ClassArray.size() - 1;

        if (upper < 0) {     //No elements into the array.
            return -1;
        }

        //Last element of the will never be tested, then we test it first.
        if (((PlugInStorage) ClassArray.lastElement()).Compare(name) == 0) {
            return upper;
        }

        /**Loop for element seeking. Our array is lexicographically sorted by name (PlugInStorage.ObjectName).
         * See PlugInStorage.Compare() to know its return values.
         * We compare the middle element of the range with the name to reach.
         * Then we know in which part of the range the name is.
         * And we loop unless we find the element or the range is equal to 1.
         */
        do {
            index = (lower + upper) / 2;        //Element to test.
            test = ((PlugInStorage) ClassArray.get(index)).Compare(name);

            if (((upper - lower) <= 1) && (test != 0)) {
                return -1;              //name doesn't match anything.
            }

            if (test < 0) {           //name is in the upper part of the range.
                lower = index;
            } else if (test < 0) {     //name is in the upper part of the range.
                upper = index;
            }

        } while (test != 0);

        return index;
    }

    /**Sort plug-ins array by name.*/
    void SortPlugIns() {
        int index = 0;      //Current element to sort.
        int index2 = 0;     //Current element to test with.

        for (index = 1; index < ClassArray.size(); ++index) {
            index2 = index - 1;

            //Compare the current element (index) to the one at index2.
            //While the first one lexicographically precede the second one, it continues.
            while (((PlugInStorage) ClassArray.get(index)).Compare(((PlugInStorage) ClassArray.get(index2)).GetName()) < 0) {
                if (index2 == 0) {  //Stop the loop if we compare with the first element.
                    break;
                }
                index2 = index2 - 1;
            }

            //We remove it from its previous position...
            //And we use the returned object to put it to the new position.
            //(i.e. : Vector.remove(index) return the deleted object.)
            ClassArray.add(index2, ClassArray.remove(index));
        }
    }
}

 Conclusion

J'ai essayé de rendre ces classes le plus robuste possible, mais pour les personnes qui se le sentent, n'hésitez pas à m'informer des bugs afin de continuer à les améliorer.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

20 février 2008 12:07:52 :
Petites corrections post-enregistrement.
20 février 2008 17:42:01 :
Modification dans le code : - Ajout d'une fonction pour lister les classes chargées. - Création d'un petit programme pour tester les classes.
20 février 2008 17:43:32 :
Modifications dans le code : - Ajout d'une fonction dans dynamiqueloader pour lister les classes chargées. - Création d'un programme de test. Explications supplémentaire dans le README.txt

 Sources de la même categorie

Source avec Zip Source avec une capture LETMESEE : CAPTURE D'ÉCRAN À INTERVALLE RÉGULIER : UTILISATI... par pyo656
ENVOI D'UNE ARBORESSENCE EN JAVA VERS SERVEUR FTP par moumou95
ENREGISTRER L'ARBORESCENCE D'UN JTREE DANS UN XML AVEC JDOM par coltman
Source avec Zip WIZARD JAVA API par aissam36
JCONFIGURATIONMANAGER - GESTION DES CONFIGURATIONS par Francks11

 Sources en rapport avec celle ci

Source avec Zip MOTEUR DE PLUGIN par sheorogath
Source avec Zip APPELER DES APIS SANS PROGRAMMATION JNI par DeadlyPredator
Source avec Zip CHARGEUR DE CLASSE par titeuf921

Commentaires et avis

Commentaire de Twinuts le 20/02/2008 13:59:02 administrateur CS

Salut,

ne voyant rien d'assez pechu, je repasse le code en débutant

ptites remarques :
1 - Tu aurais quand même pu repsecter un minimum les règles de nommage de sun et ne pas mettre des majuscules à toutes tes méthodes et noms de variables....
2 - Tu aurais pu mettre une restriction sur la portée de tes variables globales...
3 - Tu aurais pu faire en sorte que ton code charge un plugin de type générique, sans imposer une classe précise afin de déléguer la couche métier à un moteur de plugin...

Commentaire de HeeroYuhi le 20/02/2008 17:51:53

Bonjour,
Pour les règles de nommage, je m'excuse mais je commence juste le java et je viens du monde C++.

Tu pourrais préciser le coup de la restriction de portée?

De même pour le type générique?
Il me semble que je n'impose pas de type particulier. Il faut juste que les classes plug-in hérite d'une mère définie en interne dans le programme afin de pouvoir accéder aux méthodes.
J'aurais pu mettre en place un chargement dynamique des méthodes, mais cela ne me sert à rien dans mon projet.

Commentaire de Twinuts le 20/02/2008 18:22:50 administrateur CS

Salut,

"Tu pourrais préciser le coup de la restriction de portée?"
> Je parle du qualifieur 'private' sur tes variables globales afin d'éviter les trous de secu

Pour le cas du chargement de plugin bah c'est assez simple:
Tu sépares le chargement du byte code de ta couche métier (chargement du plugin) en mettant au point une sorte de jarloader (chargement des classes d'un jar en fonction d'un entry point du fichier manifest) rien de plus. En gros cette classe permet simplement de charger le byte code des classes java se trouvant dans un jar et de pouvoir créer des instances d'objet, des invoke sur les méthodes de celui-ci, etc...
Ensuite tu peux y ajouter ta couche métier en incluant ton template de plugin... et ainsi éviter une  dépendance entre le loader et la couche métier, afin de rendre le loader le plus générique possible.

Commentaire de HeeroYuhi le 21/02/2008 08:48:24

Salut,

Je pensais que java faisait comme C++ pour les attributs de classes, qu'il les rendait automatiquement private.

Pour le second point, je ne vois pas en quoi mon loader est dépendant de ma couche métier. Peut-être parles-tu de la classe PlugInStorage. Mais cette classe ne stocke aucune info spécifique à mes plugins, elle permet juste de faciliter le stockage, le tri et la recherche d'élément (cf PlugInStorage.java, dans le zip).
Je pense intégrer le chargement de classe à partir d'un .jar, mais pour mon projet (qui nécessitera des ajouts réguliers de plug-in) il est plus aisé de charger des .class indépendant. Je ne sais pas si je me suis fais comprendre, mais en gros, si on prend l'exemple du PlugedPlane, il faudra que j'ajoute régulièrement de nouveaux avions.

Merci pour tes remarques.

Commentaire de Twinuts le 21/02/2008 09:57:13 administrateur CS

Salut,

afin de mieux me faire comprendre, regarde sur cette source (1) et interrese toi à la classe JarLoader (2)

(1) -> http://www.javafr.com/codes/MOTEUR-PLUGIN_44098.aspx
(2) -> http://files.codes-sources.com/fichier.aspx?id=44098&f=Moteur+de+plugin\Admin+PlugIn+version\src\com\daedric\lang\jar\JarLoader.java

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

plugin java3D [ par fredocom ] bonjour, j'ai besoin de quelques infos sur l'API java3D. Pour pouvoir visualiser une applet java3D sur le web, je sais que l'utilisateur doit disposer Plugin JAVA3D [ par lulu31 ] J'ai une applet qui utilise une visu2D et une visu3D de la trajectoire d'un satellite. J'aimerais qu'au demarrage de cette applet, la detection du plu Instrospection Visual Basic [ par ledouxni ] est il possible de connaitre tous les objets, types, classes, ... contenus dans une référence visual basic ( comme l'instrospection Java ) ?merci pour Pb exécution servlet eclispe/tomcat.plugin sysdéo [ par pjfly ] J'utilise Tomcat 4.18, Eclipse 2.1.2 et le plugin 2.2 sous windows XP. J'ai le message : HTTP 404 la ressource demandée n'est pas disponible. Le sourc plugin [ par fredmorvant29 ] bonjour,je viens de copier des plugin ds mon répertoire plugin d'Eclipse, mais ce dernier ne les acceptent pas car il lui manquerait "org.eclipse.core Plusieurs Plugin JAVA VM avec Internet Explorer [ par fredpenn ] Bonjour,Pour faire fonctionner deux applets differentes dans IE6 SP1, j'ai besoin de deux JRE differentes 1.3.1 et 1.4.+Mlaheureusement, la premiere a SWT [ par julio13 ] Salut à tous,voila ma question :je suis en train de développer un plugin eclipse. Au départ, le plugin est initialisé avec un fichier .xml pour la con vue sous plugin eclipse [ par julio13 ] salut a tous,voila, je développe en ce moment un plugin eclipse. Je crée des vues que j'insère dedans... Jusque là rien de bien méchant.Je veux créer EclipseUML [ par EducJava ] Salut, Je cherche un expert d'Eclipse...J'ai récemment installé Eclipse 3.0 et j'aimerais maintenant faire du UML avec Eclipse. J'ai cherché et j'ai t Eclipse plugin SDE [ par EducJava ] Salut,Je cherche un expert dans l'installation du plugin pour Eclipse le SDE. J'ai executé le plugin et comme mon ordi passait son temps à geler je l'


Nos sponsors


Sondage...

CalendriCode

Mars 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728
293031    

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 0,827 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales