| Serveur et interface d'administration PingOO 2: Interface d'administration PingOO 2 |
Nous allons vous présenter les architectures et les divers principes mis en oeuvre dans la création de l'Interface d'Administration de PingOO 2. Dans ces pages seront exposés divers sujets comme les interaction entre le gestionnaire d'application et ses esclaves et outils ou encore la manière dont l'application récupère ses données dans son archive.
Nous tenons tout d'abord à préciser que le présent chapitre n'a ni
la prétention, ni la volonté de remplacer le didacticiel Java de Sun
(
http://java.sun.com/docs/books/tutorial/index.html) pour la
formation et l'apprentissage du langage Java.
De même ce chapitre n'est pas un cours sur les théories de la
programmation objet, il existe bon nombre d'ouvrages tel ] ou de sites web permettant de se documenter sur ce
sujet.
Par contres les pages suivantes contiennent des termes, des exemples
ou encore des schémas de conception reprenant les principes évoqués
dans les documents et ouvrages cités précédemment et dont la lecture
est fortement recommandée pour pouvoir arriver à comprendre ce
chapitre.
Ces pages s'adressent donc en premier lieu à des personnes ayant un
minimum de connaissances en programmation orientée objet ainsi que
dans le langage Java et dans la création d'interfaces graphiques
pour pouvoir maintenir correctement l'Interface d'Administration
PingOO.
Nous pouvons également préciser que les pages de documentation
générée par le compilateur javadoc ainsi que la lecture des
commentaires du code source Java apportent aussi une aide
non-négligeable pour comprendre comment fonctionne DLAI.
Nous allons présenter maintenant les divers fichiers et répertoires
importants dans la distribution du client. Bien que ces répertoires
soient invisibles à l'utilisteur final ils sont tours présents à
l'intérieur de l'archive .jar distribuée.
En effet un fichier .jar n'est ni plus ni moins qu'une
archive .zip à laquelle a été rajouté quelques informations
supplémentaires contenues dans un fichier manifeste spécial. Un
.jar peut de plus être numériquement signé pour guarantir
l'autenticité des données ete des classes qu'il transporte.
Nous vous conseillons de vous référer au didacticiel Java sur les
fichiers .Jar disponible à l'adresse
http://java.sun.com/docs/books/tutorial/jar/ pour avoir
plus d'informations sur la manière de manipuler ces fichiers.
L'arborescence sera présentée dans sa forme éclatée qui est utilisée
par le développeur. Par défaut dans la distribution standard se
trouvent deux fichiers portant l'extension .jar :
DLAI.jar et Loader.jar. Ces fichiers peuvent être
décompressés par l'une des deux commandes suivantes :
unzip nom_de_fichier (on peut aussi utiliser des utilitaires comme
Winzip sous Windows, disponible à l'adresse suivante
http://www.winzip.com/) ;jar xvf nom_de_fichier si le JDK est installé.Ceci désarchivera l'arborescence qui va être présentée maintenant.

Hormis les fichiers .jar, un certains
nombre de fichiers sont présents sur le répertoire racine.
Tout d'abord des scripts permettant de lancer l'interface d'administration (DLAI) :
DLAI.bat, DLAI.sh et
DLAI-test.bat, ces scripts lancent directement
l'interface d'administration
Note : dans ce cas la procédure de mise à jour n'est pas complètement supportéeet servent surtout au développement et au débogage.
Start.bat, Start.sh et
Start-test.bat utilisent le launcher pour
démarrer l'interface.D'autres scripts sont également présents sur le répertoire racine dans la version développeur. Ceux-ci permettent notamment de compiler le programmes, de créer la documentation associée ou encore de lancer la procédure d'archivage :
Make.bat et Make.sh permettent de
compiler le programme en appelant le compilateur javac
du JDK ;MakeDoc.bat et MakeDoc.sh permettent
quant à eux de générer la documentation HTML associée aux
fichiers sources Java en appelant le compilateur de
documentation du JDK javadoc ;MakeArchive.bat et
MakeArchive.sh archivent les données et créent les
fichiers .jar en appelant le compresseur du JDK : jar.
Ensuite le fichier default.properties contenant la
configuration par défaut de l'interface DLAI : la version, le
serveur par défaut ainsi que la liste des serveur optionnels, les
options de débuggage, et autres choses utiles dans le futur
(langue au lancement pour la fenêtre de connexion,
...).
Ce fichier utilise le mécanisme par défaut des ResourceBundle
inclus dans Java qui est le même que pour les fichiers de langue
et dispose d'un parseur automatique (d'où le fait que le fichier
se termine par .properties qui est l'extension par défaut pour les
ResourceBundle).
Voici un exemple de fichier de configuration :
######################### ATTENTION !!! ############################## # # # Cette bibliothèque est Copyright (C) Centre de Ressources # # Informatiques - AED - Conseil Général de la Haute Savoie # # Cette bibliothèque est Copyright (C) Fabrice Bouyé # # <bouye@cur-archamps.fr> # # Cette bibliothèque est distribuée sous la Licence 2 GNU GPL # # Cette bibliothèque est distribuée car potentiellement utile mais # # SANS AUCUNE GARANTIE, ni explicite, ni implicite, y compris les # # garanties de commercialisation ou d'adaptation dans un but # # spécifique. Reportez vous à la Licence Publique Générale GNU pour # # plus de détails. # # # ###################################################################### ############################ WARNING !!! ############################# # # # This Library is Copyright (C) Centre de Ressources Informatiques # # - AED - Conseil Général de la Haute Savoie # # This Library is Copyright (C) Fabrice Bouyé # # <bouye@cur-archamps.fr> # # This Library is distributed under GNU GPL License 2. # # This Libray is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # See the GPL.txt file for more information about the license. # # # ###################################################################### #Generic configuration ###################### # Contains the version number. # DO NOT TOUCH THE FOLLOWING LINE ! DLAIVersion=2.0 #Network configuration ###################### # Contains a list of available servers (bad idea if empty). # The first in the list is the default server. ServerList=station1.pingoo,station2.pingoo # Contains the server port. ServerPort=7433 #Tools configuration #################### # Constains the list of available tools. Tools=Abacus,BusyMonitor,Calculator,Clock,JEyes,MemoryMonitor,ThreadMonitor #Language configuration ####################### # Contains the default language eg : fr_FR. #If this field is empty, the default language will be the system's. Language=fr_FR #Font configuration ################### # Contains the name of the used font. # May be empty. FontName=Arial # Contains the style of the font : PLAIN, BOLD or ITALIC or BOLD+ITALIC. # If the content does not match any of this value PLAIN will be used. # May be empty. FontStyle=PLAIN # Contains the font size (the default is 8). # May be empty FontSize=10 #Debug configuration #################### # Enables other option, if Debug is false the other will not be used. Debug=false DebugGraphic=false DebugNetwork=false DebugLDAP=false DebugMessage=false DebugResource=false DebugException=false
On peut également trouver deux fichiers manifestes qui servent à
indiquer les classes à exécuter dans les fichiers .jar :
Manifest est associé au fichier DLAI.jar ;ManifestLoader est associé au fichier Loader.jar.L'utilisation de manifestes permet entre autre l'exécution
automatique du fichier .jar ciblé dans les environnements
qui le supporte.
voici le contenu du fichier Manifest :
Manifest-Version: 1.0 Main-Class: org.PingOO.DLAI.PPM.PPM Implementation-Title: "D.L.A.I." Implementation-Version: "2.0" Implementation-Vendor: "CRI Archamps"

Cette arborescence est nommée selon la norme Java d'extension des
ClassPath (chemins d'accès aux classes) :
type.nom.produit.... ce qui donne
org.PingOO.DLAI.... comme répertoire de base.
Les répertoires sont automatiquement générés lors de la compilation
des fichiers sources.
org.PingOO.DLAI.lib : contient toutes les
bibliothèques de base nécessaires au programme ainsi qu'à toutes
les futures applications qui seront incluses dans DLAI.
Les répertoires inclus sont les suivants :
org.PingOO.DLAI.lib.appli : classes de bases pour
créer de nouvelles applications, outils ou esclaves ; org.PingOO.DLAI.lib.appli.event : évènements
associés ainsi que les classes nécessaires à leur propagation ; org.PingOO.DLAI.lib.directorytree : classes de base
pour la gestion de l'annuaire LDAP implémentée dans PingOO,
celles-ci peuvent être réutilisées dans divers application
(gestion des utilisateurs, du matériel, des listes de
diffusion...) ; org.PingOO.DLAI.lib.graph : il s'agit d'un
bibliothèque de tracé de graphes récupérés sur Internet mais
non-encore testée ;org.PingOO.DLAI.lib.io : accès aux classes de
flux de bas niveau (sockets) et exceptions appropriées ; org.PingOO.DLAI.lib.net : accès au réseau et
exceptions appropriées (protocole de haut-niveau) ; org.PingOO.DLAI.lib.PWidget : bibliothèque
graphique (extension de Swing) gérant le multilangue et la
police centralisée ; org.PingOO.DLAI.lib.PWidget.event : évènements
pour la PWidget ; org.PingOO.DLAI.lib.PWidget.text : des styles de
documents par défaut pour les boîtes de saisie de texte.org.PingOO.DLAI.lib.util : des utilitaires pour la
configuration, des gestionnaires d'accès pour les ressources du
programmes et des classes partagées.org.PingOO.DLAI.PPM : contient les classes et les
composants de l'interface du gestionnaire de programmes ainsi que le
Kernel
Kernel : noyau, la partie centrale du programme.:
org.PingOO.DLAI.PPM.codec : encodeur et décodeur
réservés au dialogue client/serveur du protocole
PingOOp ; org.PingOO.DLAI.PPM.io : accès avancé aux flux de bas
niveau (sockets) et exceptions appropriées (protocole de
bas-niveau) ; org.PingOO.DLAI.PPM.net : accès avancé aux réseau et
exceptions appropriées (protcole de haute-niveau) ; org.PingOO.DLAI.PPM.security : gestion de la
signature des messages réservés au dialogue client/serveur du
protocole PingOOp. org.PingOO.DLAI.slave est la répertoire dans lequel
se trouvent toutes les application esclaves de l'interface
d'administration. Voici une liste non-définitive des packages
présents dans la version 2.0 :
org.PingOO.DLAI.slave.UGM : a été la première
application complète à fonctionner dans l'interface DLAI avec un
dialogue esclave/pilote utilisant le protocole PingOOp.
Il s'agit d'un gestionnaire d'utilisateurs et de groupes adapté
aux besoins de la distribution PingOO. org.PingOO.DLAI.lib.appli.tool contient les
outils qui sont de petites applications pour faciliter
l'administration ou pour passer le temps.
org.PingOO.DLAI.lib.appli.tool.Abacus : petits outils (horloge, moniteur mémoire ...) ;

Le répertoire lib contient toutes les ressources utilisées
par le programme, cet ensemble comprend aussi bien les données localisées
non-transmises par le serveur que les icônes, les images ou encore les
curseurs et les sons (ces derniers ne sont pas encore supportés).
Dans lib/resource sont inclus les différents fichiers de
langue, utilisant le mécanisme par défaut des
ResourceBundles du package java.util pour la
gestion de langue. Soit une requête au fichier au fichier de
ressources toto en utilisant la langue fr_FR, en cas de
défaut les fichiers suivants seront scannés dans l'ordre indiqué :
toto_fr_FR.properties ;toto_fr.properties;toto.properties.Dans DLAI, les application ont la possibilité de spécifier en plus un
fichier de ressources qui leur est propre si jamais il y a besoin de
surcharger les label ou d'en définir de nouveaux dont on ne veut pas
qu'il soit accessible depuis une autre application.
En cas de défaut la ressource sera recherchée dans le fichier par
défaut du programme qui se nomme DLAI.properties.
Un cache est mis en place pour éviter d'avoir à recharger les
différents bundles à chaque requête.
Ce sont les autre type de fichiers différents des fichiers de ressource de langue, et répartis dans divers répertoires. Ces répertoires partagent la même structure : dans le répertoire racine sont contenus les médias communs et accessibles par tous ensuite dans des répertoires du même nom que l'application se trouvent des médias spécialisés propres à chaque application :
lib/media ;lib/media/monAppli1 ; lib/media/monAppli2 ;En cas de défaut de la recherche dans un répertoire spécifique,
celle-ci s'effectue alors dans le répertoire commun
lib/media.
.gif
de 256 couleurs, des fichiers .jpg peuvent aussi être
inclus. Pour éviter des confusions et traitements coûteux sur des
images (même petites) les icônes on été séparées en deux parties :
les grandes et les petites, respectivement dans les répertoires
lib/icon et lib/miniicon.
Bien que se situant dans des répertoires séparés, les icônes grandes et petites sont gérées par un même gestionnaire et partagent certains algorithmes. Par exemple si une recherche pour une grande icône échoue dans le répertoire des grandes icônes, la recherche se poursuivra dans le répertoire des petites icônes et l'icône trouvé sera alors retaillée à la bonne dimension (resp quand on recherche une petite icône).
Des fonctions et méthodes de traitement des icônes sont dors et
déjà disponibles dans le gestionnaire
org.PingOO.DLAI.lib.util.IconManager
pour notamment redimensionner et composer entre elles des icônes.
lib/image.
Ces médias sont récupérés dans le programme sous forme d'Image
et non pas d'Icon, pour être utiliser de façon diverses par les
applications.
C'est le gestionnaire org.PingOO.DLAI.lib.util.ImageManager
qui permet de récupérer les images sur le disque
Note : si la
recherche d'une image échoue dans le répertoire lib/image, la
recherche s'effectuera alors dans le répertoire des icônes.
.
Comme pour les icônes les images sont des fichiers
.gif, et des fichiers .jpg. Un cache d'images
est également implémenté.
lib/cursor, mais ce n'est pas encore supporté dans
l'interface. Ils sont pris en charge par le gestionnaire
org.PingOO.DLAI.lib.util.CursorManager pour charger les
données
Note : si la recherche d'un curseur échoue
dans le répertoire lib/cursor, la recherche s'effectuera
alors dans le répertoire des icônes.
.
Basiquement ce sont des icônes auquelles on a rajouté un point
de contrôle. Ayant expérimenté ceci dans le projet de DESS
PetriStudio nous pouvons indiquer qu'il faut utiliser
des images .gif de taille 32x32, en 2 couleurs (!).
En effet contrairement à Windows, Java ne supporte que les
curseurs monochromes. Si jamais on utilise une image en 256
couleurs :
Donc dans tous les cas lorsque les curseurs seront supportés :
utiliser des .gif monochromes !
Évidement l'une des deux couleurs (le blanc en général)
deviendra la couleur transparente.
lib/sound, mais ne sont
pas encore supportés.
Ici aussi l'expérience a montré lors du stage DESS que Java ne
supporte pas tous les sous-formats .wav, par contre les
.au (de Sun) courant dans le monde UNIX fonctionnent
correctement.
lib/help en cas de défaut d'une recherche de page,
on pointe alors dans sur la page index ou sur une page d'erreur
dans ce répertoire ;
Dans lib/help/DLAI qui n'affiche que l'aide de
l'interface. Les défaut en cas de recherche générant une erreur. lib/theme
mains non-traités (il n'existe pas de gestionnaire
associés. Il s'agit de thèmes pour le look and feel
Metal de Java permettant de modifier la couleur des fenêtres
ainsi que la taille de la police de certains éléments comme les
barres titre ou les info-bulles.
D'autres répertoires sont présents sur la racine dans la distribution de développement de DLAI. Ces fichiers ne sont bien évidement pas inclus lors de l'archivage des données pour créer la distribution standard.
doc, et sont au format HTML. Ce sont
toutes les page de documentation générées par le compilateur
javadoc.org est automatiquement crée lors de l'utilisation
d'un des scripts MakeDoc.bat ou MakeDoc.sh. sources, tous les fichiers java nécessaires à la
compilation de DLAI et des applications esclaves.org.Make.bat ou Make.sh.
Cette figure rappelle l'architecture générale définie pour la construction du serveur d'administration PingOO 2.
Le client se compose donc de quatre grandes parties (FIG. Composants du client.) :
Codec : un encodeur/décodeur.et des interfaces pour le protocole PingOOp;
PPM : PingOO Program Manager ou encore Gestionnaire de Programmes PingOO.gère le multi-tâches et les droits d'accès aux applications, dispose d'une implémentation complète du protocole PingOOp ainsi que d'un bureau graphique dans lequel s'affichent les applications.
Ce package contient les classes de base dont le programme a besoin pour fonctionner, on y trouve pelle-mêle des gestionnaires pour accéder aux ressource, des classes de messages pour les transferts réseaux et d'autres objet comme la classe de configuration et des algorithmes de tris.
Cette classe est chargée de lancer l'interface lorsqu'elle est
éxécutée depuis un fichier .jar. De plus elle effectue la
mise à jour du programme en écrasant le fichier DLAI.jar
par une version différente contenue dans le fichier
DLAI.tmp si celui-ci existe. En cas de problèmes le lanceur
essaie de restaurer l'ancienne version qui a été sauvegardée dans un
fichier DLAI.old. Lorsque tout est prêt le chargeur essaie
alors d'exécuter la classe du gestionnaire de programmes :
org.PingOO.DLAI.PPM.PPM.
Tout simplement pour éviter des problèmes lors de la mise à jour
lorsque l'on écrase le fichier DLAI.jar par sa nouvelle
version DLAI.tmp. Si tout était contenu dans un même
fichier et que la mise à jour se passe mal (fichier endomagé,
coupure de courant, ...), il devient alors impossible de lancer le
programme. En effet en cas de dégat dans le fichier archive le
code n'est alors plus disponible et il faut réinstaller
entièrement le client.
En utilisant un chargeur externe qui se charege également de la mise à jour, on peut garantir que ce code-là sera toujours présent en cas de problèmes et on peut donc y inclure des solution pour essayer de rétablir un programme, certes qui n'est pas à la bonne version, mais qui peut espérer être mis à jour lors d'une connexion.
En effet lorsque Java charge en mémoire des classe ou des données il
recherche tout au long de son CLASSPATH, dans les
répertoires qui lui sont accessibles ou sur le réseau (lorsque l'on
utilise une URL distante), la première occurance du nom recherché.
Or lorsqu'on utilise un second fichier .jar et si on ne
le spécifie pas d'une manière ou d'une autre dans le
CLASSPATH
On peut spécifier le CLASSPATH en
tant que variable d'environement ou en paramètre de la ligne de
commande du programme.
, Java n'ira pas chercher ses
classes et ses données dans le fichier DLAI.jar.DLAI.jar dans les paramètres de lancement, mais
ceci devient impossible lorsqu'on utilise des .jar
distants dont l'URL peut varier ou peut même être saisie par
l'utilisateur.
Or comme il est impossible de modifier le CLASSPATH du
chargeur du système en cours d'exécution
Il en cependant possible de modifier la propriété, il faut créer un chargeur secondaire qui récupèrera les données là où on veut les récupérer.CLASSPATHen faisantSystem.setProperty(java.class.path, valeur)mais ceci n'a strictement aucun effet sur le chargeur du système.
Bien que ce ne soit pas supporté dans cette version, il est
cependant possible de modifier la classe DLAILoader pour
qu'elle aille rechercher le fichier .jar sur un serveur
web (par exemple) et lance l'application. On peut même très bien
envisager présenter une boîte de dialogue à l'utilisateur pour
qu'il spécifie lui-même le serveur ou trouver le programme client.
Le fichier Loader.jar ne peut être mis à jour en
utilisant le service de mise à jour de l'interface
d'administration. En effet à l'heure actuelle ce service ne
supporte que la récupération (et la sauvegarde) du fichier
DLAI.jar. Ceci oblige donc à faire un nouveau package
d'installation (.zip, .exe, .tar.gz,
...) pour les postes clients.
Le chargeur n'a pas accès à la PWidget ou au mécanisme de
changement de langue. Il n'est donc pas évident de pouvoir
présenter des boîtes de dialogue multilangues à l'utilisateur.
Quand bien même ces classes seraient intégrées dans le fichier
archive du chargeur, ce serait alors DLAI qui aurait des
problèmes puisque Java s'arrête sur la première occurence d'un nom
de classe donné et que dans ce cas DLAI serait obligé
d'utiliser la PWidget du chargeur qui peut évidement ne
pas être à jour...
Cette classe contient toute la configuration par défaut de
l'interface d'administration. Elle lit également lors de son
chargement le fichier default.properties. Ce fichier
présent sur la racine permet de modifier certaines valeurs et
certains paramètres de Config.
Config est utilisée par beaucoup d'objet dans le programme,
y compris les gestionnaires de ressources qui y puisent le noms des
répertoires de donnée, ou encore par le gestionnaire de la
PWidget DefaultPManager pour certaines valeurs de
mise en pages de composants. Elle est également utilisée par le
gestionnaire d'applications PPM car elle contient l'adresse
du serveur d'administration PingOO ainsi que son port et d'autres
informations importantes comme la liste des outils ou le numéro de
version de DLAI.
Les packages org.PingOO.DLAI.lib.io,
org.PingOO.DLAI.lib.net et
org.PingOO.DLAI.lib.util contiennent les prototypes, les
classes abstraites et les exceptions nécessaires à l'implémentation
du protocole PingOOp dans l'interface d'administration.
Ceic permet la création d'autres implémentations si besoin est.
Les véritables classes implémentant ce protocole se trouvent dans
les packages du gestionnaire de programme.

L'interface org.PingOO.DLAI.lib.io.ConnectionManager décrit
les méthods à implémenter pour créer un objet réalisant le protocole
de bas niveau. Tandis que la classe
org.PingOO.DLAI.lib.net.UpperProtocol décrit les principales
méthodes utilisables par le protocole de haut-niveau et propose une
implémentation par défaut pour certaines d'entre elles.
On peut remarquer en regardant le code, la documentation ou la
figure
Architecture des classes de base pour le protocole PingOOp de la classe
UpperProtocol que cette dernière utilise des objets
de type org.PingOO.DLAI.lib.util.MessageHashtable

En effet cette classe représente les message qui sont transférés au serveur via le réseau en utilisant le protocole PingOOp, ce ne sont pas des tables de hachage pour éviter que l'on puisse ajouter n'importe quel type de données. Ce nouvel objet n'accepte que les représentation Java des types prédéfinis dans le protocole PingOOp (FIG Architecture de la classe MessageHastable).
L'implémentation directe et complète du protocole et des diférents niveaux de sécurité sera discuté plus en avant dans les section concernant le gestionnaire de programmes.
Lorsqu'un élément du programme a besoin d'une donnée, qu'il
s'agisse d'une chaîne de caractères localisée, d'une icône, d'un
curseur ou de l'adresse d'une page d'aide, il utilise directement ou
indirectement l'un des gestionnaires de ressources du package
org.PingOO.DLAI.lib.util.

Ces gestionnaires sont pour la plus grande partie des
singletons, même si certains d'entre eux partagent du code,
notamment les méthodes permettant de trouver les fichiers
appropriés. D'autres comme le ResourceManager qui gère les
chaînes localisées, reposent sur des mécanismes internes à java :
les java.util.ResourceBundles.
Les données de DLAI sont conservées à l'intérieur d'une archive
.jar, surtout pour faciliter le transfert par réseau lors d'une
mise-à-jour à partir du serveur. Les recherches de données sont
font donc en utilisant des URL pointant vers ce fichier.
Dans le cas de l'exécution depuis un .jar, la classe
Manager dont hérite tous les gestionnaires délègue à la classe
DLAILoader le soin de retrouver les chemins des données nécessaires à
l'exécution du programme et de convertir ces chemins en
URL
Ces données seront utilisées par la suite pour charger
les données en mémoire via des appels spécifiques comme : new
ImageIcon(URL fileURL).
.
En effet utiliser deux fichier .jar différents
semblait poser un réel problème au chargeur de classes standard et
il ne pouvait plus trouver les données. Le fait d'utiliser le
chargeur externe servant à lancer l'application résout le problème.
Par contre dans le cas d'une exécution directe la classe
Manager utilise directement le chargeur de classes du
système :
java.lang.ClassLoader.getSystemClassLoader() qui fonctionne
parfaitement et suffit alors à retrouver les donnée des
applications.
On peut remarquer que certains gestionnaires comme
CursorManager, IconManager et
ImageManager s'appellent mutuellement.
En effet les curseurs et les images sont tout d'abord chargés
comme des icônes puis transférés dans le gestionnaire
approprié.
De même le gestionnaire d'icônes utilise le gestionnaire d'images
pour certaines opération comme pour récupérer le dessin associé à
une icône et (dans le futur) utiliser des algorithmes de
manipulation d'images pour créer de nouvelles icônes au vol.
Nous allons présenter maintenant la manière dont les données sont
récupérées. Chaque application dispose d'un répertoire ou un
fichier .properties qui lui est propre et qui porte son
nom.
Ce nom appelé module est très important car c'est grâce à
lui qu'on accède à toutes les chaînes localisée, icônes, images,
... associées à cette application. A chaque donnée est également
associée un nom appelée identificateur qui correspond
soit au nom de fichier (sans l'extension) soit à la clé de la
valeur dans un fichier .properties.
Lors de la recherche d'une icône par exemple le gestionnaire va d'abord rechercher le fichier (avec divers extensions) dans le répertoire correspondant au module spécifié, puis dans le répertoire racine de ce type de donnée qui se trouve être par défaut pour un module égal à DLAI.
Certains gestionnaires comme les gestionnaires de curseurs,
d'icônes ou d'images vont de plus chercher dans d'autres
répertoires annexes en cas d'echec dans leur propre dossier.
Ainsi ImageManager délègue en cas d'échec à
IconManager la récupération d'une image de remplacement
(si elle existe) dans ses propres répertoires de recherche.

Chaque gestionnaires permettent donc de retrouver facilement
n'importe quelle donnée utilisée par le programme et la
positionne dans des caches gérés en fonction du module appelant.
Ces caches sont bien sûr vidés et réinitialisés lors de la
déconnexion de l'utilisateur. Ceci permet non-seulement de
libérer la mémoire mais également de ne pas laisser de
traces de l'utilisateur précédent.
Ces caches sont pour la plupart de simples tables de hachage
indexées en fonction du module et contenant les données associées
aux identificateurs. Elles sont elle-même contenues dans une table
de hachage plus importante : le cache du gestionnaire (FIG
Schéma d'un cache de données standart).
Lors d'un défaut dans la table demandée le gestionnaire va d'abord
chercher dans la table de hachage associée au module DLAI
(le module par défaut) puis essaie de récupérer la donnée sur le
disque ou dans l'archive .jar.
Certains gestionnaires disposent de caches fonctionnant de manière
plus spécifiques comme CursorManager qui indexe également
des caches en fonction du point de contact du curseur, ce qui
permet d'avoir plusieurs curseur pour une même icône.
De son côté ResourceManager dispose d'un cache de
java.util.ResourceBundle associé à chaque module. Ces bundles sont
rechargés à chaque changement de langue de l'application.
Ce gestionnaire est différent des autres car il repose sur des
méthodes et des classes peu développées et peu documentées de
Java, au contraire des ResourceBundle qui sont
largement présentés dans les didacticiels. Le gestionnaires
d'impression fait de plus sans doute appel à des méthodes
natives.
En effet même s'il est possible d'imprimer en Java depuis la
version 1.1.0, il y a très peu d'exemples ou de documentation
disponible chez Sun (
http://java.sun.com/javaone/javaone98/sessions/T310/index.htm)
ou ailleurs sur Internet, utilisant ou discutant de ce mécanisme.
Certains ouvrages comme ]
traitent succinctement de ce sujet sans s'y attarder ni
fournir d'exemples probants.
Pour éviter de retomber dans le piège des appels natifs, il
faut donc implémenter l'interface Printable du package
java.awt.print et utiliser la classe
PrinterJob sans aucune indication quand à la manière
de procéder.
La distribution de l'interface d'administration inclue donc la
classe TextPrintable (FIG
Les classes des gestionnaires) qui est un filtre
d'impression de chaînes de caractère entièrement écrite en Java. D'autres
filtres seront à prévoir pour pouvoir imprimer des pages web
ou des pages d'aide ainsi que des images.
En fait imprimer en Java revient à faire exactement la même chose
que dessiner sur l'écran. Le programmeur a juste besoin de dessiner
ce qu'il doit imprimer dans un objet de type
java.awt.Graphics comme il dessine dans sa
Canvas ou dans son Applet.
Si ceci ne pose a priori pas de problèmes pour les
images ou les chaînes de texte, il en va autrement lorsqu'il faut
imprimer une page web. Faute de pouvoir récupérer de tels
composants sur Internet, il faudra voir comment la classe
JEditorPane affiche les pages web et utiliser un dérivé
de ce Renderer pour imprimer.
Il faut tout d'abord créer un objet dérivant de
Printable qui fera l'impression de l'objet que l'on veut
sortir sur papier. L'appel PrinterManager.print(Printable
monPrintable)lance ensuite l'impression dans une Thread
séparée.
Le gestionnaire d'impression affichera alors une fenêtre spécifique au système sur lequel tourne l'application (la fenêtre standard d'impression sous Windows ou la fenêtre de la bibliothèque libXp sous LINUX) ce qui permet à l'utilisateur de configurer quelques options, puis lancera l'impression en tache de fond.
De temps à autre sous LINUX, si on lance trop d'impression en même temps certaines threads se bloquent et l'objet envoyé au gestionnaire ne s'imprime jamais.
Quand le JDK sous LINUX est mal configuré et que les polices True Type ne sont pas accessibles en lecture aux utilisateurs (voir http://www.blackdown.org/java-linux/jdk1.2-status/known-bugs.html) :
La création d'une nouvelle bibliothèque de widgets
Widget: widget vient de l'abréviation de Window Gadget (on peut traduire gadget par truc), il s'agit de composants graphiques dont on peut paramêtrer l'aspect et le comportement en fonction de ses besoins. Des composants ayant des fonctionnements communs sont regroupés dans des bibliothèques comme l'AWT, Swing, Motif ou Athena permettant de créer des interfaces graphiques.reposant entièrement sur Swing, s'est avérée nécessaire d'une part pour pouvoir facilement implémenter le changement de langue et de police au vol, mais aussi pour simplifier et mettre au même niveau certains composants de Swing pour faciliter les futures extensions de DLAI par d'autre développeurs.
En effet, Swing est encore très récent et certains composants,
notamment les composants dits éclatés ou à modèle comme les
JList, les JTables ou encore les
JTree ne disposent pas encore d'appels de méthode
standardisés et peuvent être déroutant à l'usage. Au contraire,
les composants simples tels les JButtons ou les
JMenus se manipulent directement et leur inclusion dans
la PWidget consiste alors juste à l'extension de leurs fonctionnalités.
La PWidget (disponible dans le package
org.PingOO.DLAI.lib.PWidget) contient donc toute une
série de composants appelés PComponents prêt à
l'emploi que le programmeur pourra directement intégrer dans son
code. Ces composants sont d'ailleurs tous compatibles avec leur
équivalent Swing.
Cette bibliothèque dispose également de plusieurs outils comme
des modèles par défauts pour les arbres, les listes et les
tables graphiques et ainsi que des utilitaires pour adapter des
JComponent en cas de besoin.
Outre les fonctions nécessaires à l'implémentation directe
d'un PComponent (FIG.
Architecture d'un PComponent.), un objet de ce type de
possède un objet PManager (texto : un gestionnaire
de PComponent) via lequel il recherche ses données
localisées, ses icônes, ... (ici le travail est effectué par la classe
DefaultPManager qui utilise la classe Config et les
gestionnaires du package org.PingOO.DLAI.lib.util).
De plus un observateur de type PObserver est affecté à un
objet PComponent lors de sa création, cette objet sert
de lien avec un bus événementiel qui transporte les
informations de changement de langue et de police.
Le PManager est donc les gestionnaire via lequel un PComponent va
récupérer ses données lors d'un changement de langue, de police, ou
s'il a besoin d'une icône dans le cas d'un PComponent à
modèle.
Or classe PManager est une classe abstraite, le travail
réel est effectué par le DefaultPManager.
Cette seconde classe accède directement aux différents algorithmes,
gestionnaires de données et autres objets partagés dans le package
org.PingOO.DLAI.lib.util (FIG
Architecture du PManager).
En utilisant cette méthode il est beaucoup plus facile de porter la
PWidget vers d'autres applications qui ne posséderait pas du tout
les même caractéristiques que DLAI au niveau du stockage
des données du programme par exemple. Il suffit alors de réécrire un
nouveau PManager et le tour est joué.
On peut même envisager les choses plus loin. En effet il est
possible d'associer n'importe quel PManager à un
PComponent. Ce principe permettrait de récupérer des
données, un peut partout, y compris sur le réseau en s'adressant à
chaque fois à des classes spécifiques et dont l'action est ciblée
plutôt qu'à une seule grosse classe.
Le PObserver a été créé dans un premier temps dans un soucis
de centraliser du code afin de ne pas avoir à réécrire les
même lignes dans chacune des classes héritant de l'interface
PComponent.
Par la suite cette classe est devenue essentielle pour garder,
par exemple lors de l'intégration de composants Swing, la
cohérence et l'intégrité de l'aspect graphique l'interface.

La classe PObserver dispose d'un bus événementiel (FIG
Architecture d'un PComponent.)
partagé par toutes les instances de cette classe. De plus chaque
PObserver est directement lié (FIG
Laison entre les PObserver et leur cible) à son objet
cible (un JComponent ou un PComponent) ce qui
permet de faire les changement de langue ou de police lorsque ces
évènements sont capturés.
Le programmeur ou un composant de rendu automatique
(voir les diverses classes Renderer
Renderer : ces classes servent à dessiner, pour les afficher, les sous-composants de composants de haut niveau comme les noeuds d'un arbre ou les cellules d'une table graphiquede Swing) peuvent très bien insérer un
JComponent normal
dans une interface entièrement constituée de
PComponents. En cas de changement de police par
exemple, l'intégrité visuelle de l'interface n'est alors plus respectée.
Le PObserver a donc été aussi conçut pour pouvoir venir se
brancher sur un JComponent et changer ses
caractéristiques si besoin est. Pour ce faire il suffit d'utiliser
l'appel suivant :
new Pobserver(monJComponent)
Et voilà ! Le PObserver notifiera dorénavant l'objet ciblé lors du
changement de police
En effet les.JComponentne sont à priori pas localisables. On peut changer leurLocalemais cela n'a aucun effet sur leur contenu.
Le problème principal est que la référence du PObserver
sur l'objet ciblé n'est pas détruite (FIG
Laison entre les PObserver et leur cible) et donc que
l'objet ciblé restera en mémoire tant que cette liaison n'est pas
explicitement brisée
Ces appels ont lieu lorsque l'utilisateur se déconnecte ou demande à l'interface de redémarrer., le garbage collector n'arrivant pas à cette cible.
Donc au fil du temps lorsque l'utilisateur ouvre des applications et de nouvelles fenêtres, de plus en plus d'objets sont référencés en mémoire. Si tant est que DLAI est une interface d'administration et non un véritable bureau graphique utilisé à 100% du temps, ceci n'est pas vital. Mais une solution doit être à long terme trouvée pour régler cet inconvénient :
PObserver vérifie les parents des composants ciblés et
éliminent ceux dont les parents sont null ou qui ne
sont pas visibles. Ceci est loin d'être parfait puisque certains
composants peuvent avoir des parent null comme les
frame ou être temporairement invisibles comme les panneaux des
utilisateurs dans UGM qui sont contenus dans un cache.stop() des classes PSlave
et PTool. Mais ceci ne retirerai pas tous les
composants de la mémoire.
Dans le même genre d'idée, il serait possible de retirer tous les composants ayant un même module. Ceci pose également problème puisque les boutons présents dans les menus du gestionnaire de programme ont le même module que l'application qu'ils lancent.
PObserver et donc la liaison peut-être définitivement
brisée.
Le gestionnaire d'applications ou PPM sert quant à lui en même temps de contrôleur pour la sécurité de l'ensemble du client et de bureau graphique dans lequel vont s'afficher les différentes applications. Ce gestionnaire dispose également d'une implémentation complète du protocole PingOOp ce qui lui permet de communiquer avec le serveur.
PPM est le premier module de l'interface d'admnistration à contacter le serveur Perl. Le gestionnaire prend de plus à sa charge toute la phase de connexion et d'identification auprès du serveur. Même une fois la connexion établie PPM continue à monitorier le réseaux notamment en faisant des Ping réguliers pour récupérer des informations sur les applications qui sont connectées au serveur.
Ping était destiné au départ à empêcher les applications esclaves de rester indéfiniment connectées au serveur en encombrant la bande passante en désactivant celle restée inactives depuis un trop long laps de temps. Bien que ceci ne soit pas implémenté dans la version actuelle, Ping n'en reste pas mois utile car il permet entre autre de détecter quand le serveur ne répond plus et que la liaison réseau a été coupée.
A partir du moment ou la coupure a été détectée, PPM demande à l'utilisateur s'il désire quitter l'interface graphique. L'utilisateur peut en effet continuer à utiliser l'interface pour utiliser des outils mais il se peut aussi que pour une raison ou une autre seule la connexion entre PPM et le serveur ait été coupé, il peut donc quand même essayer de sauvegarder ses données de travail avant de redémarrer l'interface pour tenter une reconnexion automatique.
Une fois l'identification achevée, le gestionnaire de programmes
reçoit une liste d'applications esclaves susceptibles d'êtres
lancées par l'utilisateur. Le gestionnaire récupère également
auprès de la classe Config le liste complète des outils qui
sont fournis dans la distribution de l'interface d'administration.
PPM utilise le mécanismes de la réflection pour charger en mémoire les classes appropriées des application esclaves et des outils à partir de leur nom au format texte. PPM crée alors les boutons associés pour pouvoir démarrer ces applications. L'utilisateur n'a donc pas accès à toutes les applications esclaves de l'interface d'administration, mais uniquement à celles autorisées dans son profil. Par contre il aura accès à tous les outils car leur utilisation n'est pas restreinte.
De plus PPM doit veiller à ce qu'il on ne puisse pas faire tourner la même application plusieurs fois en même temps. Ceci permet d'une part d'éviter des problèmes d'incohérences lors de l'utilisation simultanée du même esclave. Mais cela permet aussi d'autre part d'alléger la charge de la machine sur laquelle tourne DLAI.
PPM utilise, lorsque l'utilisateur clique sur un bouton pour
démarrer une application (que ce soit un esclave ou un outil),
une nouvelle fois le mécanisme de la réflection. Il obtient tout
d'abord un constructeur appartenant à la classe de
l'application. Ce constructeur est ensuite utilisé pour créer une
une instance de cette classe. Et enfin il utilise la méthode
start() qui permet de démarrer l'application.
Lorsqu'une application esclave est démarrée, elle ne crée pas par elle-même sa connexion vers le serveur. C'est toujours les gestionnaire d'application qui grâce à son implémentation de PingOOp, ouvre une nouvelle connexion sur le serveur d'administration puis passe cette objet en paramètre au constructeur de l'esclave.
Ceci permet d'éviter des tentatives pirates pour lancer des applications non-autorisée si jamais un jour PPM dispose d'une console qui peut exécuter des commandes pour lancer des applications ou même des tentatives pour contacter d'autres serveur sans passer par le mécanisme de proxy. Bien sur le serveur filtre aussi les tentatives de connexions, mais autant alléger la charge réseau un maximum si possible.
Lorsqu'une application se termine, en général lorsque
l'utilisateur ferme la fenêtre ou clique sur le bouton
Exit, un événement est propagé et capturé par PPM.
PPM récupère alors la source de cet événement qui n'est
autre que l'application en cause, puis exécute la méthode
stop() de cet objet. Ensuite le gestionnaire
d'application réactive tous les boutons qui permettaient
d'exécuter de ce programme.
Quelle que soit la manière de quitter PPM, ce sont
toujours les mêmes actions qui sont exécutées et toujours dans le
même ordre. Ces différentes actions sont présentes dans la méthode
stop().
POptionPane) présente dans le bureau, ce qui
d'ailleurs leur fait retourner
POptionPane.UNKNOWN_RESULT ;MainDesktop ;PObservers de briser les liaisons qu'ils ont avec de
PComponents ou des JComponents. Ceci permet de
libérer de la mémoire lorsque l'utilisateur veut uniquement se
déconnecter ou redémarrer.L'utilisateur a donc la possibilité de redémarrer le
gestionnaire. Lors de la phase de connexion l'identificateur ainsi
que le mot de passe de l'utilisateur sont stockés dans les données
privées de la classe PPM.ProgramManagerRestartRunnable.
Une fois le gestionnaire courant totalement arrêté, la classe de
lancement est exécutée en tâche de fond
(SingUtilities.invokeLater(Runnable runnable)) pour
démarrer une nouvelle instance de PPM et essayer de se
reconnecter automatiquement auprès du serveur.
La déconnexion se passe à peut près de la même manière hormis le
fait que ce n'est pas la classe
PPM.ProgramManagerRestartRunnable qui est exécutée en
tâche de fond mais la classe
PPM.LoginWindowRestartRunnable. Ceci permet de réafficher
la fenêtre d'identification.
La procédure de sortie (et d'arrêt du programme) est légèrement
différente : en effet avant de commencer la méthode
stop(), une thread est lancée. Cette thread sert de
timer en cas de problèmes dans la méthode
stop().
Au bout d'un certains temps ( 30s dans la version actuelle) le
programme est coupé abruptement. Ceci n'est pas très propre mais
permet d'éviter que le programme reste indéfiniment en mémoire.
Ce délai pourra sans doute être augmenté s'il apparaît que le
temps moyen de sauvegarde des esclaves et des clients est plus
long que 30s.

L'interface du gestionnaire d'applications se présente comme un bureau graphique standard dans lequel viennent s'afficher les fenêtres internes des différents esclaves ou outils.
Outres les habituels menus Fichier et Aide,
viennent s'ajouter les menus Outils et
Applications qui présentent les différents programmes que
peut lancer un utilisateur.
Un clic avec le bouton droit de la souris (CRTL+bouton gauche sur
Macintosh) présente un menu popup reprenant les contenus de ces
deux menus pour pouvoir accéder plus aisément aux applications.
De plus une horloge vient compléter la barre de menu du bureau
pour indiquer l'heure à tout moment.
L'apparence du bureau utilise le Look and Feel standard de
Java : Metal. L'utilisateur peut néanmoins le modifier en fonction de
ses préférences via un outil de configuration. Ce même outil
permet également à l'utilisateur de modifier la police et la langue
utilisée ainsi que les réactions des fenêtre au passage de la souris.

Nous allons faire une rappel rapide sur les différents classes de
base (FIG
Architecture des classes de base pour le protocole PingOOp) du protocole
PingOOp qui ont présentée dans la section sur
la bibliothèque partagée (org.PingOO.DLAI.lib).
Les fonctions du protocole de bas niveau sont toutes décrites dans
l'interface org.PingOO.DLAI.lib.io.ConnectionManager.
Les fonctions de base du protocole de haut-niveau sont accessibles
dans la classe org.PingOO.DLAI.lib.net.UpperProtocol. Ces
méthodes sont suffisantes pour envoyer et recevoir des données
vers un serveur d'administration PingOO mais nous
pouvons remarquer que la procédure de connexion est absente. Ceci
est tout à fait normal et est nécessaire pour empêcher des
esclaves d'ouvrir de leur propre chef des connexions vers d'autres
serveurs.
L'interface org.PingOO.DLAI.lib.net.MessageFormatter
décrit les fonction servant à interpréter les paquets de données
brutes et cryptées reçues sur le réseau en objets message plus
évolué et aptes à être utilisés dans le programme. Les descriptifs
des fonctions permettant de transformer les messages en chaînes ou
en octets y sont également inclus.

Cette classe est l'équivalent des messages transmis sur le
réseau. Elle fonctionne exactement comme une table de hachage mais
les clés sont des chaîne de caractère (java.lang.String)
et les valeurs contenues sont uniquement d'un des quatre types
suivants (FIG
Architecture de la classe MessageHastable) :
java.lang.String ;java.lang.String[] (des
tableaux de chaînes) ;or.PingOO.DLAI.lib.util.ValueHastable (des tables de
valeurs) ;or.PingOO.DLAI.lib.util.BinaryData (des valeurs
binaires). Cet objet possède de plus des propriétés définies par les
clés ACCEPTED_KEY, COMMENT_KEY,
FUNCTION_KEY, MODULE_KEY et
REQUEST_ID_KEY. Ces propriétés définissent des valeurs
importants utilisées dans le transfert réseau, comme le non de la
fonction à exécuter ainsi que le module qui doit la lancer.
Les objets or.PingOO.DLAI.lib.util.ValueHastable
correspondent aux tables de hachage définies dans le protocole
PingOOp. Les clés sont des chaînes de caractères
(java.lang.String) et les valeurs ne peuvent être que de
deux types :
java.lang.String ;or.PingOO.DLAI.lib.util.ValueHastable.Cette classe encapsule les données binaires telles qu'elles sont
transmises par le serveur via le protocole. En fait la classe
BinaryData contient juste un tableau d'octets avec
éventuellement un nom de fichier associé.

Cette figure (FIG Architecture complète de l'implémentation de PingOOp présente l'architecture complète de l'implémentation du protocole PingOOp dans la distribution de l'interface d'administration (il ne manque gère que les exceptions).
Comme ConnectionManager n'est qu'une interface ne donnant
que des descriptif, cette partie est entièrement assurée par la classe
org.PingOO.DLAI.PPM.io.MasterConnectionManager, qui à
l'aide de sockets et des classes chargées du cryptage et
de la signature permet de communiquer avec le serveur.
L'implémentation complète du protocole de haut-niveau, y compris
les phases de connexion au serveur sont réalisés par les classes
org.PingOO.DLAI.PPM.net.MasterProtocol et
org.PingOO.DLAI.PPM.net.MasterMessageFormatter.
MasterMessageFormatter est chargé de recréer un objet
MessageHashtable avec les données qui ont été récupérée
par le réseau, en utilisant la classe Base64Codec.
MasterProtocol est de son côté un automate décrivant les
états dans lesquels il est possible d'envoyer des messages au
serveur. Cet classe permet la connexion initiale au serveur,
lorsque PPM est lancé, mais aussi permet d'ouvrir de
nouvelles connexion pré-initialisées lors du démarrage d'un esclave.
Nous définissons une application esclave comme étant un programme pouvant se lancer dans l'interface d'administration PingOO et qui communique avec un driver présent sur le serveur Perl au moyen du protocole de communication PingOOp. Le droit d'utiliser une application esclave varie en fonction des droits concédés à chaque utilisateur de l'interface d'administration.

Tous les programmes esclaves sont destinés à être lancés
uniquement au sein de l'interface d'administration PingOO. Chaque
application esclave hérite de la classe abstraite PSlave
et est donc un objet de type PInternalFrame : soit une
fenêtre interne qui s'affiche dans le bureau de l'interface.
Un objet de type PSlave est de plus connecté à un bus
événementiel qui peut l'avertir lors d'actions telles que le
changement de langage, l'arrêt d'un autre esclave ou d'un
outil...
Ceci permet notamment à un esclave de réagir spécifiquement à ces
évènements selon ce que veux le programmeur et selon les besoins
du client.
Chaque esclave est lancé à partir de l'interface du gestionnaire
de programmes lorsque l'utilisateur clique sur le bouton approprié.
Une première phase d'analyse dans la fonction de démarrage
consiste alors à récupérer la classe du programme, puis un
constructeur approprié. Une connexion réseau vers le serveur est
ensuite créée, puis une instance de l'esclave est initialisée avec
cette connexion.
Le gestionnaire n'a alors plus qu'à lancer le programme esclave en
tâche de fond.
Tant qu'un esclave donné tourne, il est impossible d'en lancer un
second du même type car les boutons ont été désactivés lors du
lancement initial. Ces boutons restent désactivés jusqu'à l'arrêt
de l'application.
Un esclave peut s'arrêter de trois manières différentes :
Dans les sous-sections suivantes nous supposerons que nous disposons
d'un esclave MonEsclave qui est défini dans le fichiers
source sources/org/PingOO/DLAI/slave/MonEsclave/MonsEsclave.java.
Évidement, il n'est point possible de lancer l'application si
PPM n'arrive pas à instancer un nouvel objet à partir
de la classe MonEsclave. Il faut donc que le
constructeur public MonEsclave(UpperProtocol protocol)
existe et que celui-ci fasse appel au constructeur approprié
de la classe PSlave selon les besoins du programmeur.
PPM utilise ce constructeur pour passer à l'esclave une
connexion réseau déjà préétablie avec le serveur
d'administration. C'est typiquement dans ce constructeur
qu'est instancié l'objet Request qui représente la
couche requête de cette application.
Les deux autres fonctions obligatoires sont celles qui
définissent le nom de l'esclave, ce sont String getModule()
qui est une méthode d'instance et String getSlaveName() qui
est une méthode de classe. Ces deux fonctions doivent retourner
le même nom, qui est aussi celui de la classe, du fichier et du
répertoire : MonEsclave.
Chaque esclave dispose d'une méthode void start(). En
général on commence à construire l'interface graphique dans
cette méthode et on peut récupérer des objets nécessaires à
l'initialisation de l'application via le réseau. Cette méthode
peut éventuellement se terminer pas un appel à la méthode
start() de la super-classe.
Si l'interface et les premières initilisations sont faîtes dans
le constructeur (à éviter car dans note cas il vaut mieux garder
un constructeur rapide et léger), il n'y a à priori pas besoin de
réécrire cette fonction, car PPM appèlera directement
le start() de PSlave.
La méthode void stop() sert faire des sauvegardes sur le
serveur avant l'arrêt de l'application. Mais elle sert avant
tout à permettre de libérer (en brisant des liens) toutes les
ressources qui peuvent être accaparées par l'application. Ainsi
il est courant d'arrêter les toutes les threads de l'esclave
dans cette méthode.
Si cette méthode n'est pas surchargée, le stop() de
PSlave fera des libérations par défaut puis coupera la
connexion réseau. Au contraire si cette méthode est surchargée
il faut obligatoirement appeler le stop() de la
super-classe sur la dernière ligne de la nouvelle méthode sinon
la connexion réseau ne sera jamais coupée.
Cette méthode de classe (Icon getSlaveIcon()) permet de
récupérer l'icône associée au bouton et à la fenêtre de
l'application MonEsclave. Elle est optionnelle mais c'est plus joli
avec une icône.
La méthode de classe String getSlaveToolTipKey() permet de
récupérer la clé déterminant le texte de l'info-bulle du bouton
et de l'info-bulle de la fenêtre de l'application esclave.
Enfin la méthode de classe String getSlaveTitleKey()
permet de récupérer la clé déterminant le texte du bouton et le
titre de la fenêtre de l'application MonEsclave.

Comme l'indique la figure Les différents niveaux dans la communication réseau d'un esclave celui-ci est, à proprement parlé, composé de deux couches :
Comme spécifié dans la description du protocole PingOOp, un
client peut appeler des fonctions sur le serveur ou sur une machine distante.
La partie requête d'un programme esclave doit alors créer un objet
MessageHashtable qui contient le nom de la fonction,
ainsi que le drivers où se situe la fonction. Ce
message contient également des données qui peuvent être
nécessaires à l'exécution de la requête sous forme de chaînes, de
tableaux de chaînes, de tables de hachage ou de fichier.
Si la requête a été acceptée, le serveur renvoie alors un résultat
sous forme de MessageHashtable, que le programme esclave
exploitera selon ses besoins.
Chaque application esclave a à sa disposition un groupe de thread personalisé. Il est préférable de lancer toutes les threads dépendantes de la même application dans un même groupe de threads.
Normalement lorsqu'une application est arrétée, toutes ses threads
doivent être interrompues, puis il faut libérer le groupe de
threads. Bien que ceci fonctionne bien sous Linux tant avec les
outils que les esclaves, des problèmes
d'IllegalStateException sont apparus sous Windows lors de
la libération du groupe de threads de certains outils. Le code de
libération a donc été désactivé et les groupes de threads
persistent tant que l'application n'a pas été arrêtée ou
redémarrée.
Un outil est tout comme un esclave une application qui se lance à l'intérieur de l'interface d'administration. Mis à part cela, un outil ne communique pas avec le serveur et l'utilisation d'un outil particulier n'est soumis à aucune restriction : tout le monde peut utiliser tous les outils.
A peu de choses près un outil est exactement la même chose qu'un
esclave avec néanmoins une différence importante : un outil ne
communique pas avec le serveur PingOO via le réseau.
De plus les outils sont de petites applications fournies directement
dans l'interface et utilisables par tout le monde. Il n'y a pas de
restrictions quand à leur usage.
Il est donc important que les futurs outils ajoutés dans l'interface d'administration ne soient pas des applications sensibles ou à haut risque. Il faut qu'ils restent de petits utilitaires pour aider à l'administration.

Tout comme les PSlaves, un outil (héritant de la classe
abstraite PTool) est une fenêtre interne s'affichant dans
le bureau de l'interface d'administration. On peut d'ailleurs
notter l'estrème similarité entre l'architecture d'un outil et
celle d'un esclave, il ne manque guère en fait que la partie
réseau...
En effet une fois le principe de fonctionnement d'un esclave déterminé et simplifié, il était suffisement modulable pour être adapté pour d'autres applications qui utilisent les ressources propres de la machine sur laquelle s'exécute l'application cliente. Ainsi sont nés les outils, dont la philosophie est tournée vers la machine locale même s'ils se concoivent, se programment, s'utilisent et fonctionnent à peu de chose près de la même manière qu'une application esclave qui elle est orientée vers le dialogue client-serveur.
Le cycle de vie d'un outil (FIG Le cycle de vie d'un outil) est exactement le même que celui d'un esclave (FIG Le cycle de vie d'un esclave) hormis qu'il n'y a pas de création d'une liaison avec le serveur et que l'outil ne communique pas avec le serveur pendant son execution.
Mis à part cela c'est exactement le même principe pour les deux types d'application, elles naissent, se lancent et s'executent exactement de la même manière.
Dans les sous-sections suivantes nous supposerons que nous disposons
d'un outil MonOutil qui est défini dans le fichiers
source sources/org/PingOO/DLAI/tool/MonOutil/MonsOutil.java.
Évidement, il n'est point possible de lancer l'application si
PPM n'arrive pas à instancer un nouvel objet à partir
de la classe MonOutil. Il faut donc que le
constructeur public MonOutil(UpperProtocol protocol)
existe et que celui-ci fasse appel au constructeur approprié
de la classe PTool selon les besoins du programmeur.
PPM utilise ce constructeur pour passer à l'outil une
connexion réseau déjà préétablie avec le serveur
d'administration. C'est typiquement dans ce constructeur
qu'est instancié l'objet Request qui représente la
couche requête de cette application.
Les deux autres fonctions obligatoires sont celles qui
définissent le nom de l'outil, ce sont String getModule()
qui est une méthode d'instance et String getToolName() qui
est une méthode de classe. Ces deux fonctions doivent retourner
le même nom, qui est aussi celui de la classe, du fichier et du
répertoire : MonOutil.
Chaque outil dispose d'une méthode void start(). En
général on commence à construire l'interface graphique dans
cette méthode et on peut récupérer des objets nécessaires à
l'initialisation de l'application via le réseau. Cette méthode
peut éventuellement se terminer pas un appel à la méthode
start() de la super-classe.
Si l'interface et les premières initilisations sont faîtes dans
le constructeur (à éviter car dans note cas il vaut mieux garder
un constructeur rapide et léger), il n'y a à priori pas besoin de
réécrire cette fonction, car PPM appèlera directement
le start() de PTool.
La méthode void stop() sert faire des sauvegardes sur le
serveur avant l'arrêt de l'application. Mais elle sert avant
tout à permettre de libérer (en brisant des liens) toutes les
ressources qui peuvent être accaparées par l'application. Ainsi
il est courant d'arrêter les toutes les threads de l'outil
dans cette méthode.
Si cette méthode n'est pas surchargée, le stop() de
PTool fera des libérations par défaut puis coupera la
connexion réseau. Au contraire si cette méthode est surchargée
il faut obligatoirement appeler le stop() de la
super-classe sur la dernière ligne de la nouvelle méthode sinon
la connexion réseau ne sera jamais coupée.
Cette méthode de classe (Icon getToolIcon()) permet de
récupérer l'icône associée au bouton et à la fenêtre de
l'application MonOutil. Elle est optionnelle mais c'est plus joli
avec une icône.
La méthode de classe String getToolToolTipKey() permet de
récupérer la clé déterminant le texte de l'info-bulle du bouton
et de l'info-bulle de la fenêtre de l'outil.
Enfin la méthode de classe String getToolTitleKey()
permet de récupérer la clé déterminant le texte du bouton et le
titre de la fenêtre de l'application MonOutil.
Chaque outil a à sa disposition un groupe de thread personalisé. Il est préférable de lancer toutes les threads dépendantes de la même application dans un même groupe de threads.
Normalement lorsqu'une application est arrétée, toutes ses threads
doivent être interrompues, puis il faut libérer le groupe de
threads. Bien que ceci fonctionne bien sous Linux tant avec les
outils que les esclaves, des problèmes
d'IllegalStateException sont apparus sous Windows lors de
la libération du groupe de threads de certains outils. Le code de
libération a donc été désactivé et les groupes de threads
persistent tant que l'application n'a pas été arrêtée ou
redémarrée.
N'hésitez pas à consulter la partie dissertant d'UGM dans le chapitre réservé au serveur pour en savoir plus sur les divers fonctions disponibles dans le driver.

UGM utilise les composants de l'annuaire inclus dans le package
org.PingOO.DLAI.lib.directorytree pour simuler sur la
machine locale la base de donnée contenue sur le serveur.
Ces composants sont placés dans un package externe à UGM car ils
peuvent être réutilisés pour d'autres applications comme le futur
MLM qui gérera les listes de diffusion.
Ces composants sont classés en deux familles principales : les noeuds et les feuilles.
Les noeuds sont typiquement des objets qui peuvent contenir
d'autres sous-objets (des noeuds ou des feuilles). Ils se
décomposent en trois grands familles : les noeuds racines, les
noeuds home et les groupes. Les noeuds héritent de la
classe abstraite DirectoryNode.
Les noeuds racines sont ceux qui sont utilisés pour créer le
chemin vers une organisation comme un pays
(CountryNode), un département
(DepartementNode), ...
Normalement le dernier noeud est de type
OrganizationNode et ne peut contenir que des noeuds
spéciaux de type HomeNode.
Les homes sont des noeuds particuliers qui sont placés
dans l'organisation. Pour chaque type de home (héritant
de la classe abstraite HomeNode) il ne devrait y avoir
à priori qu'une seule instance sous organisation.
Ainsi il n'existe qu'un seul noeud de type PeopleHome
qui contient des utilisateurs dans une organisation.
Les groupes sont des noeuds qui peuvent contenir d'autres
groupes ou des feuilles, parmi eux on peut citer la classe
UserGroup qui correspond à un noeud contenant des
utilisateurs dans UGM. Ces types de noeuds héritent de
la classe abstraite GroupNode.
Les noeuds feuilles héritent de la classe abstraite
DirectoryLeaf. Ces objets sont classé en deux sous-types
principaux : les fiches et les alias.
Les fiches sont des objets renseignant des choses, des
personnes, des listes de diffusion...
Par exemple dans le cas de des utilisateurs dans UGM ce
sont des feuilles de type UserSheet.
Les alias héritent de AliasLeaf. Ce sont typiquement
des feuilles qui pointent vers d'autre feuilles (des fiches
uniquement pour le moment).
Dans UGM les administrateurs sont de type
AdministratorAlias tandis que les alias utilisateur
sont de type UserAlias. Ces deux objets héritent de la
classe abstraite PersonAlias car ils partagent du code
et des attributs.
Chaque type d'objet dispose d'un ensemble d'attributs qui lui est propre. Certains attributs sont hérités des sur-classes, d'autre sont hérités dans la classe même. Ces attributs sont définis par des clé publiques dans l'objet même.
Ainsi un utilisateur dispose de presque tous les attributs qui
sont définis dans l'annuaire LDAP. Certains attributs sont quand
même absents car ils ne doivent jamais se retrouver sur
l'interface du client.
De plus chaque attribut dispose de valeurs satellites associées
comme un label localisé et surtout un droit d'accès. Ces droits
sont stockés sur le serveur et permettent de savoir si
l'utilisateur d'une application donnée de DLAI a le droit
de modifier un attribut.
Les types de ces attributs sont définis dans le constructeur de
l'objet d'annuaire associé. Il est possible de modifier des
attributs en remplaçant leur valeur par un nouvel objet du même
type. Cette action s'effectue en appelant la méthode
setAttributeValue() de l'objet.
Si une demande de modification s'effectue sur une clé donnée et
que celle-ci appartient à l'objet alors il y a vérification des
droits d'accès sur cet attribut. Dans le cas où on peut le
modifier et si le type de la nouvelle valeur est compatible avec
le type de l'ancienne, le remplacement est effectif. Dans tous les
cas d'erreur, rien ne se passe.
Ce même package contient de plus d'autres utilitaires pour aider à
manipuler ces objets dans le contexte d'une interface
graphique. Ainsi les classes DirectoryTree,
DirectoryTreeModel et
DirectoryComponentTreeCellRendrer permettent d'utiliser
ces composants dans un arbre graphique. D'autre comme
DirectoryTreeFormatter permet de construire un arbre à partir d'un
message réseau envoyé par le serveur (c'est cette classe
qu'utilise UGM). D'autres classe permettent d'afficher
des composants dans des liste ou encore de les imprimer.

Le gestionnaire se compose de deux grandes parties : un arbre représentant l'arborescence de la base de données et un panneau qui présente les données et les valeurs des attributs de cet objet.
Via les barres d'outils et de menus et surtout via le menu popup qui apparaît lorsqu'on clique avec le bouton de droite sur un noeud, il est possible d'effectuer des actions sur cette arborescence comme créer de nouveau objets d'annuaires, les déplacer ou les supprimer.
Lorsqu'UGM démarre il récupère une arborescence sur le
serveur et crée l'arbre d'annuaire DirectoryTree
associé. Chaque noeud de cet arbre n'est alors qu'une coquille vide
: les attributs sont initialisés avec des valeurs par défaut (vides)
et les droits d'accès ne permettent pas de modifier leur
contenu. Les noeuds qui sont dans cet étant sont déclarés comme
étant non-à-jour.
Quand un utilisateur clique sur un noeud qui n'est pas à jour, UGM récupère alors ses droits d'accès réels sur le serveur ainsi que les valeurs des attributs visibles par le client. Le noeud peut ensuite être modifié si tant est que l'utilisateur peut modifier au moins un des champs.
Tous les envois, récupérations et sauvegardes des attributs ou des
objets eux-même se fait dans l'objet Request associé à UGM.
C'est le code source de cet objet et celui du driver associé qui
à regarder en premier lieu pour comprendre comment effectuer des
actions sur la base LDAP via le réseau.
La création d'un objet est un processus délicat car il faut s'assuer qu'on donne suffisemetn d'infomations requise pour que la création soit possible dans la base LDAP tout en évitant qu'une collision ait lieu avec un noeud pre-existant.
Il faut donc avant-tout créer un objet vide, puis remplir ses données
requises via des appels à la méthode setAttributeValue()
tout en modifiant les accès par défaut sur les attributs pour
pouvoir les modifier.
Il faut également donner un nom à ce nouvel objet. La politique
régissant la création de ce nom varir fortement suivant le type du
noeud qui est créé. Il faut regarder dans le code source de la
classe CreationPanel disponible dans le même package
qu'UGM pour voir les algorithmes à appliquer suivant que
l'on veut un utilisateur physique, une institution ou un groupe.
Il faut ensuite envoyer l'objet vers le serveur en vérifiant que le
nom qu'on lui a choisit. Cette vérification est entièrement prise en
charge par l'objet Request. Ainsi il ne faut pas s'étonner
si lors de la création d'un utilisateur, un chiffre apparait dans le
nom de ce nouvel objet lorsqu'il est inséré dans l'arbre. C'est tout
simplement qu'il existait déjà précedement un utilisateur avec
extactement le même nom dans la base.
Enfin l'objet peut être envoyé à la base LDAP pour sa création sur le serveur. Si le serveur accepte la requête on peut alors insérer l'objet dans l'arbre représentant la base côté client en le marquant comme non-à-jour pour que l'utilisateur provoque de lui-même la récupération des données générées lors de la création sur le systèmes (GCOS, Home, ...) la prochaine fois qu'il cliquera sur cet objet.
DLAI peut être compilé en utilisant l'un des deux scripts
Make.bat ou Make.sh. Ces scripts contiennent juste
des lignes de commandes qui compilent les divers packages séparément
et dans l'ordre de leur dépendances comme :
javac -d . /sources/org/PingOO/DLAI/lib/util*.java
Une modification mineure d'une classe ou d'un package ne nécessite pas à priori de recompiler l'intégralité de l'application. Ici et contrairement au langage C par exemple, la phase de linkage est dynamique et a lieu en cours d'exécution.
Le documentation de programmation est constituée de commentaires
spéciaux insérés dans le code source de l'application. Si vous
voulez plus de détails sur la documentation Java veuillez vous
référer à cette adresse
http://java.sun.com/products/jdk/1.2/docs/tooldocs/javadoc/index.html
. La documentation est générée par un des
deux scripts MakeDoc.bat et MakeDoc.sh. Ces
fichiers contiennent chacun une ligne de commandes :
javadoc -private -locale fr -author -version -sourcepath ./sources -d ./doc/ <liste des packages>
En utilisant le compilateur jar fournis avec le JDK et les
scripts MakeArchive.bat et MakeArchive.sh bien
sur! Ces scripts contiennent les lignes suivantes :
jar cvmf ManifestLoader Loader.jar org/PingOO/DLAI/lib/util/DLAILoader.class GPL.txt jar cvmf Manifest DLAI.jar org/ lib/ default.properties GPL.txt
jar utilise les mêmes options que le compresseur
tar sous UNIX et LINUX plus d'autres pour permettre la
modification du manifeste par défaut avec un fichier externe.
Ces deux scripts vont créer les fichiers DLAI.jar et
Loader.jar qui sont utilisées dans la distribution.
Vous devez au moins avoir une machine virtuelle compatible Java 2 installée dans votre système d'exploitation. De plus cette machine virtuelle doit supporter les JFC (Java Foundation Classes) pour pouvoir exécuter les applications utilisant Swing.
Vous pouvez récupérer la dernière version du JRE (Java Runtime Envirronement), si vous êtes simple utilisateur ou la dernière version du JDK (Java Development Kit) si vous êtes développeur directement depuis le site de Sun ( http://www.java.sun.com/).
Cette version est lancée à partir des fichier .jar et
utilise la classe org.PingOO.DLAI.li.util.DLAILoader pour
charger le programme en mémoire
java -jar Loader.jar
Loader.jar, soit vous utilisez la ligne de
commande suivante :
C:\WINDOWS\SYSTEM\java -jar Loader.jar
Ou encore pour lancer l'application dans un processus séparé :
C:\WINDOWS\SYSTEM\javaw -jar Loader.jar
Cette version utilise l'arborescence éclatée nécessaire au développement de l'application. Nous pouvons donc lancer l'application en appelant directement le gestionnaire de programmes.
java -classpath . org.PingOO.org.PPM.PPM
C:\WINDOWS\SYSTEM\java -classpath . org.PingOO.org.PPM.PPM
Ou encore pour lancer l'application dans un processus séparé :
C:\WINDOWS\SYSTEM\javaw -classpath . org.PingOO.org.PPM.PPM
Dans ce cas la mise à jour n'est pas entièrement supportée car le
fichier .jar est récupéré mais comme le programme est
lancé à partir de l'arborescence éclatée, cela ne change en rien
le numéro de version. Il faut donc dans ce cas directement
modifier le fichier default.properties.
Il faut tout d'abord créer un nouveau répertoire
sources/org/PingOO/DLAI/tool/MonEsclave/ dans lequel
placer au moins un fichier MonEsclave.java.
Le nouvel esclave doit obligatoirement hériter de la classe
org.PingOO.DLAI.lib.appli.PSlave.
Le nouvel esclave peut utiliser directement les données du
fichier par défaut de DLAI. Mais l'esclave peut tout
aussi bien posséder et utiliser son ou ses propres fichiers de
langue dans le répertoire lib/resource :
MonEsclave.properties contient la langue par
défaut ;MonEsclave_fr.properties est le fichier pour
toute la langue française ;MonEsclave_fr_FR.properties est le fichier de
langue pour le français parlé en Métropole.Prenons le cas des icônes qui sont placées dans le répertoire
Vous devez rajouter un ligne pour la compilation du nouveau
package à la fin des fichiers Make.bat et Make.sh.
Vous devez rajouter le nom du package
org.PingOO.DLAI.tool.MonEsclave dans la ligne de
commandes des fichiers MakeDoc.bat ete MakeDoc.sh.
Il faut tout d'abord créer un nouveau répertoire
sources/org/PingOO/DLAI/tool/MonOutil/ dans lequel placer
au moins le fichier MonOutil.java.
Le nouvel outil doit obligatoirement hériter de la classe
org.PingOO.DLAI.lib.appli.PTool.
A priori les outils n'ont pas besoin d'avoir leur propres icônes et leur propre fichiers de langues. Cependant, l'usage du mécanisme du module n'est absolument pas réservé aux application esclaves et peut très bien fonctionner avec des outils.
S'il s'avère nécessaire de créer des ressources spéciales pour un outil il faut alors procéder de la même manière que pour une application esclave.
Pour la compilation ainsi que la documentation, il faut procéder
exactement de la même manière que pour les esclaves. Par contre
il ne faut pas oublier de modifier le fichier
default.properties et rajouter le nouvel outil à la liste
des outils pré-existants.
Tout simplement car il ne faut pas oublier que l'interface est avant-tout destinée à fonctionner sous Windows même si elle est développée sous LINUX. Comme il y existe des différences de comportement entre les deux systèmes (cf Mémoire), il faut toujours tester l'interface sous Windows avant de valider la mise à jour.
N'oubliez pas que vous devrez utiliser java et non pas
javaw pour visualiser les messages d'erreur. N'oubliez pas
également qu'il n'est pas possible de scroller dans une fenêtre DOS
pour visualiser les messages d'erreurs
On peut trouver sur Internet des sharewares qui permettent de récupérer les messages parus dans une boîte DOS et de les garder dans un tampon..