插件工厂类PluginFactory.java
/** * Constellio, Open Source Enterprise Search * Copyright (C) 2010 DocuLibre inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package com.doculibre.constellio.plugins; import java.io.File; import java.io.FileFilter; import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import java.util.Set; import net.xeoh.plugins.base.PluginManager; import net.xeoh.plugins.base.impl.PluginManagerFactory; import net.xeoh.plugins.base.impl.PluginManagerImpl; import net.xeoh.plugins.base.impl.classpath.ClassPathManager; import net.xeoh.plugins.base.impl.classpath.ClassPathManagerUtils; import net.xeoh.plugins.base.util.PluginManagerUtil; import org.apache.commons.io.FileUtils; import com.doculibre.constellio.plugins.api.ConstellioPlugin; import com.doculibre.constellio.plugins.defaults.DefaultConstellioPlugin; import com.doculibre.constellio.utils.ClasspathUtils; import com.doculibre.constellio.utils.ConstellioSpringUtils; public class PluginFactory { private static Set<ClassLoader> classLoaders = new HashSet<ClassLoader>(); private static PluginManager pm; @SuppressWarnings("unchecked") private static void initPluginManager() { if (pm == null) { pm = PluginManagerFactory.createPluginManager(); File classesDir = ClasspathUtils.getClassesDir(); pm.addPluginsFrom(classesDir.toURI()); File pluginsDir = getPluginsDir(); File[] pluginDirs = pluginsDir.listFiles(new FileFilter() { @Override public boolean accept(File pathname) { boolean accept; if (pathname.isFile()) { accept = false; } else if (DefaultConstellioPlugin.NAME.equals(pathname)) { accept = true; } else { List<String> availablePluginNames = ConstellioSpringUtils.getAvailablePluginNames(); accept = availablePluginNames.contains(pathname.getName()); } return accept; } }); for (File pluginDir : pluginDirs) { // Plugin root dir jars Collection<File> pluginJarFiles = FileUtils.listFiles(pluginDir, new String[] { "jar" }, false); // Accept only one root dir jar File pluginJarFile = pluginJarFiles.isEmpty() ? null : pluginJarFiles.iterator().next(); if (pluginJarFile != null) { URI pluginJarFileURI = pluginJarFile.toURI(); pm.addPluginsFrom(pluginJarFileURI); PluginManagerImpl pmImpl = (PluginManagerImpl) pm; ClassPathManager classPathManager = pmImpl.getClassPathManager(); ClassLoader classLoader = ClassPathManagerUtils.getClassLoader(classPathManager, pluginJarFile); classLoaders.add(classLoader); File pluginLibDir = new File(pluginDir, "lib"); if (pluginLibDir.exists() && pluginLibDir.isDirectory()) { Collection<File> pluginDependencies = FileUtils.listFiles(pluginLibDir, new String[] { "jar" }, false); ClassPathManagerUtils.addJarDependencies(classPathManager, pluginJarFile, pluginDependencies); } } } } } public static <P extends ConstellioPlugin> P getPlugin(Class<P> pluginClass) { return getPlugin(pluginClass, false); } public static <P extends ConstellioPlugin> P getDefaultPlugin(Class<P> pluginClass) { return getPlugin(pluginClass, true); } private static <P extends ConstellioPlugin> P getPlugin(Class<P> pluginClass, boolean onlyDefault) { List<P> matches = getPlugins(pluginClass, onlyDefault); return !matches.isEmpty() ? matches.get(0) : null; } public static <P extends ConstellioPlugin> List<P> getPlugins(Class<P> pluginClass) { return getPlugins(pluginClass, false); } public static <P extends ConstellioPlugin> List<P> getDefaultPlugins(Class<P> pluginClass) { return getPlugins(pluginClass, true); } private static <P extends ConstellioPlugin> List<P> getPlugins(Class<P> pluginClass, boolean onlyDefault) { List<P> matches = new ArrayList<P>(); P defaultPlugin = null; initPluginManager(); PluginManagerUtil pmu = new PluginManagerUtil(pm); for (P impl : pmu.getPlugins(pluginClass)) { // ClassLoader classLoader = impl.getClass().getClassLoader(); // classLoaders.add(classLoader); if (DefaultConstellioPlugin.NAME.equals(impl.getName())) { defaultPlugin = impl; } else if (!onlyDefault) { matches.add(impl); } } if (matches.isEmpty()) { if (defaultPlugin != null) { matches.add(defaultPlugin); } } else { // If many plugins are found, they are sorted in the order they are configured in constellio.xml // (the last has priority over the previous) Collections.sort(matches, new Comparator<ConstellioPlugin>() { @Override public int compare(ConstellioPlugin o1, ConstellioPlugin o2) { List<String> availablePluginNames = ConstellioSpringUtils.getAvailablePluginNames(); Integer indexOfPluginName1 = availablePluginNames.indexOf(o1.getName()); Integer indexOfPluginName2 = availablePluginNames.indexOf(o2.getName()); return indexOfPluginName1.compareTo(indexOfPluginName2); } }); } return matches; } public static File getPluginsDir() { File webinfDir = ClasspathUtils.getWebinfDir(); return new File(webinfDir, "plugins"); } @SuppressWarnings("unchecked") public static boolean isValidPlugin(String name) { boolean validPlugin; File pluginsDir = getPluginsDir(); File pluginDir = new File(pluginsDir, name); if (!pluginDir.exists() || pluginDir.isFile()) { validPlugin = false; } else { Collection<File> pluginJarFiles = FileUtils.listFiles(pluginDir, new String[] { "jar" }, false); // Accept only one root dir jar File pluginJarFile = pluginJarFiles.isEmpty() ? null : pluginJarFiles.iterator().next(); if (pluginJarFile != null) { validPlugin = true; } else { validPlugin = false; } } return validPlugin; } public static Set<ClassLoader> getClassLoaders() { initPluginManager(); return classLoaders; } }
自定义类加载器PluginAwareClassLoader.java
/** * Constellio, Open Source Enterprise Search * Copyright (C) 2010 DocuLibre inc. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package com.doculibre.constellio.plugins; import java.io.IOException; import java.net.URL; import java.util.Enumeration; import java.util.Set; public class PluginAwareClassLoader extends ClassLoader { private ClassLoader defaultClassLoader; public PluginAwareClassLoader() { defaultClassLoader = Thread.currentThread().getContextClassLoader(); while (defaultClassLoader instanceof PluginAwareClassLoader) { PluginAwareClassLoader nested = (PluginAwareClassLoader) defaultClassLoader; defaultClassLoader = nested.getDefaultClassLoader(); } } public ClassLoader getDefaultClassLoader() { return defaultClassLoader; } public void setDefaultClassLoader(ClassLoader defaultClassLoader) { this.defaultClassLoader = defaultClassLoader; } protected Set<ClassLoader> getExtraClassLoaders() { Set<ClassLoader> extraClassLoaders = PluginFactory.getClassLoaders(); extraClassLoaders.add(PluginAwareClassLoader.class.getClassLoader()); return extraClassLoaders; } @Override protected Class<?> findClass(String name) throws ClassNotFoundException { Class<?> clazz; Throwable throwable; try { clazz = defaultClassLoader.loadClass(name); throwable = null; } catch (Throwable t) { clazz = null; throwable = t; } if (clazz == null) { for (ClassLoader extraClassLoader : getExtraClassLoaders()) { try { clazz = extraClassLoader.loadClass(name); if (clazz != null) { break; } } catch (ClassNotFoundException e) { // Ignore, already handled } } } if (clazz == null && throwable != null) { if (throwable instanceof ClassNotFoundException) { throw (ClassNotFoundException) throwable; } else if (throwable instanceof RuntimeException) { throw (RuntimeException) throwable; } else { throw new RuntimeException(throwable); } } return clazz; } @Override protected URL findResource(String name) { URL resource; Throwable throwable; try { resource = defaultClassLoader.getResource(name); throwable = null; } catch (Throwable t) { resource = null; throwable = t; } if (resource == null) { for (ClassLoader extraClassLoader : getExtraClassLoaders()) { resource = extraClassLoader.getResource(name); if (resource != null) { break; } } } if (resource == null && throwable != null) { if (throwable instanceof RuntimeException) { throw (RuntimeException) throwable; } else { throw new RuntimeException(throwable); } } return resource; } @Override protected Enumeration<URL> findResources(String name) throws IOException { Enumeration<URL> resources; Throwable throwable; try { resources = defaultClassLoader.getResources(name); throwable = null; } catch (Throwable t) { resources = null; throwable = t; } if (resources == null) { for (ClassLoader extraClassLoader : getExtraClassLoaders()) { resources = extraClassLoader.getResources(name); if (resources != null) { break; } } } if (resources == null && throwable != null) { if (throwable instanceof IOException) { throw (IOException) throwable; } else if (throwable instanceof RuntimeException) { throw (RuntimeException) throwable; } else { throw new RuntimeException(throwable); } } return resources; } }
插件框架参考 http://www.cnblogs.com/chenying99/archive/2013/04/01/2994529.html