:: Enseignements :: Master :: M1 :: 2013-2014 :: Java Avancé ::
![[LOGO]](http://igm.univ-mlv.fr/ens/resources/mlv.png) | Souriez vous etes surveilles |
On souhaite réaliser un petit programme qui surveille les fichiers
qui sont créés dans un répertoire donné. Dans un premier temps,
on demandera au file system de nous prévenir quand un fichier
du repertoire change, les informations étant poussées du
file system vers votre programme, on parle de push de données.
Dans un second temps, on voudra pouvoir choisir si le programme fonctionne
en mode
push ou en mode
pull. Le mode
pull
consiste à aller chercher périodiquement la liste des fichiers d'un répertoire
et à les comparer avec l'état précédent du répertoire.
Ces exercices permettent de se familiariser avec la syntaxe des lambdas
et avec les APIs du paquetage
java.nio.file.
Exercice 1 - PushPathMonitor
On souhaite écrire une classe fr.umlv.monitor.PushPathMonitor
qui utilise le java.nio.file.WatchService du système de fichier.
Pour cela, il faut dans un premier temps récupérer le FileSystem
par défaut en utilisant la classe java.nio.file.FileSystems
puis créer un WatchService dessus.
Enfin il faut enregistrer le repertoire de surveillance sur
le WatchService grace à la méthode path.register.
Lisez la javadoc de WatchService avant de vous lancer !
-
A quoi correspondant la classe java.nio.file.Path ?
A quoi sert la classe java.nio.file.Paths (avec un s à la fin) ?
Ecrire une classe Main de test, créant un java.nio.file.Path
sur le répertoire courant (".") et affichant celui-ci.
-
A quoi sert la classe java.nio.file.FileSystems ?
Comment obtenir le file system par défaut ?
A quoi sert la classe java.nio.file.WatchService ?
Comment créer un WatchService ?
Modifier le code de votre main pour créer un WatchService
-
A quoi sert la méthode register sur la classe java.nio.file.Path ?
A quoi sert la classe java.nio.file.StandardWatchEventKinds ?
Comment utiliser un import static pour que le code suivant fonctionne ?
path.register(watchService, ENTRY_CREATE, ENTRY_DELETE, ENTRY_MODIFY);
-
A quoi servent les méthodes poll et take sur un WatchService ?
Laquelle doit on utiliser ici ?
Comment récupérer tous les évènements associées à une clé ?
Comment récupérer le Path à un évènement particulier ?
Modifier votre classe Main pour afficher les fichiers créés,
supprimés ou modifiés dans le repertoire courant.
L'affichage devra être celui-ci
./foo.txt changed
./foo.txt changed
Note sous UNIX, touch foo créer un fichier nommé "foo" vide et
rm foo supprime le répertoire "foo".
-
On peut noter que le chemin affiché est relatif au répertoire surveillé.
Changer votre code pour que le chemin affiché soit le chemin contenant
le répertoire et pas le chemin relative au répertoire ?
Il y a une méthode magique sur Path pour résoudre le problème :)
-
Ecrire une classe PushPathMonitor, un constructeur qui prend
un répertoire à surveiller et une méthode monitor qui
affiche à chaque fois qu'un des fichiers dans le répertoire est
créé, supprimé ou modifié.
Note: La méthode monitor utilisera une boucle infinie et
pour tester changer votre classe Main pour utiliser
la classe PushPathMonitor.
Comment doit-on gérer l'IOException dans le constructeur ?
-
Pour pouvoir réutiliser la classe PushPathMonitor, on souhaite éviter
que la méthode monitor fasse elle même l'affichage.
On va pour cela découpler l'affichage de la partie qui détecte si un fichier est modifié.
La technique habituelle pour ce genre de chose est de demander à l'utilisateur
de la classe de fournir l'implantation d'une interface qui fera les affichages
de la façon souhaitée par l'utilisateur.
Modifier le constructeur de la classe PushPathMonitor pour prendre
un second paramètre de type PathStateChangeListener et modifier
votre méthode monitor pour utiliser cette interface.
De plus, modifier votre classe Main pour que les affichages
soient effectués par celle-ci.
Note: il faut utiliser une lambda ici !
Exercice 2 - PollPathMonitor
-
Avant de commencer à coder la classe PollPathMonitor, écrire dans une
classe Main2 un main qui va lister l'ensemble des
fichiers du répertoire ".".
Il existe une méthode newDirectoryStream qui renvoie un DirectoryStream
qui permet d'obtenir les différents fichiers.
Un DirectoryStream implante Iterable<Path> donc il
est possible de faire une boucle for-each dessus.
-
Un DirectoryStream doit être fermé en appelant la méthode close,
comment faire pour garantir que le DirectoryStream est fermé même si
une ecpetion est levée penadant le parcours.
Modifier votre code en utilisant la syntaxe du try-with-resources pour résoudre votre problème.
-
Modifier votre main pour faire un diff entre deux appels
à newDirectoryStream et afficher uniquement les fichiers qui changent.
Note: La structure de donnée à utiliser pour sauvegarder les fichiers n'est pas une List.
-
Ecrire la classe fr.umlv.monitor.PollPathMonitor
ayant un constructeur prenant les mêmes arguments
que la classe PushPathMonitor et utilisant un DirectoryStream
pour monitorer des fichiers.
Pour la méthode monitor, pour éviter de faire chauffer
le processeur on utilisera Thread.sleep pour
ne faire la liste des fichiers qu'une fois toutes les 10s.
-
Il existe pas mal de code commun à PushPathMonitor et
PollPathMonitor, refactoriser votre code pour éviter
la duplication de code.
Exercice 3 - Filtre ou Philtre [à la maison]
On souhaite pouvoir spécifier un filtre sur les deux
PathMonitor
qui va indiquer si un nom de fichier doit où non être surveiller.
Si aucun filtre n'est spécifier, il faudra surveiller tout les fichiers
(donc avoir le comportement précédent).
On utilisera pour cela l'interface ci-dessous.
sachant seuls les fichiers pour lesquels la méthode
accept
renverra vrai devront être surveillé.
-
Ajouter une méthode setPathFilter(PathFilter) aux classes
PushPathMonitor et PollPathMonitor
sachant qu'il existe dans la classe java.nio.file.Files
une surcharge de la méthode newDirectoryStream qui prend un filtre en paramètre.
Notez que le type du filtre pris en paramètre de newDirectoryStream
n'est pas un PathFilter mais quelque chose s'y approchant grandement.
-
On souhaite maintenant tester la méthode setPathFilter en créant un
filtre qui affiche surveille tout les fichiers '.txt'.
Ecrire le code de test dans une méthode main d'une classe Main.
Note: la classe String possède une méthode endsWith.
© Université de Marne-la-Vallée