:: Enseignements :: Master :: M1 :: 2013-2014 :: Java Avancé ::
[LOGO]

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 !

  1. 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.
  2. 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
  3. 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);
            
  4. 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".
  5. 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 :)
  6. 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 ?
  7. 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 !
Vérifier avec les tests unitaires que votre implantation est bien conforme. PushPathMonitorTest.java

Exercice 2 - PollPathMonitor

  1. 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.
  2. 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.
  3. 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.
  4. 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.
  5. Il existe pas mal de code commun à PushPathMonitor et PollPathMonitor, refactoriser votre code pour éviter la duplication de code.
Vérifier avec les tests unitaires que votre implantation est bien conforme. PollPathMonitorTest.java

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

  1. 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.
  2. 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.
Vérifier avec les tests unitaires que votre implantation est bien conforme. PollPathMonitorTest2.java et PushPathMonitorTest2.java