Switched to Reflections (http://code.google.com/p/reflections/) project for
inspecting the source tree and loading walkers, rather than trying to roll our own by hand. git-svn-id: file:///humgen/gsa-scr1/gsa-engineering/svn_contents/trunk@1286 348d0f76-0448-11de-a6fe-93d51630548a
This commit is contained in:
parent
436a196e2b
commit
b43925c01e
5
ivy.xml
5
ivy.xml
|
|
@ -10,5 +10,10 @@
|
|||
<dependency org="jboss" name="javassist" rev="3.7.ga" />
|
||||
<dependency org="org.simpleframework" name="simple-xml" rev="2.0.4" />
|
||||
<dependency org="org.apache.bcel" name="bcel" rev="5.2" />
|
||||
|
||||
<!-- Dependencies for reflections mvn repository -->
|
||||
<dependency org="org.reflections" name="reflections" rev="0.9.2" />
|
||||
<dependency org="com.google.collections" name="google-collections" rev="0.9" />
|
||||
|
||||
</dependencies>
|
||||
</ivy-module>
|
||||
|
|
|
|||
|
|
@ -42,9 +42,6 @@ public class CommandLineGATK extends CommandLineExecutable {
|
|||
@Argument(fullName = "analysis_type", shortName = "T", doc = "Type of analysis to run")
|
||||
private String analysisName = null;
|
||||
|
||||
@Argument(fullName = "plugin_path", doc = "Which path will the GATK search for plugin walkers.", required = false)
|
||||
private String pluginPath = null;
|
||||
|
||||
// our argument collection, the collection of command line args we accept
|
||||
@ArgumentCollection
|
||||
private GATKArgumentCollection argCollection = new GATKArgumentCollection();
|
||||
|
|
@ -72,7 +69,7 @@ public class CommandLineGATK extends CommandLineExecutable {
|
|||
@Override
|
||||
protected GenomeAnalysisEngine getGATKEngine() {
|
||||
if( GATKEngine == null )
|
||||
GATKEngine = new GenomeAnalysisEngine( pluginPath );
|
||||
GATKEngine = new GenomeAnalysisEngine();
|
||||
return GATKEngine;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,10 +70,10 @@ public class GenomeAnalysisEngine {
|
|||
* new MicroScheduler class we'll be able to delete that function.
|
||||
*
|
||||
*/
|
||||
public GenomeAnalysisEngine( String pluginPathName ) {
|
||||
public GenomeAnalysisEngine() {
|
||||
// make sure our instance variable points to this analysis engine
|
||||
instance = this;
|
||||
walkerManager = new WalkerManager(pluginPathName);
|
||||
walkerManager = new WalkerManager();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -1,19 +1,12 @@
|
|||
package org.broadinstitute.sting.gatk;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
|
||||
import org.broadinstitute.sting.gatk.walkers.*;
|
||||
import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedDatum;
|
||||
import org.broadinstitute.sting.gatk.refdata.ReferenceOrderedData;
|
||||
import org.broadinstitute.sting.utils.JVMUtils;
|
||||
import org.broadinstitute.sting.utils.PathUtils;
|
||||
import org.broadinstitute.sting.utils.StingException;
|
||||
import org.broadinstitute.sting.utils.PackageUtils;
|
||||
import org.apache.log4j.Logger;
|
||||
import net.sf.picard.filter.SamRecordFilter;
|
||||
|
||||
|
|
@ -33,42 +26,9 @@ public class WalkerManager {
|
|||
|
||||
private Map<String, Class<? extends Walker>> walkersByName;
|
||||
|
||||
public WalkerManager(String pluginDirectory) {
|
||||
try {
|
||||
List<Class> walkerCandidates = new ArrayList<Class>();
|
||||
|
||||
// Load all classes that live in this jar.
|
||||
final File location = JVMUtils.getLocationFor( getClass() );
|
||||
walkerCandidates.addAll(loadClassesFromLocation(location));
|
||||
|
||||
// Load all classes that live in the extension path.
|
||||
if (pluginDirectory == null)
|
||||
pluginDirectory = location.getParent() + File.separator + "walkers";
|
||||
logger.info("plugin directory: " + pluginDirectory);
|
||||
|
||||
File extensionPath = new File(pluginDirectory);
|
||||
if (extensionPath.exists()) {
|
||||
List<String> classFilesInPath = PathUtils.findFilesInPath(extensionPath, "", "class", false);
|
||||
walkerCandidates.addAll(JVMUtils.loadExternalClasses(extensionPath, classFilesInPath));
|
||||
List<String> jarsInPath = PathUtils.findFilesInPath(extensionPath, "", "jar", false);
|
||||
for( String jarFileName: jarsInPath ) {
|
||||
File jarFile = new File( extensionPath, jarFileName );
|
||||
walkerCandidates.addAll(JVMUtils.loadExternalClassesFromJar(jarFile) );
|
||||
}
|
||||
}
|
||||
|
||||
List<Class<? extends Walker>> walkers = filterWalkers(walkerCandidates);
|
||||
|
||||
if (walkerCandidates.isEmpty())
|
||||
throw new RuntimeException("No walkers were found.");
|
||||
|
||||
walkersByName = createWalkerDatabase(walkers);
|
||||
}
|
||||
// IOExceptions here are suspect; they indicate that the WalkerManager can't open its containing jar.
|
||||
// Wrap in a RuntimeException.
|
||||
catch (IOException ex) {
|
||||
throw new RuntimeException(ex);
|
||||
}
|
||||
public WalkerManager() {
|
||||
List<Class<? extends Walker>> walkers = PackageUtils.getClassesImplementingInterface(Walker.class);
|
||||
walkersByName = createWalkerDatabase(walkers);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -206,38 +166,6 @@ public class WalkerManager {
|
|||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load classes internal to the classpath from an arbitrary location.
|
||||
*
|
||||
* @param location Location from which to load classes.
|
||||
* @return List of classes.
|
||||
* @throws IOException Problem occurred reading classes.
|
||||
*/
|
||||
private List<Class> loadClassesFromLocation(File location)
|
||||
throws IOException {
|
||||
if (location.getAbsolutePath().endsWith(".jar"))
|
||||
return JVMUtils.loadInternalClassesFromJar(location);
|
||||
else {
|
||||
List<String> classFileNames = PathUtils.findFilesInPath(location, "", "class", true);
|
||||
return JVMUtils.loadInternalClasses(classFileNames);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a list of classes, return a list of those classes which extend from the Walker base interface.
|
||||
*
|
||||
* @param classes Arbitrary list of classes.
|
||||
* @return List of classes extending from Walker.
|
||||
*/
|
||||
private List<Class<? extends Walker>> filterWalkers(List<Class> classes) {
|
||||
List<Class<? extends Walker>> walkerClasses = new ArrayList<Class<? extends Walker>>();
|
||||
for( Class clazz: classes ) {
|
||||
if( JVMUtils.isConcreteImplementationOf(clazz,Walker.class) )
|
||||
walkerClasses.add( (Class<? extends Walker>)clazz );
|
||||
}
|
||||
return walkerClasses;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiate the list of walker classes. Add them to the walker hashmap.
|
||||
*
|
||||
|
|
|
|||
|
|
@ -16,9 +16,7 @@ import org.broadinstitute.sting.playground.gatk.walkers.variants.*;
|
|||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* VariantFiltrationWalker applies specified conditionally independent features to pre-called variants, thus modifying
|
||||
|
|
@ -33,8 +31,8 @@ public class VariantFiltrationWalker extends LocusWalker<Integer, Integer> {
|
|||
@Argument(fullName="list", shortName="ls", doc="List the available features and exclusion criteria and exit") public Boolean LIST = false;
|
||||
@Argument(fullName="truth", shortName="truth", doc="Operate on truth set only") public Boolean TRUTH = false;
|
||||
|
||||
private ArrayList<Class> featureClasses;
|
||||
private ArrayList<Class> exclusionClasses;
|
||||
private List<Class<? extends IndependentVariantFeature>> featureClasses;
|
||||
private List<Class<? extends VariantExclusionCriterion>> exclusionClasses;
|
||||
private PrintWriter vwriter;
|
||||
private HashMap<String, PrintWriter> ewriters;
|
||||
|
||||
|
|
@ -143,7 +141,7 @@ public class VariantFiltrationWalker extends LocusWalker<Integer, Integer> {
|
|||
* @param classes an ArrayList of classes
|
||||
* @return String of available classes
|
||||
*/
|
||||
private String getAvailableClasses(ArrayList<Class> classes) {
|
||||
private <T> String getAvailableClasses(List<Class<? extends T>> classes) {
|
||||
String availableString = "";
|
||||
|
||||
for (int classIndex = 0; classIndex < classes.size(); classIndex++) {
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ public class SomaticCoverageTool extends CommandLineExecutable {
|
|||
@Override
|
||||
protected GenomeAnalysisEngine getGATKEngine() {
|
||||
if( GATKEngine == null )
|
||||
GATKEngine = new GenomeAnalysisEngine( null );
|
||||
GATKEngine = new GenomeAnalysisEngine();
|
||||
return GATKEngine;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,14 +1,5 @@
|
|||
package org.broadinstitute.sting.utils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.FileInputStream;
|
||||
import java.util.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.jar.JarInputStream;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.lang.reflect.Modifier;
|
||||
|
||||
/**
|
||||
|
|
@ -26,189 +17,14 @@ public class JVMUtils {
|
|||
*/
|
||||
private JVMUtils() { }
|
||||
|
||||
/**
|
||||
* Determines which location contains the specified class.
|
||||
*
|
||||
* @return Location (either jar file or directory) of path containing class.
|
||||
*/
|
||||
public static File getLocationFor( Class clazz ) throws IOException {
|
||||
try {
|
||||
java.net.URI locationURI = clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
|
||||
return new File(locationURI);
|
||||
}
|
||||
catch (java.net.URISyntaxException ex) {
|
||||
// a URISyntaxException here must be an IO error; wrap as such.
|
||||
throw new IOException(ex);
|
||||
}
|
||||
catch ( NullPointerException ne ) {
|
||||
throw new IOException("Can not extract code source location for "+clazz.getName());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads concrete classes from a jar which are both in the same package or 'sub-package' of baseClass,
|
||||
* and which extend from baseClass. Loaded classes must already be on the classpath.
|
||||
*
|
||||
* @param jarFile The jar file to search.
|
||||
* @return A list of classes derived from baseClass.
|
||||
*/
|
||||
public static List<Class> loadInternalClassesFromJar(final File jarFile)
|
||||
throws IOException {
|
||||
return loadClassesFromJar( jarFile, new InternalLoadingStrategy() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads concrete classes from a jar which are both in the same package or 'sub-package' of baseClass,
|
||||
* and which extend from baseClass. Loaded classes can be outside of the current classpath.
|
||||
*
|
||||
* @param jarFile The jar file to search.
|
||||
* @return A list of classes derived from baseClass.
|
||||
*/
|
||||
public static List<Class> loadExternalClassesFromJar(final File jarFile)
|
||||
throws IOException {
|
||||
return loadClassesFromJar( jarFile, new ExternalLoadingStrategy(jarFile) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a list of classes currently on the classpath.
|
||||
*
|
||||
* @param classFileNames List of files representing classes.
|
||||
* @return class objects.
|
||||
* @throws IOException Unable to open any of the found classes.
|
||||
*/
|
||||
public static List<Class> loadInternalClasses(List<String> classFileNames)
|
||||
throws IOException {
|
||||
return loadClasses( classFileNames, new InternalLoadingStrategy() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Load loose classes, external to the classloader, from the specified directory.
|
||||
*
|
||||
* @param path source path from which to load classes.
|
||||
* @return A list of all loose classes contained in the path directory.
|
||||
*/
|
||||
public static List<Class> loadExternalClasses(final File path, List<String> classFileNames)
|
||||
throws IOException {
|
||||
return loadClasses( classFileNames, new ExternalLoadingStrategy( path ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a filename of the form a/b/c.class to a.b.c. Makes no assurances about whether the
|
||||
* class is valid on any classloader.
|
||||
*
|
||||
* @param fileName Filename to convert.
|
||||
* @return classname represented by that file.
|
||||
*/
|
||||
public static String fileNameToClassName(String fileName) {
|
||||
return fileName.substring(0, fileName.lastIndexOf(".class")).replace('/', '.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the specified class a concrete implementation of baseClass?
|
||||
* @param clazz Class to check.
|
||||
* @param baseClass Base class to check against.
|
||||
* @return True if clazz implements baseClass and is not abstract / an interface. False otherwise.
|
||||
* @return True if clazz is concrete. False otherwise.
|
||||
*/
|
||||
public static boolean isConcreteImplementationOf( Class clazz, Class baseClass ) {
|
||||
return baseClass.isAssignableFrom(clazz) &&
|
||||
!Modifier.isAbstract(clazz.getModifiers()) &&
|
||||
!Modifier.isInterface(clazz.getModifiers());
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a list of classes from the given jar, using the provided loading strategy.
|
||||
* @param jarFile Jar file from which to load.
|
||||
* @param loader Dictates how these classes should be loaded.
|
||||
* @return A list of loaded classes.
|
||||
* @throws IOException In case there's an IO error trying to load the jar.
|
||||
*/
|
||||
private static List<Class> loadClassesFromJar( final File jarFile, final LoadingStrategy loader )
|
||||
throws IOException {
|
||||
List<Class> classes = new ArrayList<Class>();
|
||||
|
||||
JarInputStream jarInputStream = new JarInputStream(new FileInputStream(jarFile));
|
||||
|
||||
try {
|
||||
JarEntry jarEntry = jarInputStream.getNextJarEntry();
|
||||
|
||||
while (jarEntry != null) {
|
||||
String jarEntryName = jarEntry.getName();
|
||||
if (jarEntryName.endsWith(".class")) {
|
||||
String className = fileNameToClassName(jarEntryName);
|
||||
classes.add( loader.load( className ) );
|
||||
}
|
||||
jarEntry = jarInputStream.getNextJarEntry();
|
||||
}
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// A ClassNotFoundException here must be an IO error; wrap as such.
|
||||
throw new IOException(ex);
|
||||
}
|
||||
finally {
|
||||
jarInputStream.close();
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a list of classes, using the provided loading strategy.
|
||||
* @param classFileNames Which class files to load.
|
||||
* @param loader Dictates how these classes should be loaded.
|
||||
* @return A list of loaded classes.
|
||||
* @throws IOException In case there's an IO error trying to load the jar.
|
||||
*/
|
||||
private static List<Class> loadClasses( List<String> classFileNames, LoadingStrategy loader )
|
||||
throws IOException {
|
||||
List<Class> classes = new ArrayList<Class>();
|
||||
|
||||
for (String classFileName : classFileNames) {
|
||||
String className = fileNameToClassName(classFileName);
|
||||
try {
|
||||
classes.add( loader.load( className ) );
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
// A ClassNotFoundException here must be an IO error; wrap as such.
|
||||
throw new IOException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* What mechanism should we use for loading a list of classes?
|
||||
*/
|
||||
private static interface LoadingStrategy {
|
||||
Class load( String className ) throws ClassNotFoundException;
|
||||
}
|
||||
|
||||
/**
|
||||
* An internal loading strategy, for loading classes already on the classpath.
|
||||
*/
|
||||
private static class InternalLoadingStrategy implements LoadingStrategy {
|
||||
public Class load( String className )
|
||||
throws ClassNotFoundException {
|
||||
return Class.forName( className );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* An external loading strategy, for loading classes not necessarily already
|
||||
* on the classpath.
|
||||
*/
|
||||
private static class ExternalLoadingStrategy implements LoadingStrategy {
|
||||
private final ClassLoader classLoader;
|
||||
|
||||
public ExternalLoadingStrategy( final File jarFile ) throws IOException {
|
||||
URL pathURL = jarFile.toURI().toURL();
|
||||
classLoader = new URLClassLoader(new URL[]{pathURL});
|
||||
}
|
||||
|
||||
public Class load( String className ) throws ClassNotFoundException {
|
||||
return classLoader.loadClass(className);
|
||||
}
|
||||
public static boolean isConcrete( Class clazz ) {
|
||||
return !Modifier.isAbstract(clazz.getModifiers()) &&
|
||||
!Modifier.isInterface(clazz.getModifiers());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,56 +1,55 @@
|
|||
package org.broadinstitute.sting.utils;
|
||||
|
||||
import java.util.List;
|
||||
import org.reflections.Reflections;
|
||||
import org.reflections.scanners.SubTypesScanner;
|
||||
import org.reflections.util.AbstractConfiguration;
|
||||
import org.reflections.util.ClasspathHelper;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.ArrayList;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* PackageUtils contains some useful methods for package introspection.
|
||||
*/
|
||||
public class PackageUtils {
|
||||
/**
|
||||
* A reference into our introspection utility.
|
||||
*/
|
||||
private static Reflections reflections = null;
|
||||
|
||||
static {
|
||||
// Initialize general-purpose source tree reflector.
|
||||
reflections = new Reflections( new AbstractConfiguration() {
|
||||
{
|
||||
setUrls(ClasspathHelper.getUrlsForCurrentClasspath());
|
||||
setScanners(new SubTypesScanner());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Private constructor. No instantiating this class!
|
||||
*/
|
||||
private PackageUtils() {}
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the classes that implement the specified interface.
|
||||
*
|
||||
* @param iface the interface which returned classes should implement.
|
||||
* @return the list of classes that implement the interface. How is that not clear by now?!!!!111one!!
|
||||
* @return the list of classes that implement the interface.
|
||||
*/
|
||||
public static ArrayList<Class> getClassesImplementingInterface(Class iface) {
|
||||
try {
|
||||
final File location = JVMUtils.getLocationFor(iface);
|
||||
|
||||
List<Class> potentialClasses = getClassesFromLocation(location);
|
||||
ArrayList<Class> implementingClasses = new ArrayList<Class>();
|
||||
|
||||
for (Class potentialClass : potentialClasses) {
|
||||
if (JVMUtils.isConcreteImplementationOf(potentialClass, iface)) {
|
||||
implementingClasses.add(potentialClass);
|
||||
}
|
||||
}
|
||||
|
||||
return implementingClasses;
|
||||
} catch (IOException e) {
|
||||
throw new StingException(String.format("Unable to inspect package containing '%s'", iface.getName()));
|
||||
public static <T> List<Class<? extends T>> getClassesImplementingInterface(Class<T> iface) {
|
||||
// Load all classes implementing the given interface, then filter out any class that isn't concrete.
|
||||
Set<Class<? extends T>> allTypes = reflections.getSubTypesOf(iface);
|
||||
List<Class<? extends T>> concreteTypes = new ArrayList<Class<? extends T>>();
|
||||
for( Class<? extends T> type: allTypes ) {
|
||||
if( JVMUtils.isConcrete(type) )
|
||||
concreteTypes.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a list of classes at the specified location
|
||||
* @param location the location where we should start searching (as returned by JVMUtils.getLocationFor(Class))
|
||||
* @return a list of classes at this location
|
||||
* @throws IOException thrown if the jar or directory cannot be inspected
|
||||
*/
|
||||
public static List<Class> getClassesFromLocation(File location) throws IOException {
|
||||
if (location.getAbsolutePath().endsWith(".jar"))
|
||||
return JVMUtils.loadInternalClassesFromJar(location);
|
||||
else {
|
||||
List<String> classFileNames = PathUtils.findFilesInPath(location, "", "class", true);
|
||||
return JVMUtils.loadInternalClasses(classFileNames);
|
||||
}
|
||||
return concreteTypes;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -99,13 +99,7 @@ public abstract class CommandLineProgram {
|
|||
// Default implementation to find a command line that makes sense.
|
||||
// If the user is running from a jar, return '-jar <jarname>'; otherwise
|
||||
// return the full class name.
|
||||
String runningInstructions = null;
|
||||
try {
|
||||
runningInstructions = JVMUtils.getLocationFor( getClass() ).getName();
|
||||
}
|
||||
catch( IOException ex ) {
|
||||
throw new StingException("Unable to determine running instructions", ex);
|
||||
}
|
||||
String runningInstructions = getClass().getName();
|
||||
|
||||
if( runningInstructions.endsWith(".jar") )
|
||||
runningInstructions = String.format("-jar %s", runningInstructions);
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@
|
|||
<module organisation="edu.mit.broad" resolver="projects" />
|
||||
<module organisation="net.sf" module="functionalj" resolver="projects" />
|
||||
<module organisation="net.sf" module="samtools" resolver="projects" />
|
||||
<module organisation="org.reflections" module="reflections" resolver="projects" />
|
||||
</modules>
|
||||
</ivysettings>
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -0,0 +1,3 @@
|
|||
<ivy-module version="1.0">
|
||||
<info organisation="org.reflections" module="reflections" revision="0.9.2" status="release" />
|
||||
</ivy-module>
|
||||
Loading…
Reference in New Issue