OVH Cloud OVH Cloud

Tester la présence d'un package

9 réponses
Avatar
yvon.thoravalNO-SPAM
Dans mon appli j'ai des dossiers contenants des données (dans un jar) :
yt.macave.datas.au
---------------.dz
etc...

j'aurai par ailleurs une liste de tous les cas possibles, MAIS je
souhaite pouvoir ajouter de nouveaux dossiers au fur et à mesure et
faire en sorte que mon appli détecte automatiquement si, par exemple
"yt.macave.datas.au" (les données pour l'Australie) est présent ou pas.

c'est possible ? Avec l'introspection ?

(après tout eclipse sait bien si un package est dans le path ou pas...)

--
yt

9 réponses

Avatar
Black Myst
Yvon Thoraval wrote:
Dans mon appli j'ai des dossiers contenants des données (dans un jar) :
yt.macave.datas.au
---------------.dz
etc...

j'aurai par ailleurs une liste de tous les cas possibles, MAIS je
souhaite pouvoir ajouter de nouveaux dossiers au fur et à mesure et
faire en sorte que mon appli détecte automatiquement si, par exemple
"yt.macave.datas.au" (les données pour l'Australie) est présent ou pas.

c'est possible ? Avec l'introspection ?

(après tout eclipse sait bien si un package est dans le path ou pas...)



Non, il est impossible de demander au classLoader la liste des classe
disponible, encore moins la liste des packages.

Le "package" n'a d'utilité que pour organiser les classes et pour gérer
les droits... Il ne contient aucune information....

Que contienne les répertoires de ton Jar, cherche-tu un fichier ou une
classe ?

@+
Clément

Avatar
Thibal
Black Myst wrote:

Yvon Thoraval wrote:

Dans mon appli j'ai des dossiers contenants des données (dans un jar) :
yt.macave.datas.au
---------------.dz
etc...

j'aurai par ailleurs une liste de tous les cas possibles, MAIS je
souhaite pouvoir ajouter de nouveaux dossiers au fur et à mesure et
faire en sorte que mon appli détecte automatiquement si, par exemple
"yt.macave.datas.au" (les données pour l'Australie) est présent ou pas.

c'est possible ? Avec l'introspection ?

(après tout eclipse sait bien si un package est dans le path ou pas...)



Non, il est impossible de demander au classLoader la liste des classe
disponible, encore moins la liste des packages.

Le "package" n'a d'utilité que pour organiser les classes et pour gérer
les droits... Il ne contient aucune information....

Que contienne les répertoires de ton Jar, cherche-tu un fichier ou une
classe ?

@+
Clément


En effet c'est pas gagné comme ça, essaye plutôt de le faire "à
l'ancienne" avec les méthodes de la classe File.


Avatar
yvon.thoravalNO-SPAM
Black Myst <Black_point_myst_chez_free_fr> wrote:


Que contienne les répertoires de ton Jar, cherche-tu un fichier ou une
classe ?


des classes, c'est mon gestionnaire d'appellations (vins) qui est
organisé ainsi :

yt.macave.datas.au le package correspondant à L'australie

supposons qu'il ne soit pas dans le jar pour diverses raisons, mais que
le package :

yt.macave.datas.fr y soit

par construction j'ai qqpart la liste des pays viticoles, ds mon exemple
j'aurais : "Australie", "France"

dans chaque package j'ai une class portant (à peu près juste pour
simplifier) le nom du pays, cette class a aussi une methode (au moins)
qui est add(), toujours la même fonction qqsoit le pays.

ce que je veux donc faire c'est "introspecter" le jar Appellations.jar
pour savoir quels pays y sont inclus.

ce que je fais, pour l'instant :

Map worldApps = new TreeMap();

Area world = new Area("Terre", "Racine", "WORLD", null);
worldApps.put(world, empty);

[...]
Australie.add(worldApps, world);
[...]
France.add(worldApps, world);

ce que je voudrais pouvoir faire (donné schématiquement) :

Map worldApps = new TreeMap();

Area world = new Area("Terre", "Racine", "WORLD", null);
worldApps.put(world, empty);

String[] allPossibleCountries = {"Australie", ..., "France"};
Class[] allPossibleCountriesClazz = { Australie.class, ...,
France.class};

for (allPossibleCountries) {
if(thisCountryExistsInPackage()) {
Class clazz = allPossibleCountriesClazz[i];
clazz.add(worldApps, world);
}
}

Le seul truc que je n'avais pas trouvé hier soir, c'est le moyen
d'implémenter thisCountryExistsInPackage() et je pense avoir trouvé,
grâce à un article de Shawn Silverman ( Java Tip 127: See JAR run) dans
JavaWorld
(<http://www.javaworld.com/javaworld/javatips/jw-javatip127.html>)
qui répond, indirectement, à ma question.

J'ai fait un petit test sur un jar contenant mon app :

JarInputStream jarIn = new JarInputStream(new
FileInputStream("le_fichier_a_lire"));
JarEntry entry;

while ((entry = jarIn.getNextJarEntry()) != null) {
System.out.println("entry.getName() : " + entry.getName());
}

qui me donne la même chose que "jar tf le_fichier_a_lire" mais cette
fois-ci, non pas à la console mais dans un prog java... :
~/work/Java/Jar/ReadJarContents> java ReadJarContents monapp.jar
[...]
entry.getName() : yt/macave/bottles/datas/BottlesAll.class
entry.getName() : yt/macave/bottles/datas/FileInit.class
entry.getName() : yt/macave/bottles/MasterOfWine.class
entry.getName() : yt/macave/bottles/Person.class
entry.getName() : yt/macave/bottles/PhoneLine.class
entry.getName() : yt/macave/bottles/PostalAddress.class
entry.getName() : yt/macave/bottles/Price.class
entry.getName() : yt/macave/bottles/Producer.class
entry.getName() : yt/macave/bottles/SimpleDate.class
[...]


par exemple, c'est donc faisable ««« yapuka »»» ;-)

ça me permettra des màj automatiques sans souci...
... enfin ;-) c'est ce que j'espère...
--
yt

Avatar
Black Myst
Yvon Thoraval wrote:
Black Myst <Black_point_myst_chez_free_fr> wrote:


Que contienne les répertoires de ton Jar, cherche-tu un fichier ou une
classe ?



des classes, c'est mon gestionnaire d'appellations (vins) qui est
organisé ainsi :

yt.macave.datas.au le package correspondant à L'australie

supposons qu'il ne soit pas dans le jar pour diverses raisons, mais que
le package :

yt.macave.datas.fr y soit

par construction j'ai qqpart la liste des pays viticoles, ds mon exemple
j'aurais : "Australie", "France"

dans chaque package j'ai une class portant (à peu près juste pour
simplifier) le nom du pays, cette class a aussi une methode (au moins)
qui est add(), toujours la même fonction qqsoit le pays.

ce que je veux donc faire c'est "introspecter" le jar Appellations.jar
pour savoir quels pays y sont inclus.

ce que je fais, pour l'instant :

Map worldApps = new TreeMap();

Area world = new Area("Terre", "Racine", "WORLD", null);
worldApps.put(world, empty);

[...]
Australie.add(worldApps, world);
[...]
France.add(worldApps, world);

ce que je voudrais pouvoir faire (donné schématiquement) :

Map worldApps = new TreeMap();

Area world = new Area("Terre", "Racine", "WORLD", null);
worldApps.put(world, empty);

String[] allPossibleCountries = {"Australie", ..., "France"};
Class[] allPossibleCountriesClazz = { Australie.class, ...,
France.class};

for (allPossibleCountries) {
if(thisCountryExistsInPackage()) {
Class clazz = allPossibleCountriesClazz[i];
clazz.add(worldApps, world);
}
}

Le seul truc que je n'avais pas trouvé hier soir, c'est le moyen
d'implémenter thisCountryExistsInPackage() et je pense avoir trouvé,
grâce à un article de Shawn Silverman ( Java Tip 127: See JAR run) dans
JavaWorld
(<http://www.javaworld.com/javaworld/javatips/jw-javatip127.html>)
qui répond, indirectement, à ma question.

J'ai fait un petit test sur un jar contenant mon app :

JarInputStream jarIn = new JarInputStream(new
FileInputStream("le_fichier_a_lire"));
JarEntry entry;

while ((entry = jarIn.getNextJarEntry()) != null) {
System.out.println("entry.getName() : " + entry.getName());
}

qui me donne la même chose que "jar tf le_fichier_a_lire" mais cette
fois-ci, non pas à la console mais dans un prog java... :
~/work/Java/Jar/ReadJarContents> java ReadJarContents monapp.jar
[...]
entry.getName() : yt/macave/bottles/datas/BottlesAll.class
entry.getName() : yt/macave/bottles/datas/FileInit.class
entry.getName() : yt/macave/bottles/MasterOfWine.class
entry.getName() : yt/macave/bottles/Person.class
entry.getName() : yt/macave/bottles/PhoneLine.class
entry.getName() : yt/macave/bottles/PostalAddress.class
entry.getName() : yt/macave/bottles/Price.class
entry.getName() : yt/macave/bottles/Producer.class
entry.getName() : yt/macave/bottles/SimpleDate.class
[...]


par exemple, c'est donc faisable ««« yapuka »»» ;-)

ça me permettra des màj automatiques sans souci...
... enfin ;-) c'est ce que j'espère...


Non, c'est clairement pas la bonne démarche, si tu y passe beaucoup de
temps, tu réussira peut-être à le faire marcher sur ton poste de dev,
mais la solution que tu décrit est le meilleur moyen de se tiré dans le
pied à la première install...

Résumons :
- Tu as un certain nombre de classe que tu doit retrouvé dynamiquement :
- yt.macave.datas.fr.France
- yt.macave.datas.au.Australie
- Toutes ses classes hérite d'une même classe ou implémente une
interface définissant la méthode 'add'.
- Tu connais la liste des pays mais pas leur nom de paquage -> ca nous
sert à rien pour les retrouver !

A faire :
- Un fichier txt simple, contenant 1 nom complet (paquage+classe) par
ligne, que tu place à un endroit unique... yt/macave/datas/ListPays.txt
- Tu peux demander au ClassLoader se fichier, car tu connais son nom.
- Ensuite tu lis le fichier et tu utilise la reflexivité pour charger,
instancier et exécuter 'add' sur toutes tes classes.

Cerise sur le gâteau :
Si tu veux ditribuer ton application sous forme de plusieur JAR, tu
créer un fichier yt/macave/datas/ListPays.txt pour chaque JAR, contenant
le nom des classes contenus dans le JAR.
Tu peux ensuite demandé au ClassLoader qui te donne accès à tous les
fichiers yt/macave/datas/ListPays.txt, tu peux donc les ouvrirs l'un
après l'autre pour découvrir les classes dans chacuns des JAR.

Le tout en utilisant le comportement 'normale' du ClassLoader... Ca
n'exclus pas tous les risques de déployment, mais ca limite quand même...



Sinon, pour en revenir à ton code, ca me semble super bizare une classe
yt.macave.datas.fr.France... Ca me laisse croire que tes données sont
hard-codé dans des classes java... pourquoi ne pas faire 1 ou plusieurs
fichiers de données en XML ???

@+
Black.Myst


Avatar
pasde.bcausse.spam
Yvon Thoraval wrote:

Black Myst <Black_point_myst_chez_free_fr> wrote:


Que contienne les répertoires de ton Jar, cherche-tu un fichier ou une
classe ?


des classes, c'est mon gestionnaire d'appellations (vins) qui est
organisé ainsi :

yt.macave.datas.au le package correspondant à L'australie

supposons qu'il ne soit pas dans le jar pour diverses raisons, mais que
le package :

yt.macave.datas.fr y soit

par construction j'ai qqpart la liste des pays viticoles, ds mon exemple
j'aurais : "Australie", "France"

dans chaque package j'ai une class portant (à peu près juste pour
simplifier) le nom du pays, cette class a aussi une methode (au moins)
qui est add(), toujours la même fonction qqsoit le pays.

ce que je veux donc faire c'est "introspecter" le jar Appellations.jar
pour savoir quels pays y sont inclus.

ce que je fais, pour l'instant :

Map worldApps = new TreeMap();

Area world = new Area("Terre", "Racine", "WORLD", null);
worldApps.put(world, empty);

[...]
Australie.add(worldApps, world);
[...]
France.add(worldApps, world);

ce que je voudrais pouvoir faire (donné schématiquement) :

Map worldApps = new TreeMap();

Area world = new Area("Terre", "Racine", "WORLD", null);
worldApps.put(world, empty);

String[] allPossibleCountries = {"Australie", ..., "France"};
Class[] allPossibleCountriesClazz = { Australie.class, ...,
France.class};

for (allPossibleCountries) {
if(thisCountryExistsInPackage()) {
Class clazz = allPossibleCountriesClazz[i];
clazz.add(worldApps, world);
}
}

Le seul truc que je n'avais pas trouvé hier soir, c'est le moyen
d'implémenter thisCountryExistsInPackage() et je pense avoir trouvé,
grâce à un article de Shawn Silverman ( Java Tip 127: See JAR run) dans
JavaWorld
(<http://www.javaworld.com/javaworld/javatips/jw-javatip127.html>)
qui répond, indirectement, à ma question.

J'ai fait un petit test sur un jar contenant mon app :

JarInputStream jarIn = new JarInputStream(new
FileInputStream("le_fichier_a_lire"));
JarEntry entry;

while ((entry = jarIn.getNextJarEntry()) != null) {
System.out.println("entry.getName() : " + entry.getName());
}

qui me donne la même chose que "jar tf le_fichier_a_lire" mais cette
fois-ci, non pas à la console mais dans un prog java... :
~/work/Java/Jar/ReadJarContents> java ReadJarContents monapp.jar
[...]
entry.getName() : yt/macave/bottles/datas/BottlesAll.class
entry.getName() : yt/macave/bottles/datas/FileInit.class
entry.getName() : yt/macave/bottles/MasterOfWine.class
entry.getName() : yt/macave/bottles/Person.class
entry.getName() : yt/macave/bottles/PhoneLine.class
entry.getName() : yt/macave/bottles/PostalAddress.class
entry.getName() : yt/macave/bottles/Price.class
entry.getName() : yt/macave/bottles/Producer.class
entry.getName() : yt/macave/bottles/SimpleDate.class
[...]


par exemple, c'est donc faisable ««« yapuka »»» ;-)

ça me permettra des màj automatiques sans souci...
... enfin ;-) c'est ce que j'espère...


je ne sais pas bien si je reponds a la question. Dans chaque classes une
methode static exist() et un try catch pour gerer l'exception


Avatar
Olivier Thomann
Personnellement je pense que ton problème se résoudrait très bien avec
une base de données plutôt que plein de classes.
Tous tes problèmes d'existence de classes seraient gérés par la base de
données.
Juste une idée comme ça.
--
Olivier
Avatar
yvon.thoravalNO-SPAM
Bruno Causse wrote:


je ne sais pas bien si je reponds a la question. Dans chaque classes une
methode static exist() et un try catch pour gerer l'exception


ouais, bien vu, ça revient à avoir des pays vides...
c'est ce que je fais en ce moment. merci.
--
yt

Avatar
yvon.thoravalNO-SPAM
Black Myst <Black_point_myst_chez_free_fr> wrote:

Non, c'est clairement pas la bonne démarche, si tu y passe beaucoup de
temps, tu réussira peut-être à le faire marcher sur ton poste de dev,
mais la solution que tu décrit est le meilleur moyen de se tiré dans le
pied à la première install...


Ouais, c'est exact, j'ai déja intuité ce pb potentiel, la hiérarchie de
mes dossiers n'est pas la même sous éclipse que déployé, en plus, sous
eclipse je n'ai pas le jar de mon appli, c'est dans le rep bin sous
forme de fichiers *.class...
Résumons :
- Tu as un certain nombre de classe que tu doit retrouvé dynamiquement :
- yt.macave.datas.fr.France
- yt.macave.datas.au.Australie
- Toutes ses classes hérite d'une même classe ou implémente une
interface définissant la méthode 'add'.
- Tu connais la liste des pays mais pas leur nom de paquage -> ca nous
sert à rien pour les retrouver !


Ah non, ce n'est pas exactement ce que j'ai prévu, je connais la liste
de tous les pays "potentiels" et la liste de tous les packages aussi,
mais seulement potentiellement, ce que je ne sais pas c'est là où j'en
serai à un moment donné (il faut pas mal de temps pour avoir les datas).

Disons que je veux pouvoir développer mon appli sans avoir à me
préoccuper de l'existence d'un pays ou non, s'il n'existe pas encore
(ie; je n'ai pas eu le temps de me renseigner sur les appellations d'un
pays donné) je ne détecte pas sa classe et donc je ne le charge pas.
A faire :
- Un fichier txt simple, contenant 1 nom complet (paquage+classe) par
ligne, que tu place à un endroit unique... yt/macave/datas/ListPays.txt
- Tu peux demander au ClassLoader se fichier, car tu connais son nom.
- Ensuite tu lis le fichier et tu utilise la reflexivité pour charger,
instancier et exécuter 'add' sur toutes tes classes.
oui, c'est vrai je peux générer ce fichier *.txt automatiquement au

build avec ant par ex.(je veux éviter mes étourderies ie. "registrer" un
pays qui n'existe pas encore ou en oublier un)
Cerise sur le gâteau :
Si tu veux ditribuer ton application sous forme de plusieur JAR, tu
créer un fichier yt/macave/datas/ListPays.txt pour chaque JAR, contenant
le nom des classes contenus dans le JAR.
Tu peux ensuite demandé au ClassLoader qui te donne accès à tous les
fichiers yt/macave/datas/ListPays.txt, tu peux donc les ouvrirs l'un
après l'autre pour découvrir les classes dans chacuns des JAR.

Le tout en utilisant le comportement 'normale' du ClassLoader... Ca
n'exclus pas tous les risques de déployment, mais ca limite quand même...
Sinon, pour en revenir à ton code, ca me semble super bizare une classe
yt.macave.datas.fr.France... Ca me laisse croire que tes données sont
hard-codé dans des classes java... pourquoi ne pas faire 1 ou plusieurs
fichiers de données en XML ???
Oui, c'est vrai, mais ce n'est que temporaire, ce n'est qu'une solution

intermédiaire et souple afin d'alimenter ma bd, je vois bien que je ne
pourrais pas continuer ainsi. Là je fais des boucles for sur des
String[][][] mais j'ai tellement de contres-exemples.

En fait, j'ai choisi cette méthode parce que j'améliore ma connaissance
des appellations tout en développant mon appli, les objets sur lesquels
je travaille ne sont pas encore figés du point de vue de leurs
attributs...

De plus, je suis tombé, en fin de semaine dernière, sur un bugg de cette
bd (db4o) avec les TreeSet, ça m'a "refroidi"... je me donne qq jours (
et au dev travaillant sur cette bd) pour dire si oui ou non je continue
avec cette bd-objet.

en tout cas merci pour ta longue réponse.


--
yt

Avatar
yvon.thoravalNO-SPAM
Olivier Thomann wrote:

Personnellement je pense que ton problème se résoudrait très bien avec
une base de données plutôt que plein de classes.
Tous tes problèmes d'existence de classes seraient gérés par la base de
données.
Juste une idée comme ça.



Oui, oui, j'ai aussi cette possiblité là, au lieu de déployer mon appli
avec des classes en dur (pour charger la bd), la déployer avec les
fichiers associés à cette bd (db4o utilise des fichiers *.yap),
d'ailleurs cette bd permet de travailler sur des données "read-only",
c'est le cas pour les appellations dans mon appli, l'utilisateur final
ne pourra pas changer ces données-là. La solution que j'utilise
actuellement, je suis d'accord pour dire qu'elle n'est pas élégante,
DOIT disparaître en cours de développement.

En fait, ce pb n'existera plus une fois l'appli (+ ou -) figée.

Merci.

--
yt