org.apache.ibatis.io
Class ResolverUtil<T>

java.lang.Object
  extended by org.apache.ibatis.io.ResolverUtil<T>

public class ResolverUtil<T>
extends java.lang.Object

ResolverUtil is used to locate classes that are available in the/a class path and meet arbitrary conditions. The two most common conditions are that a class implements/extends another class, or that is it annotated with a specific annotation. However, through the use of the ResolverUtil.Test class it is possible to search using arbitrary conditions.

A ClassLoader is used to locate all locations (directories and jar files) in the class path that contain classes within certain packages, and then to load those classes and check them. By default the ClassLoader returned by Thread.currentThread().getContextClassLoader() is used, but this can be overridden by calling setClassLoader(ClassLoader) prior to invoking any of the find() methods.

General searches are initiated by calling the find(org.apache.ibatis.io.ResolverUtil.Test, String) ()} method and supplying a package name and a Test instance. This will cause the named package and all sub-packages to be scanned for classes that meet the test. There are also utility methods for the common use cases of scanning multiple packages for extensions of particular classes, or classes annotated with a specific annotation.

The standard usage pattern for the ResolverUtil class is as follows:

 ResolverUtil<ActionBean> resolver = new ResolverUtil<ActionBean>();
 resolver.findImplementation(ActionBean.class, pkg1, pkg2);
 resolver.find(new CustomTest(), pkg1);
 resolver.find(new CustomTest(), pkg2);
 Collection<ActionBean> beans = resolver.getClasses();
 

Author:
Tim Fennell

Nested Class Summary
static class ResolverUtil.AnnotatedWith
          A Test that checks to see if each class is annotated with a specific annotation.
static class ResolverUtil.IsA
          A Test that checks to see if each class is assignable to the provided class.
static interface ResolverUtil.Test
          A simple interface that specifies how to test classes to determine if they are to be included in the results produced by the ResolverUtil.
 
Constructor Summary
ResolverUtil()
           
 
Method Summary
protected  void addIfMatching(ResolverUtil.Test test, java.lang.String fqn)
          Add the class designated by the fully qualified class name provided to the set of resolved classes if and only if it is approved by the Test supplied.
 ResolverUtil<T> find(ResolverUtil.Test test, java.lang.String packageName)
          Scans for classes starting at the package provided and descending into subpackages.
 ResolverUtil<T> findAnnotated(java.lang.Class<? extends java.lang.annotation.Annotation> annotation, java.lang.String... packageNames)
          Attempts to discover classes that are annotated with the annotation.
 ResolverUtil<T> findImplementations(java.lang.Class<?> parent, java.lang.String... packageNames)
          Attempts to discover classes that are assignable to the type provided.
protected  java.net.URL findJarForResource(java.net.URL url, java.lang.String path)
          Attempts to deconstruct the given URL to find a JAR file containing the resource referenced by the URL.
 java.util.Set<java.lang.Class<? extends T>> getClasses()
          Provides access to the classes discovered so far.
 java.lang.ClassLoader getClassLoader()
          Returns the classloader that will be used for scanning for classes.
protected  java.lang.String getPackagePath(java.lang.String packageName)
          Converts a Java package name to a path that can be looked up with a call to ClassLoader.getResources(String).
protected  boolean isJar(java.net.URL url)
          Returns true if the resource located at the given URL is a JAR file.
protected  boolean isJar(java.net.URL url, byte[] buffer)
          Returns true if the resource located at the given URL is a JAR file.
protected  boolean isRelevantResource(java.lang.String resourceName)
          Returns true if the name of a resource (file or directory) is one that matters in the search for classes.
protected  java.util.List<java.lang.String> listClassResources(java.util.jar.JarInputStream jar, java.lang.String path)
          List the names of the entries in the given JarInputStream that begin with the specified path.
protected  java.util.List<java.lang.String> listClassResources(java.net.URL url, java.lang.String path)
          Recursively list all resources under the given URL that appear to define a Java class.
 void setClassLoader(java.lang.ClassLoader classloader)
          Sets an explicit ClassLoader that should be used when scanning for classes.
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

ResolverUtil

public ResolverUtil()
Method Detail

getClasses

public java.util.Set<java.lang.Class<? extends T>> getClasses()
Provides access to the classes discovered so far. If no calls have been made to any of the find() methods, this set will be empty.

Returns:
the set of classes that have been discovered.

getClassLoader

public java.lang.ClassLoader getClassLoader()
Returns the classloader that will be used for scanning for classes. If no explicit ClassLoader has been set by the calling, the context class loader will be used.

Returns:
the ClassLoader that will be used to scan for classes

setClassLoader

public void setClassLoader(java.lang.ClassLoader classloader)
Sets an explicit ClassLoader that should be used when scanning for classes. If none is set then the context classloader will be used.

Parameters:
classloader - a ClassLoader to use when scanning for classes

findImplementations

public ResolverUtil<T> findImplementations(java.lang.Class<?> parent,
                                           java.lang.String... packageNames)
Attempts to discover classes that are assignable to the type provided. In the case that an interface is provided this method will collect implementations. In the case of a non-interface class, subclasses will be collected. Accumulated classes can be accessed by calling getClasses().

Parameters:
parent - the class of interface to find subclasses or implementations of
packageNames - one or more package names to scan (including subpackages) for classes

findAnnotated

public ResolverUtil<T> findAnnotated(java.lang.Class<? extends java.lang.annotation.Annotation> annotation,
                                     java.lang.String... packageNames)
Attempts to discover classes that are annotated with the annotation. Accumulated classes can be accessed by calling getClasses().

Parameters:
annotation - the annotation that should be present on matching classes
packageNames - one or more package names to scan (including subpackages) for classes

find

public ResolverUtil<T> find(ResolverUtil.Test test,
                            java.lang.String packageName)
Scans for classes starting at the package provided and descending into subpackages. Each class is offered up to the Test as it is discovered, and if the Test returns true the class is retained. Accumulated classes can be fetched by calling getClasses().

Parameters:
test - an instance of ResolverUtil.Test that will be used to filter classes
packageName - the name of the package from which to start scanning for classes, e.g. net.sourceforge.stripes

listClassResources

protected java.util.List<java.lang.String> listClassResources(java.net.URL url,
                                                              java.lang.String path)
                                                       throws java.io.IOException
Recursively list all resources under the given URL that appear to define a Java class. Matching resources will have a name that ends in ".class" and have a relative path such that each segment of the path is a valid Java identifier. The resource paths returned will be relative to the URL and begin with the specified path.

Parameters:
url - The URL of the parent resource to search.
path - The path with which each matching resource path must begin, relative to the URL.
Returns:
A list of matching resources. The list may be empty.
Throws:
java.io.IOException

listClassResources

protected java.util.List<java.lang.String> listClassResources(java.util.jar.JarInputStream jar,
                                                              java.lang.String path)
                                                       throws java.io.IOException
List the names of the entries in the given JarInputStream that begin with the specified path. Entries will match with or without a leading slash.

Parameters:
jar - The JAR input stream
path - The leading path to match
Returns:
The names of all the matching entries
Throws:
java.io.IOException

findJarForResource

protected java.net.URL findJarForResource(java.net.URL url,
                                          java.lang.String path)
                                   throws java.net.MalformedURLException
Attempts to deconstruct the given URL to find a JAR file containing the resource referenced by the URL. That is, assuming the URL references a JAR entry, this method will return a URL that references the JAR file containing the entry. If the JAR cannot be located, then this method returns null.

Parameters:
url - The URL of the JAR entry.
path - The path by which the URL was requested from the class loader.
Returns:
The URL of the JAR file, if one is found. Null if not.
Throws:
java.net.MalformedURLException

getPackagePath

protected java.lang.String getPackagePath(java.lang.String packageName)
Converts a Java package name to a path that can be looked up with a call to ClassLoader.getResources(String).

Parameters:
packageName - The Java package name to convert to a path

isRelevantResource

protected boolean isRelevantResource(java.lang.String resourceName)
Returns true if the name of a resource (file or directory) is one that matters in the search for classes. Relevant resources would be class files themselves (file names that end with ".class") and directories that might be a Java package name segment (java identifiers).

Parameters:
resourceName - The resource name, without path information

isJar

protected boolean isJar(java.net.URL url)
Returns true if the resource located at the given URL is a JAR file.

Parameters:
url - The URL of the resource to test.

isJar

protected boolean isJar(java.net.URL url,
                        byte[] buffer)
Returns true if the resource located at the given URL is a JAR file.

Parameters:
url - The URL of the resource to test.
buffer - A buffer into which the first few bytes of the resource are read. The buffer must be at least the size of JAR_MAGIC. (The same buffer may be reused for multiple calls as an optimization.)

addIfMatching

protected void addIfMatching(ResolverUtil.Test test,
                             java.lang.String fqn)
Add the class designated by the fully qualified class name provided to the set of resolved classes if and only if it is approved by the Test supplied.

Parameters:
test - the test used to determine if the class matches
fqn - the fully qualified name of a class


Copyright © 2010. All Rights Reserved.