Skip to content

Instantly share code, notes, and snippets.

@ryankennedy
Created October 13, 2010 19:52
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryankennedy/624761 to your computer and use it in GitHub Desktop.
Save ryankennedy/624761 to your computer and use it in GitHub Desktop.
import javax.ws.rs.*;
import java.io.File;
import java.lang.reflect.Method;
import java.net.URISyntaxException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* JAX-RS utility class for locating all JAX-RS resources under a given ClassLoader.
*/
public class ResourceLocator {
/**
* Returns all of the JAX-RS resources under the given ClassLoader, minus any passed in the exclude list.
*
* @param classLoader The ClassLoader instance to search for JAX-RS resources.
* @param excludeList A list of classes to exclude from the returned list.
* @return A list of JAX-RS resource classes suitable for use in a JAX-RS Application instance.
*/
public static List<Class<?>> locateResources(ClassLoader classLoader, Class<?>... excludeList) {
try {
List<Class<?>> resourceClasses = new ArrayList<Class<?>>();
List<File> resources = new ArrayList<File>();
File root = new File(classLoader.getResource("/").toURI());
findClasses(root, resources);
for (File resource : resources) {
try {
String relativePath = resource.getAbsolutePath().substring(root.getAbsolutePath().length() + 1);
String className = relativePath.replace("/", ".").replace(".class", ""); // TODO: Need to use the platform path separator? Substring off the .class instead of using replace.
Class<?> resourceClass = Class.forName(className, false, classLoader);
if (isJaxRsResource(resourceClass)) {
resourceClasses.add(resourceClass);
}
} catch (ClassNotFoundException e) {
System.err.println("Class returned by class loader cannot be found...this shouldn't happen");
}
}
resourceClasses.removeAll(Arrays.asList(excludeList));
return resourceClasses;
} catch (URISyntaxException e) {
throw new RuntimeException("Got a bad resource URI from the class loader...this shouldn't happen.", e);
}
}
/**
* Recursively search the File instance for class files. Add them to the list of flies.
*
* @param file The File to search recursively.
* @param classes The list to add class files to.
*/
private static void findClasses(File file, List<File> classes) {
if (file.isDirectory()) {
for (File child : file.listFiles()) {
if (child.isFile() && child.getName().endsWith(".class")) {
classes.add(child);
} else if (child.isDirectory()) {
findClasses(child, classes);
}
}
}
}
/**
* Checks to see if a given class is a JAX-RS resource according to the 1.1 spec:
*
* "A resource class is a Java class that uses JAX-RS annotations to implement a corresponding Web resource.
* Resource classes are POJOs that have at least one method annotated with @Path or a request method designator."
*
* https://jsr311.dev.java.net/nonav/releases/1.1/spec/spec.html
*
* @param resourceClass The class to check.
* @return True if the class is a JAX-RS resource, false otherwise.
*/
private static boolean isJaxRsResource(Class<?> resourceClass) {
for (Method method : resourceClass.getMethods()) {
if (hasAnnotation(method, Path.class, HttpMethod.class, GET.class, POST.class, PUT.class, DELETE.class, HEAD.class, OPTIONS.class)) {
return true;
}
}
return false;
}
private static boolean hasAnnotation(Method method, Class... annotations) {
for (Class annotation : annotations) {
if (annotation.isAnnotation() && (method.getAnnotation(annotation) != null)) {
return true;
}
}
return false;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment