/** * Create a new plugin manager. * * @param pluginType Core type for a plugin. * @param pluginCategory Provides a category name to the plugin. Must not be null. * @param pluginSuffix Provides a suffix that will be trimmed off when converting to a plugin * name. Can be null. * @param classpath Custom class path to search for classes. */ public PluginManager( Class pluginType, String pluginCategory, String pluginSuffix, List<URL> classpath) { this.pluginCategory = pluginCategory; this.pluginSuffix = pluginSuffix; this.plugins = new ArrayList<Class<? extends PluginType>>(); this.interfaces = new ArrayList<Class<? extends PluginType>>(); Reflections reflections; if (classpath == null) { reflections = defaultReflections; } else { addClasspath(classpath); reflections = new Reflections( new ConfigurationBuilder().setUrls(classpath).setScanners(new SubTypesScanner())); } // Load all classes types filtering them by concrete. @SuppressWarnings("unchecked") Set<Class<? extends PluginType>> allTypes = reflections.getSubTypesOf(pluginType); for (Class<? extends PluginType> type : allTypes) { // The plugin manager does not support anonymous classes; to be a plugin, a class must have a // name. if (JVMUtils.isAnonymous(type)) continue; if (JVMUtils.isConcrete(type)) plugins.add(type); else interfaces.add(type); } pluginsByName = new TreeMap<String, Class<? extends PluginType>>(); for (Class<? extends PluginType> pluginClass : plugins) { String pluginName = getName(pluginClass); pluginsByName.put(pluginName, pluginClass); } // sort the plugins so the order of elements is deterministic sortPlugins(plugins); sortPlugins(interfaces); }