Exemple de recherche simple avec VFS

Dans cette partie nous allons détailler un fonctionnalité avancée de VFS qui permet d'effectuer une recherche de fichier selon différents critères.

L'API VFS offre en effet certaines possibilités intéressantes concernant la recherche.
Par exemple, elle permet de faire une recherche sur n'importe quel type de systèmes de fichiers avec la même interface.
Par ailleurs l'API utilise un système de cache local qui permet de réduire considérablement le temps des recherche suivantes sur le même système de fichiers. En effet, lors d'une première recherche, l'API parcours une arborescence et enregistre certaines données, concernant les fichiers en cours d'examination, dans un fichier temporaire. Ce fichier sert alors de cache pour les recherches suivantes.
De cette manière, les recherches que l'on effectue après cette mise en cache (sur le même système de fichiers) sont quasiment instantanées.

Problèmes liés au cache

Ce système comporte une limitation non négligeable. En effet, la gestion du cache par l'API VFS est encore assez limité. Par exemple il n'existe aucun mécanisme permettant de supprimer ou de modifier un fichier qui se trouve dans le cache. Cela pose un gros problème : admettons que l'utilisateur souhaite supprimer un fichier nommé 'toto.txt'. Il ne sait pas ou se trouve ce fichier et effectue une recherche. Après avoir trouvé l'emplacement du fichier, l'utilisateur le supprime. Si l'utilisateur effectue une seconde recherche sur les même répertoires que précédemment, le fichier toto.txt se trouvera encore dans le cache alors qu'il n'existe plus physiquement.

Principe de fonctionnement

L'utilisation de l'API VFS pour la recherche est effectivement très simple. Il suffit pour cela d'implémenter une interface nommée FileSelector.
L'interface FileSelector propose deux méthodes à implémenter :

boolean includeFile(FileSelectInfo fileinfo);

Cette méthode permet de valider si oui ou non le fichier contenu dans l'interface FileSelectInfo correspond aux critères de recherche. Dans ce cas, on doit retourner la valeur booléenne true, de manière à sélectionner le fichier.

boolean traverseDescendents(FileSelectInfo fileinfo);

Cette méthode permet de savoir si l'on descend ou non dans l'arborescence de ce repértoire pour la recherche. Pour effectuer une recherche récursive, il suffit de retourner la valeur booléenne true.

Cette interface est utilisée par la méthode findFiles( FileSelector searchSelector) de la classe FileObject. Cette méthode retourne un tableau de FileObject permettant d'obtenir les fichiers correspondant à la recherche.

Un peu de code ...

Voici un exemple de classe implantant l'interface FileSelector et permettant d'effectuer une recherche (récursive ou non) par nom et/ou extension.

Une archive zip contenant un exemple complet de recherche VFS avec une fenêtre de dialogue en SWT est disponible ICI.

public class MyFileSelector implements FileSelector {

/*
* @see org.apache.commons.vfs.FileSelector#includeFile(org.apache.commons.vfs.FileSelectInfo)
*/
private String fileToSearch;
private String extToSearch;
private boolean recursiveSearch;
private String startDirectory;

public MyFileSelector(String startDirectory,boolean recursiveSearch,String fileToSearch,String extToSearch){
this.recursiveSearch = recursiveSearch;
this.fileToSearch = fileToSearch;
this.extToSearch = extToSearch;
this.startDirectory = startDirectory;
}

public boolean includeFile(FileSelectInfo arg0) throws Exception {
boolean ok = false;
if(fileToSearch!=null){
if(arg0.getFile().getName().getBaseName().toLowerCase().indexOf(fileToSearch.toLowerCase())!=-1) {
ok = true;
}
else return false;
}
if(extToSearch!=null){
if(arg0.getFile().getName().getExtension().equalsIgnoreCase(extToSearch)) {
ok = true;
}
else return false;
}
return ok;
}

/*
* @see org.apache.commons.vfs.FileSelector#traverseDescendents(org.apache.commons.vfs.FileSelectInfo)
*/
public boolean traverseDescendents(FileSelectInfo arg0) throws Exception {
if(recursiveSearch==true) {
return recursiveSearch;
}
else {
FileSelector nonRecursiveSelector = Selectors.SELECT_SELF_AND_CHILDREN;
return nonRecursiveSelector.traverseDescendents(arg0);
}
}

}

Flavien Bach