diff --git a/ivy.xml b/ivy.xml index 53c15d03c..6d580c3cc 100644 --- a/ivy.xml +++ b/ivy.xml @@ -10,5 +10,10 @@ + + + + + diff --git a/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java b/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java index d53638a19..e665e0f0d 100755 --- a/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java +++ b/java/src/org/broadinstitute/sting/gatk/CommandLineGATK.java @@ -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; } diff --git a/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java b/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java index ca378bb94..8836d99f4 100755 --- a/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java +++ b/java/src/org/broadinstitute/sting/gatk/GenomeAnalysisEngine.java @@ -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(); } /** diff --git a/java/src/org/broadinstitute/sting/gatk/WalkerManager.java b/java/src/org/broadinstitute/sting/gatk/WalkerManager.java index 0e84f5884..5d211199b 100755 --- a/java/src/org/broadinstitute/sting/gatk/WalkerManager.java +++ b/java/src/org/broadinstitute/sting/gatk/WalkerManager.java @@ -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> walkersByName; - public WalkerManager(String pluginDirectory) { - try { - List walkerCandidates = new ArrayList(); - - // 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 classFilesInPath = PathUtils.findFilesInPath(extensionPath, "", "class", false); - walkerCandidates.addAll(JVMUtils.loadExternalClasses(extensionPath, classFilesInPath)); - List jarsInPath = PathUtils.findFilesInPath(extensionPath, "", "jar", false); - for( String jarFileName: jarsInPath ) { - File jarFile = new File( extensionPath, jarFileName ); - walkerCandidates.addAll(JVMUtils.loadExternalClassesFromJar(jarFile) ); - } - } - - List> 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> 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 loadClassesFromLocation(File location) - throws IOException { - if (location.getAbsolutePath().endsWith(".jar")) - return JVMUtils.loadInternalClassesFromJar(location); - else { - List 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> filterWalkers(List classes) { - List> walkerClasses = new ArrayList>(); - for( Class clazz: classes ) { - if( JVMUtils.isConcreteImplementationOf(clazz,Walker.class) ) - walkerClasses.add( (Class)clazz ); - } - return walkerClasses; - } - /** * Instantiate the list of walker classes. Add them to the walker hashmap. * diff --git a/java/src/org/broadinstitute/sting/playground/gatk/walkers/variants/VariantFiltrationWalker.java b/java/src/org/broadinstitute/sting/playground/gatk/walkers/variants/VariantFiltrationWalker.java index 08fff4ba4..7d719ca37 100755 --- a/java/src/org/broadinstitute/sting/playground/gatk/walkers/variants/VariantFiltrationWalker.java +++ b/java/src/org/broadinstitute/sting/playground/gatk/walkers/variants/VariantFiltrationWalker.java @@ -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 { @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 featureClasses; - private ArrayList exclusionClasses; + private List> featureClasses; + private List> exclusionClasses; private PrintWriter vwriter; private HashMap ewriters; @@ -143,7 +141,7 @@ public class VariantFiltrationWalker extends LocusWalker { * @param classes an ArrayList of classes * @return String of available classes */ - private String getAvailableClasses(ArrayList classes) { + private String getAvailableClasses(List> classes) { String availableString = ""; for (int classIndex = 0; classIndex < classes.size(); classIndex++) { diff --git a/java/src/org/broadinstitute/sting/playground/somaticcoverage/SomaticCoverageTool.java b/java/src/org/broadinstitute/sting/playground/somaticcoverage/SomaticCoverageTool.java index 2853ce766..e1e1abce6 100644 --- a/java/src/org/broadinstitute/sting/playground/somaticcoverage/SomaticCoverageTool.java +++ b/java/src/org/broadinstitute/sting/playground/somaticcoverage/SomaticCoverageTool.java @@ -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; } diff --git a/java/src/org/broadinstitute/sting/utils/JVMUtils.java b/java/src/org/broadinstitute/sting/utils/JVMUtils.java index 142deddaf..c4d63b08e 100755 --- a/java/src/org/broadinstitute/sting/utils/JVMUtils.java +++ b/java/src/org/broadinstitute/sting/utils/JVMUtils.java @@ -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 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 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 loadInternalClasses(List 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 loadExternalClasses(final File path, List 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 loadClassesFromJar( final File jarFile, final LoadingStrategy loader ) - throws IOException { - List classes = new ArrayList(); - - 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 loadClasses( List classFileNames, LoadingStrategy loader ) - throws IOException { - List classes = new ArrayList(); - - 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()); } } diff --git a/java/src/org/broadinstitute/sting/utils/PackageUtils.java b/java/src/org/broadinstitute/sting/utils/PackageUtils.java index cc99d630c..3ff474686 100755 --- a/java/src/org/broadinstitute/sting/utils/PackageUtils.java +++ b/java/src/org/broadinstitute/sting/utils/PackageUtils.java @@ -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 getClassesImplementingInterface(Class iface) { - try { - final File location = JVMUtils.getLocationFor(iface); - - List potentialClasses = getClassesFromLocation(location); - ArrayList implementingClasses = new ArrayList(); - - 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 List> getClassesImplementingInterface(Class iface) { + // Load all classes implementing the given interface, then filter out any class that isn't concrete. + Set> allTypes = reflections.getSubTypesOf(iface); + List> concreteTypes = new ArrayList>(); + for( Class 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 getClassesFromLocation(File location) throws IOException { - if (location.getAbsolutePath().endsWith(".jar")) - return JVMUtils.loadInternalClassesFromJar(location); - else { - List classFileNames = PathUtils.findFilesInPath(location, "", "class", true); - return JVMUtils.loadInternalClasses(classFileNames); - } + return concreteTypes; } } diff --git a/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java b/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java index 7a1eaf448..b9a00b590 100644 --- a/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java +++ b/java/src/org/broadinstitute/sting/utils/cmdLine/CommandLineProgram.java @@ -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 '; 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); diff --git a/settings/ivysettings.xml b/settings/ivysettings.xml index 5cacb105a..fcfc8fd0f 100644 --- a/settings/ivysettings.xml +++ b/settings/ivysettings.xml @@ -12,5 +12,6 @@ + diff --git a/settings/repository/org.reflections/reflections-0.9.2.jar b/settings/repository/org.reflections/reflections-0.9.2.jar new file mode 100644 index 000000000..c91cffea5 Binary files /dev/null and b/settings/repository/org.reflections/reflections-0.9.2.jar differ diff --git a/settings/repository/org.reflections/reflections-0.9.2.xml b/settings/repository/org.reflections/reflections-0.9.2.xml new file mode 100644 index 000000000..7676d4df8 --- /dev/null +++ b/settings/repository/org.reflections/reflections-0.9.2.xml @@ -0,0 +1,3 @@ + + +