Page suivante Page précédente Table des matières Serveur et interface d'administration PingOO 2: Interface d'administration PingOO 2  

4. Interface d'administration PingOO 2

4.1 Introduction

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.

4.2 Arborescence des fichiers du client

Les fichiers Jar

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.

Décompression des données

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 :

Ceci désarchivera l'arborescence qui va être présentée maintenant.

Représentation de l'arborescence

L'arborescence de la distribution standard.

Fichiers sur la racine

Hormis les fichiers .jar, un certains nombre de fichiers sont présents sur le répertoire racine.

Scripts de lancement

Tout d'abord des scripts permettant de lancer l'interface d'administration (DLAI) :

Scripts de compilation.

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 :

Fichiers de configuration par défaut

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   

Les manifestes

On peut également trouver deux fichiers manifestes qui servent à indiquer les classes à exécuter dans les fichiers .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"

Arborescence des fichiers class

Les packages présents dans la version 2.0 du client.

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.

Arborescence des ressources

L'arborescence des fichiers de données dans la distribution standard.

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).

Fichiers de langues

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é :

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.

Fichiers média

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 :

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.

Arborescence de développement

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.

4.3 Principes généraux

Architecture générale

Architecture générale.

Cette figure rappelle l'architecture générale définie pour la construction du serveur d'administration PingOO 2.

Composants du client.

Le client se compose donc de quatre grandes parties (FIG. Composants du client.) :

4.4 Les objets partagés

Le package org.PingOO.DLAI.lib.util

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.

La classe DLAILoader

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.

Pourquoi un second Jar?

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.

pourquoi utiliser un autre ClassLoader?

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.
Il est vrai que pour un fichier local, on peut envisager de placer la chaîne 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é CLASSPATH en faisant System.setProperty(java.class.path, valeur) mais ceci n'a strictement aucun effet sur le chargeur du système.
, il faut créer un chargeur secondaire qui récupèrera les données là où on veut les récupérer.

Extensions

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.

Problèmes connus

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...

La classe Config

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 prototypes du protocole PingOOp

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.

Architecture des classes de base pour le protocole PingOOp.

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

Architecture de la classe MessageHastable.

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.

Les gestionnaires de ressources

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.

Architecture

Les classes des gestionnaires.

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.

Communications entre gestionnaires

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.

Principe de récupération des données

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.

Caches

Schéma d'un cache de données standard.

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.

Le gestionnaire d'impression

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.

Comment imprimer?

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.

Utilisation du gestionnaire d'impression

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.

Problèmes connus

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 P-Widget

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.

Architecture

Architecture d'un PComponent.

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.

Fonctionnement du PManager

Architecture du PManager.

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.

Fonctionnement du PObserver

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.

Fonctionnement

Laison entre les PObserver et leur cible.

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.

Utilisation de JComponents

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 graphique
de 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 JComponent ne sont à priori pas localisables. On peut changer leur Locale mais cela n'a aucun effet sur leur contenu.
.

Problèmes connus

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 :

4.5 Le gestionnaire d'application

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.

Dialogue 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.

Intérêt de Ping

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.

Gestion des applications

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.

Création des boutons

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.

Politique vis à vis des applications

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.

Lancement d'une application

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.

Lancement d'un esclave

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.

Terminaison d'une application

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.

Terminaison du gestionnaire de programme

Procédure standard

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().

Redémarrage

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.

Déconnexion

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.

Sortie

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.

Interface graphique

Le bureau du gestionnaire de programmes PingOO.

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.

Implémentation de pingOOp côté client

Données partagées

Architecture des classes de base pour le protocole PingOOp.

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).

protocole de bas-niveau

Les fonctions du protocole de bas niveau sont toutes décrites dans l'interface org.PingOO.DLAI.lib.io.ConnectionManager.

protocole de haut-niveau

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.

Table de messages

Architecture de la classe MessageHastable.

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) :

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.

Table de valeurs

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 :

Les valeurs binaires

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é.

Données privées

Architecture complète de l'implémentation de PingOOp.

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).

Protocole de bas niveau

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.

Protocole de haut niveau

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.

4.6 Fonctionnement d'une application 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.

Architecture

L'architecture générale d'un esclave.

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.

Cycle de vie

Le cycle de vie d'un esclave.

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 :

Fonctions caractéristiques

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.

Fonctions obligatoires

Constructeur

É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.

Nom

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.

Fonctions optionnelles

Démarrage

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.

Arrêt

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.

Icône

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.

Info-bulle

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.

Titre

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.

Accès au réseau

Les différents niveaux dans la communication réseau d'un esclave.

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 :

Discussion avec le serveur

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.

Mise à disposition d'un groupe de thread

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.

Problèmes connus

Accès au réseau bloquant

Libération du 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.

4.7 Le fonctionnement d'un outil

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.

Architecture

L'architecture générale d'un outil.

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.

Cycle de vie

Le cycle de vie d'un outil.

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.

Fonctions caractéristiques

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.

Fonctions obligatoires

Constructeur

É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.

Nom

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.

Fonctions optionnelles

Démarrage

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.

Arrêt

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.

Icône

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.

Info-bulle

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.

Titre

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.

Mise à disposition d'un groupe de thread

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.

Problèmes connus

Libération du 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.

4.8 Description du fonctionnement d'UGM

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.

Les objets de l'annuaire

Architecture des composants de l'annuaire.

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

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

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 home

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

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 feuilles

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

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

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.

Un objet, 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.

Utilitaires complémentaires

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.

Interface graphique

Interface graphique du gestionnaire d'utisateurs et de groupes.

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.

Récupération de la base

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.

Création d'un objet

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.

4.9 Frequently Asked Questions

Comment compiler le client?

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.

Comment compiler la documentation?

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>
  

Comment créer les fichiers Jar?

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.

Comment exécuter le client?

Prérequis

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/).

Version utilisateur

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

Version développeur

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.

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.

Comment ajouter un nouvel esclave?

Les sources

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.

Les fichiers de données

Les fichiers de langage

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 :

Autres fichiers média

Prenons le cas des icônes qui sont placées dans le répertoire

Modification des scripts

Compilation

Vous devez rajouter un ligne pour la compilation du nouveau package à la fin des fichiers Make.bat et Make.sh.

Documentation

Vous devez rajouter le nom du package org.PingOO.DLAI.tool.MonEsclave dans la ligne de commandes des fichiers MakeDoc.bat ete MakeDoc.sh.

Comment ajouter un nouvel outil?

Les sources

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.

Les fichiers de données

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.

Modification des scripts

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.

Pourquoi tester sous Windows ?

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.
.