package cz.cuni.lf1.lge.ThunderSTORM; import cz.cuni.lf1.lge.ThunderSTORM.results.PostProcessingModule; import ij.IJ; import java.net.URL; import java.net.URLConnection; import java.util.*; /** * A class for loading modules at runtime. */ public class ModuleLoader { /** * Loads implementations of sublcasses of IModule interface. It uses the * imagej plugin classloader, so it looks for implementations in the imagej * plugin directory. For the module to be loaded, you must place a jar with * an implementation of one of the subclasses of IModule. The jar must * contain, in the folder META-INF/services, a file named after the full * name of the implemented interface (for example * cz.cuni.lf1.lge.ThunderSTORM.detectors.IDetector) and the content of the * file is full names of the classes implementing the interface. Each on a * separate line. The file must be in UTF-8 (without BOM!) See * {@link ServiceLoader} for more details. * * <br/> * The implementation must provide a no-arguments constructor so the module * can be instantiated. * * If there is an error while loading a module, the error is logged and the * method attempts to continue loading other modules. Exception is thrown * only when no modules are succesfully loaded. * * @return a list of instances of the specified class (instantiated by the * no-args constructor) * @throws RuntimeException if no modules were loaded. */ public static <T extends IModuleUI> ArrayList<T> getUIModules(Class<T> c) { //workaround a bug when service loading does not work after refreshing menus in ImageJ boolean oldUseCaching = setUseCaching(false); ArrayList<T> retval = new ArrayList<T>(); try { ServiceLoader loader = ServiceLoader.load(c, IJ.getClassLoader()); for(Iterator<T> it = loader.iterator(); it.hasNext();) { //when something goes wrong while loading modules, log the error and try to continue try { retval.add(it.next()); } catch(ServiceConfigurationError e) { IJ.handleException(e); } } } catch(Throwable e) { IJ.handleException(e); } finally { setUseCaching(oldUseCaching); } if(retval.isEmpty()) { //throw exception only when no modules are succesfully loaded throw new RuntimeException("No modules of type " + c.getSimpleName() + " loaded."); } return retval; } public static <T extends IModule> ArrayList<T> getModules(Class<T> c) { //workaround a bug when service loading does not work after refreshing menus in ImageJ boolean oldUseCaching = setUseCaching(false); ArrayList<T> retval = new ArrayList<T>(); try { ServiceLoader loader = ServiceLoader.load(c, IJ.getClassLoader()); for(Iterator<T> it = loader.iterator(); it.hasNext();) { //when something goes wrong while loading modules, log the error and try to continue try { retval.add(it.next()); } catch(ServiceConfigurationError e) { IJ.handleException(e); } } } catch(Throwable e) { IJ.handleException(e); } finally { setUseCaching(oldUseCaching); } if(retval.isEmpty()) { //throw exception only when no modules are succesfully loaded throw new RuntimeException("No modules of type " + c.getSimpleName() + " loaded."); } return retval; } public static List<PostProcessingModule> getPostProcessingModules() { //workaround a bug when service loading does not work after refreshing menus in ImageJ boolean oldUseCaching = setUseCaching(false); List<PostProcessingModule> retval = new ArrayList<PostProcessingModule>(); try { ServiceLoader loader = ServiceLoader.load(PostProcessingModule.class, IJ.getClassLoader()); for(Iterator<PostProcessingModule> it = loader.iterator(); it.hasNext();) { //when something goes wrong while loading modules, log the error and try to continue try { retval.add(it.next()); } catch(ServiceConfigurationError e) { IJ.handleException(e); } } } catch(Throwable e) { IJ.handleException(e); } finally { setUseCaching(oldUseCaching); } if(retval.isEmpty()) { //throw exception only when no modules are succesfully loaded throw new RuntimeException("No modules of type " + PostProcessingModule.class.getSimpleName() + " loaded."); } return retval; } /** * Enables or disables caching for URLConnection. * * @return the value of useCaching before this call */ public static boolean setUseCaching(boolean useCache) { try { URLConnection URLConnection = new URL("http://localhost/").openConnection(); boolean oldValue = URLConnection.getDefaultUseCaches(); URLConnection.setDefaultUseCaches(useCache); return oldValue; } catch(Exception ex) { return true; } } public static <T extends IModuleUI> T moduleByName(List<T> knownModules, String name) { for(IModuleUI module : knownModules) { if(module.getName().equals(name)) { return (T) module; } } return null; } public static <T extends IModuleUI> int moduleIndexByName(List<T> knownModules, String name) { for(int i = 0; i < knownModules.size(); i++) { if(knownModules.get(i).getName().equals(name)) { return i; } } return 0; } }