Solution for two common tasks: finding files on file system and finding classes (or resources) on class path.
Jodd integrates two JDK file filtering interfaces FileFilter and FilenameFilter into one: FileFilterEx. There is also default base (abstract) implementation for new interface, FileFilterBase that works as adapter to both JDK filters.
Furthermore, Jodd offers two most common FileFilterEx implementations: RegExpFileFilter and WildcardFileFilter. They provides filtering using regular expression (slower) and wildcards (faster), respectively.
FileFilterEx implementations may be used in File.list() and File.listFiles().
Using just JDK file filtering is not powerful as it should be. Following is missing:
String or File array, it is not possible to perform files manipulation during the search, without allocation of the array (i.e. incremental search). This may be a problem for large number of files.Jodd answers these problems with FindFile.
FindFile helps in every-day work: it searches path(s) for files and folders. FindFile is configurable: it is possible to choose to perform recursive search for files and/or folders on one or more paths, as well as to choose if subfolders should be examined before files and so on. FindFile offers incremental search, so resulting files may be examined during the search.
Subclasses of FindFile provide various matching mechanisms. Fastest and, probably, most used one is WildcardFindFile - it uses wildcard patterns for matching files. Besides wildcards, available are: RegExpFindFile and FilterFindFile.
FindFile and its derivates works incrementally and have to be used in the loop. Here is one simple example that finds all files on some path:
FindFile ff = new WildcardFindFile("*")
.recursive(true)
.includeDirs(true)
.searchPath("/some/path");
File f;
while ((f = ff.nextFile()) != null) {
if (f.isDirectory() == true) {
System.out.println(". >" + f.getName());
} else {
System.out.println(". " + f.getName());
}
}
Another approach is to have callback handler for each founded file. Abstract class FilepathScanner provides callback method onFile. Usage is quite simple:
FilepathScanner fs = new FilepathScanner() {
@Override
protected void onFile(File file) {
System.out.println(file.getName());
}
}.includeDirs(true).recursive(true).includeFiles(false);
fs.scan("d:\\temp\\");
This example prints folders names of all folders (and not only direct subfolders) under the provided root.
Finding a class or a resource on classpath is special case of finding files. Jodd provides abstract class FindClass that contains internal logic (based on FindFile) for finding classes and resources on provided classpath. FindClass is able to scan JARs, filter entities by including and/or excluding some and so on. When matched class or resource (i.e. entry) is found, callback method is invoked.
Besides locating classes and resources, FindClass may open it's input stream by using InputStreamProvider that is passed to callback method, so callback method may read actual content of class or resource. Once opened, InputStream does not have to be closed in callback method, since FindClass does that.
FindClass is supposed to be used by some configurator, therefore not all methods are made public. FindClass is used internally by Jodd frameworks, for automatic configurations.
For more convenient on-place usage, there is ClasspathScanner. It extends FindClass and offers some public scanning methods and fluent interface. Here is the usage example:
ClasspathScanner cs = new ClasspathScanner() {
@Override
protected void onClassName(EntryData entryData) {
InputStream inputStream = entryData.openInputStream();
byte[] bytes = StreamUtil.readAvailableBytes(inputStream);
System.out.println("---> " + entryData.getName() + ':' + entryData.getArchiveName() + "\t\t" + bytes.length);
}
};
cs.includeResources(true).scan("/some/classpath");