Created
October 13, 2010 19:52
-
-
Save ryankennedy/624761 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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