:: Enseignements :: Master :: M1 :: 2016-2017 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | TP noté de Java Avancé |
Le but de ce TP noté est d'implanter une sorte de coffre virtuelle permettant de stocker une valeur
accessible uniquement à certain utilisateur.
Vos sources Java produites pendant le TP devront être placées sous le répertoire
EXAM de votre compte ($HOME) (qui est vierge dans l'environnement de TP noté);
sinon, elles ne seront pas récupérées.
Exercice 1 - Safe
On cherche vérifier si un utilisateur, puis plus tard un utilisateur
parmi un groupe d'utilisateurs peux accéder ou non à une valeur stocker
dans un coffre virtuel.
Certains tests unitaires correspondant à l'implantation sont ici:
TPNoteTest.java.
-
Ecrire une classe User qui correspond à un utilisateur avec son nom.
Ecrire une classe Safe qui correspond à un coffre qui contient
l'utilisateur qui peut accéder à la valeur ainsi que la valeur.
Plus en detail, la classe User doit possèder un constructeur qui permet de créer
un utilisateur à partir de son nom ainsi qu'une méthode d'affichage affichant le nom
de l'utilisateur.
La classe Safe possède un constructeur qui créé un coffre à partir d'un
utilisateur et une valeur. L'utilisateur correspond à l'utilisateur qui peut accèder
à la valeur. En plus du constructeur, la classe Safe possède une méthode
getValue qui permet de récupérer la valeur ainsi qu'une méthode
isAuthorized qui prend un utilisateur en paramètre et renvoie un booléen
indiquant si il a le droit d'accéder à la valeur.
Pour l'instant, la méthode getValue n'a aucune protection pour vérifier
que c'est bien un utilisateur autorisé qui à le droit d'accéder à la valeur.
Nous changerons le code dans les questions suivantes pour cela.
-
On souhaite garantir qu'il ne puisse y avoir qu'un seul utilisateur ayant un nom donné.
On se propose pour cela de créer une classe UserManager ainsi qu'une méthode
d'instance createUser sur la classe UserManager pour créer un utilisateur.
Cette méthode a pour responsabilité de vérifier que si l'on cherche à créer plusiuers
utilisateur avec un même nom, une exception IllegalStateException sera levé.
On veillera à ne pas permettre de créer un utilisateur de nom null.
Ce n'est pas suffisant car il faut aussi garantir qu'il n'y aura pas plusiuers instance
de la classe UserManager car sinon, il pourrait y avoir plusieurs utilisateurs
de même nom mais créer par des instances différentes de UserManager.
Pour palier à ce problème, UserManager possède une méthode getUserManager
qui elle la seule façon d'obtenir une instance (toujours la même) de la classe Usermanager.
Implanter la classe UserManager et modifier la classe User en conséquence.
-
On souhaite modifier la classe Safe pour permettre à un groupe d'utilisateurs
d'accéder à la valeur du coffre (à la valeur de Safe).
Ecrire la classe Group qui correspond à un groupe d'utilisateurs sachant que
-
Un groupe d'utilisateur ne contient que des utilisateurs, pas d'autres groupes.
-
Tous les utilisateurs du groupe peuvent accéder à la valeur du Safe,
donc la méthode isAuthorized de Safe devra répondre vrai
pour n'importe quel utilisateur du groupe.
-
Ajouter plusieurs fois le même utlisateur au groupe est équivalent à ajouter l'utilisateur
une fois
Bien sûr, le code que vous avez déjà écrit précédemment et les tests, doivent
continuer à fonctionner.
-
On souhaite que les classes que vous avez écrites précédemment Safe, User
et Group soient tread-safe.
Note: vous avez deux tests qui peuvent vous aidez mais rappelez vous que si un test plante
cela veut dire que votre code à un problème mais si le code passe le test, cela ne veut pas
dire que le code est correcte. Les tests ne testent pas toutes les configurations possibles.
-
On souhaite ajouter dans la classe User deux méthodes:
-
getCurrentUser qui permet de récupérer l'utilisateur associé à la thread courante
si il existe (on utilise un Optional en type de retour pour indiquer si un tel utilisateur existe).
-
run qui prend en paramètre un code et exécute celui-ci de tel façon à ce que si le code
exécute getCurrentUser, alors l'utilisateur sur lequel on a appelée la méthode run
soit l'utilisateur renvoyé.
L'idée est donc d'associer à la thread courante un utilisateur pendant le temps que le code passé
en aparmètre de la méthode run soit exécutée.
-
Bien sûr, l'implantation de ces deux méthodes doit faire en sorte que la classe User
reste thread-safe.
-
Maintenant, que l'on sait associer un utilisateur à l'exécution d'un code, modifier le code
de la méthode getValue de la classe Safe tel que
-
La classe Safe soit toujours thread-safe.
-
Que un appel à getValue alors que l'utilisateur courant (le résultat de getCurrentUser)
est bien un utilisateur authorisé.
-
Note: comme on change la sémantique de getValue les tests testSafe et testSafe2
ne sont plus bon, vous pouvez les mettres en commentaire.
-
La classe UserManager peut être lock-free, comment faire ?
Modifier l'implantation de UserManager en conséquence.
L'astuce ici est d'utiliser une classe déjà existante de java.util.concurrente qui est lock-free
plutôt que de ré-inventer la roue.
-
Enfin, on souhaite ajouter une méthode waitUntilAuthorized à la classe Group qui lorsque elle est appelée,
met la thread courante en attente si l'utilisteur passé en paramètre ne fait pas partie des utilisateurs autorisés.
Si l'utilisateur est déjà authorisé, la méthode ne fait rien et si l'on authorise l'utilisateur alors les threads en attente
sont alors toutes débloquées.
Implanter la méthode waitUntilAuthorized qui prend un User en paramètre dans la classe Group.
© Université de Marne-la-Vallée