mirror of https://github.com/jenkinsci/jenkins.git
147 lines
4.1 KiB
Java
147 lines
4.1 KiB
Java
package hudson;
|
|
|
|
import hudson.model.Hudson;
|
|
import hudson.util.Service;
|
|
import java.util.logging.Level;
|
|
|
|
import javax.servlet.ServletContext;
|
|
import java.io.File;
|
|
import java.io.FilenameFilter;
|
|
import java.io.IOException;
|
|
import java.net.URL;
|
|
import java.util.ArrayList;
|
|
import java.util.Collection;
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
import java.util.logging.Logger;
|
|
|
|
/**
|
|
* Manages {@link PluginWrapper}s.
|
|
*
|
|
* @author Kohsuke Kawaguchi
|
|
*/
|
|
public final class PluginManager {
|
|
/**
|
|
* All discovered plugins.
|
|
*/
|
|
private final List<PluginWrapper> plugins = new ArrayList<PluginWrapper>();
|
|
|
|
/**
|
|
* All active plugins.
|
|
*/
|
|
private final List<PluginWrapper> activePlugins = new ArrayList<PluginWrapper>();
|
|
|
|
/**
|
|
* Plug-in root directory.
|
|
*/
|
|
public final File rootDir;
|
|
|
|
public final ServletContext context;
|
|
|
|
/**
|
|
* {@link ClassLoader} that can load all the publicly visible classes from plugins
|
|
* (and including the classloader that loads Hudson itself.)
|
|
*
|
|
*/
|
|
// implementation is minmal --- just enough to run XStream
|
|
// and load plugin-contributed classes.
|
|
public final ClassLoader uberClassLoader = new UberClassLoader();
|
|
|
|
public PluginManager(ServletContext context) {
|
|
this.context = context;
|
|
rootDir = new File(Hudson.getInstance().getRootDir(),"plugins");
|
|
if(!rootDir.exists())
|
|
rootDir.mkdirs();
|
|
|
|
File[] archives = rootDir.listFiles(new FilenameFilter() {
|
|
public boolean accept(File dir, String name) {
|
|
return name.endsWith(".hpi") // plugin jar file
|
|
|| name.endsWith(".hpl"); // linked plugin. for debugging.
|
|
}
|
|
});
|
|
|
|
if(archives==null) {
|
|
LOGGER.severe("Hudson is unable to create "+rootDir+"\nPerhaps its security privilege is insufficient");
|
|
return;
|
|
}
|
|
for( File arc : archives ) {
|
|
try {
|
|
PluginWrapper p = new PluginWrapper(this, arc);
|
|
plugins.add(p);
|
|
if(p.isActive())
|
|
activePlugins.add(p);
|
|
} catch (IOException e) {
|
|
LOGGER.log(Level.SEVERE, "Failed to load a plug-in " + arc, e);
|
|
}
|
|
}
|
|
}
|
|
|
|
public List<PluginWrapper> getPlugins() {
|
|
return plugins;
|
|
}
|
|
|
|
public PluginWrapper getPlugin(String shortName) {
|
|
for (PluginWrapper p : plugins) {
|
|
if(p.getShortName().equals(shortName))
|
|
return p;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Discover all the service provider implementations of the given class,
|
|
* via <tt>META-INF/services</tt>.
|
|
*/
|
|
public <T> Collection<Class<? extends T>> discover( Class<T> spi ) {
|
|
Set<Class<? extends T>> result = new HashSet<Class<? extends T>>();
|
|
|
|
for (PluginWrapper p : activePlugins) {
|
|
Service.load(spi, p.classLoader, result);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* Orderly terminates all the plugins.
|
|
*/
|
|
public void stop() {
|
|
for (PluginWrapper p : activePlugins) {
|
|
p.stop();
|
|
}
|
|
}
|
|
|
|
private final class UberClassLoader extends ClassLoader {
|
|
public UberClassLoader() {
|
|
super(PluginManager.class.getClassLoader());
|
|
}
|
|
|
|
@Override
|
|
protected Class<?> findClass(String name) throws ClassNotFoundException {
|
|
for (PluginWrapper p : activePlugins) {
|
|
try {
|
|
return p.classLoader.loadClass(name);
|
|
} catch (ClassNotFoundException e) {
|
|
//not found. try next
|
|
}
|
|
}
|
|
// not found in any of the classloader. delegate.
|
|
throw new ClassNotFoundException(name);
|
|
}
|
|
|
|
@Override
|
|
protected URL findResource(String name) {
|
|
for (PluginWrapper p : activePlugins) {
|
|
URL url = p.classLoader.getResource(name);
|
|
if(url!=null)
|
|
return url;
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
|
|
private static final Logger LOGGER = Logger.getLogger(PluginManager.class.getName());
|
|
|
|
}
|