:: Enseignements :: ESIPE :: E4INFO :: 2011-2012 :: Java Avancé ::
[LOGO]

Souriez vous etes surveilles


On souhaite réaliser un petit programme qui surveille les fichiers qui sont créé dans un répertoire donné. Dans un premier temps, on utilisera une technique dite de polling consistant à périodiquement regarder les fichiers d'un répertoire et de comparer avec l'état précédent du répertoire. Dans un second temps, on demandera gentiment au file system de nous prévenir quand un fichier du repertoire change, c-a-d une technique dite push.
Ces exercices permettent de se familiariser avec la syntax des classes anonymes et avec les APIs du paquetage java.nio.file.

Exercice 1 - PollPathMonitor

Avant de commencer à coder la classe PollPathMonitor, Ecrire dans une classe MonTestAMoi un main qui va lister l'ensemble des fichier du répertoire ".". On utilisera pour cela, la méthode Paths.get() qui permet de créer un Path correspondant à ".", la classe java.nio.file.Files qui contient tout ce qu'il faut pour manipuler des Path (nom de fichier), entre autre une méthode newDirectoryStream (qui est un Iterable<Path>) et qui donc devrait vous permettre d'obtenir le contenu du repertoire grâce une simple boucle for-each.

  1. Ecrire une classe PollPathMonitor dans le package fr.umlv.file prenant en paramètre un repertoire à surveiller. Le constructeur devra lever l'exception IOException si le repertoire n'est pas un répertoire ou que le programme n'a pas l'accès en lecture sur le répertoire.
  2. Ajouter une méthode monitor qui toutes les 100 milisecondes affiche tous les Path contenu dans le repertoire passé à la construction.
    On utilisera Thread.sleep pour attendre. La seule façon de sortir de monitor est si la thread courante est interrompu, Il faut donc gérer les InterruptedException et InterruptedIOException correctement ?
  3. Modifier la méthode monitor pour n'afficher que les fichiers créé et supprimé entre l'ancienne liste de fichiers et la nouvelle liste.
    Dans quel strcture de donnée doit-on utiliser pour stocker les fichiers pour que le diff entre deux listing de répertoire n'est pas une complexité en O(n2).
  4. Pour pouvoir réutiliser la classe PollPathMonitor, on souhaite éviter que la méthode monitor fasse elle même l'affichage. Pour cela, écrire une méthode addPathStateChangeListener qui prend en paramètre un objet implantant l'interface PathStateChangeListener et qui stocke celui-ci dans une liste.

    Modifier la méthode monitor pour que tous les PathStateChangeListener qui se sont au préalable enregistré en utilisant addPathStateChangeListener aient leur méthode pathAdded et pathDeleted appelée.
  5. Ecrire une classe Main de test dans le package fr.umlv.file.main qui vérifie que le programme marche. Le main effectuera l'affichage des fichiers ajoutés ou supprimé
            ./foo.txt added
            ./foo.txt deleted
           

    Note sous UNIX, touch foo créer un fichier nommé "foo" vide et rm foo supprime le répertoire "foo".
Verifier avec les tests unitaires que votre implantation est bien conforme. PollPathMonitorTest.java

Exercice 2 - PushPathMonitor

On souhaite maintenant écrire une nouvelle classe 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.
Une partie du code de PollPathMonitor et PushPathMonitor est le même, ne le dupliquez pas. De plus, on ne souhaite pas voir à l'extérieur de paquetage fr.umlv.file que les deux PathMonitor partage du code.
Lisez la javadoc de WatchService avant de vous lancer !

  1. Ecrire le constructeur de la classe PushPathMonitor qui prend en paramètre le répertoire à surveiller avec les même contrainte que pour la classe PollPathMonitor.
  2. Implanter la méthode addPathStateChangeListener.
  3. Implanter la méthode monitor.
    Si vous n'avez pas encore lu la javadoc de WatchService, il est temps de la faire :)
Verifier avec les tests unitaires que votre implantation est bien conforme. PushPathMonitorTest.java

Exercice 3 - Filtre ou Philtre

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) à la classe 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. Pour tester, on souhaite avoir un filtre qui sélectionne les fichiers dont le nom se termine par une certaine chaîne de caractères. Ecrire une méthode endsWithExtension dans une classe PathFilters qui prend en paramètre une chaîne de caractère et renvoie un PathFilter qui sélectionne les fichier dont le nom se fini par la chaîne de carcatère spécifiée en argument.
    Note: la classe String possède une méthode endsWith.
  3. Modifier la classe PushPathMonitor pour quelle accept aussi un filtre.
Verifier avec les tests unitaires que votre implantation est bien conforme. PollPathMonitorTest2.java et PushPathMonitorTest2.java

Exercice 4 - [A la maison]

On souhaite avoir un main qui démarre le programme de surveillance de répertoire. Voici son synopsis:
        java fr.umlv.file.PathMonitorMain [-poll|-push] [-endsWith argument] directory
          monitor a directory and print on the standard output stream when a file
          is added or deleted.
          
          options: -poll use the PollPathMonitor
                   -push use the PushPathMonitor
                   if neither -poll nor -push are specified on the command line push is used as the default.
                  
                   -endsWith argument only monitor files with a filename that ends with
                    the argument e.g -endsWith ".txt" only montitor text files. 
      
Veillez à ce que votre code soit le plus simple possible !

  1. Dans un premier temps, utiliser un switch sur des strings pour parser les arguments de la ligne de commande.
  2. Même chose mais en utilisant un enum pour représenter les différentes options.