public class FastClasspathScanner extends Object
new FastClasspathScanner(
new String[] { "com.xyz.widget", "com.xyz.gizmo" }) // Whitelisted package prefixes to scan
.matchSubclassesOf(DBModel.class,
// c is a subclass of DBModel
c -> System.out.println("Subclasses DBModel: " + c.getName()))
.matchClassesImplementing(Runnable.class,
// c is a class that implements Runnable
c -> System.out.println("Implements Runnable: " + c.getName()))
.matchClassesWithAnnotation(RestHandler.class,
// c is a class annotated with @RestHandler
c -> System.out.println("Has @RestHandler class annotation: " + c.getName()))
.matchFilenamePattern("^template/.\*\.html",
// templatePath is a path on the classpath that matches the above pattern;
// inputStream is a stream opened on the file or zipfile entry
// No need to close inputStream before exiting, it is closed by caller.
(absolutePath, relativePath, inputStream) -> {
try {
String template = IOUtils.toString(inputStream, "UTF-8");
System.out.println("Found template: " + absolutePath
+ " (size " + template.length() + ")");
} catch (IOException e) {
throw new RuntimeException(e);
}
})
.scan(); // Actually perform the scan
Note that you need to pass a whitelist of package prefixes to scan into the constructor, and the ability
to detect that a class or interface extends another depends upon the entire ancestral path between the two
classes or interfaces having one of the whitelisted package prefixes.
The scanner also records the latest last-modified timestamp of any file or directory encountered, and you
can see if that latest last-modified timestamp has increased (indicating that something on the classpath
has been updated) by calling:
boolean classpathContentsModified = fastClassPathScanner.classpathContentsModifiedSinceScan();
This can be used to enable dynamic class-reloading if something on the classpath is updated, for example
to support hot-replace of route handler classes in a webserver. The above call is several times faster
than the original call to scan(), since only modification timestamps need to be checked.
Hosted at: https://github.com/lukehutch/fast-classpath-scanner
Inspired by: https://github.com/rmuller/infomas-asl/tree/master/annotation-detector
See also: http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4
Let me know if you find this useful!| Modifier and Type | Class and Description |
|---|---|
static interface |
FastClasspathScanner.ClassAnnotationMatchProcessor
The method to run when a class with the right matching annotation is found on the classpath.
|
static interface |
FastClasspathScanner.FileMatchProcessor
The method to run when a matching file is found on the classpath.
|
static interface |
FastClasspathScanner.InterfaceMatchProcessor<T>
The method to run when a class implementing a specific interface is found on the classpath.
|
static interface |
FastClasspathScanner.SubclassMatchProcessor<T>
The method to run when a subclass of a specific class is found on the classpath.
|
| Constructor and Description |
|---|
FastClasspathScanner(String[] pacakagesToScan)
Initialize a classpath scanner, with a list of package prefixes to scan.
|
| Modifier and Type | Method and Description |
|---|---|
boolean |
classpathContentsModifiedSinceScan()
Returns true if the classpath contents have been changed since scan() was last called.
|
static ArrayList<File> |
getUniqueClasspathElements()
Get a list of unique elements on the classpath as File objects, preserving order.
|
<T> FastClasspathScanner |
matchClassesImplementing(Class<T> iface,
FastClasspathScanner.InterfaceMatchProcessor<T> interfaceMatchProcessor)
Call the given ClassMatchProcessor if classes are found on the classpath that implement the specified
interface.
|
FastClasspathScanner |
matchClassesWithAnnotation(Class<?> annotation,
FastClasspathScanner.ClassAnnotationMatchProcessor classMatchProcessor)
Call the given ClassMatchProcessor if classes are found on the classpath that have the given
annotation.
|
FastClasspathScanner |
matchFilenamePattern(String filenameMatchPattern,
FastClasspathScanner.FileMatchProcessor fileMatchProcessor)
Call the given FileMatchProcessor if files are found on the classpath with the given regex pattern in
their path.
|
<T> FastClasspathScanner |
matchSubclassesOf(Class<T> superclass,
FastClasspathScanner.SubclassMatchProcessor<T> classMatchProcessor)
Call the given ClassMatchProcessor if classes are found on the classpath that extend the specified
superclass.
|
void |
scan()
Scan classpath for matching files.
|
public FastClasspathScanner(String[] pacakagesToScan)
pacakagesToScan - A list of package prefixes to scan.public <T> FastClasspathScanner matchSubclassesOf(Class<T> superclass, FastClasspathScanner.SubclassMatchProcessor<T> classMatchProcessor)
superclass - The superclass to match (i.e. the class that subclasses need to extend to match).classMatchProcessor - the ClassMatchProcessor to call when a match is found.public <T> FastClasspathScanner matchClassesImplementing(Class<T> iface, FastClasspathScanner.InterfaceMatchProcessor<T> interfaceMatchProcessor)
iface - The interface to match (i.e. the interface that classes need to implement to match).interfaceMatchProcessor - the ClassMatchProcessor to call when a match is found.public FastClasspathScanner matchClassesWithAnnotation(Class<?> annotation, FastClasspathScanner.ClassAnnotationMatchProcessor classMatchProcessor)
annotation - The class annotation to match.classMatchProcessor - the ClassMatchProcessor to call when a match is found.public FastClasspathScanner matchFilenamePattern(String filenameMatchPattern, FastClasspathScanner.FileMatchProcessor fileMatchProcessor)
filenameMatchPattern - The regex to match, e.g. "app/templates/.\*\.html"fileMatchProcessor - The FileMatchProcessor to call when each match is found.public static ArrayList<File> getUniqueClasspathElements()
public void scan()
public boolean classpathContentsModifiedSinceScan()
Copyright © 2014. All rights reserved.