提交 a3117648 编写于 作者: K kohsuke

Using AntClassLoader with Closeable so that we can predictably release jar...

Using AntClassLoader with Closeable so that we can predictably release jar files opened by URLClassLoader

git-svn-id: https://hudson.dev.java.net/svn/hudson/trunk/hudson/main@19472 71c3de6d-444a-0410-be80-ed276b4c234a
上级 2dd66726
......@@ -33,15 +33,18 @@ import java.io.FileInputStream;
import java.io.FileReader;
import java.io.FilenameFilter;
import java.io.IOException;
import java.io.Closeable;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.ArrayList;
import java.util.List;
import java.util.Arrays;
import java.util.Collection;
import java.util.jar.Manifest;
import java.util.logging.Logger;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.AntClassLoader;
import org.apache.tools.ant.taskdefs.Expand;
import org.apache.tools.ant.types.FileSet;
......@@ -115,7 +118,7 @@ public class ClassicPluginStrategy implements PluginStrategy {
// TODO: define a mechanism to hide classes
// String export = manifest.getMainAttributes().getValue("Export");
List<URL> paths = new ArrayList<URL>();
List<File> paths = new ArrayList<File>();
if (isLinked) {
parseClassPath(manifest, archive, paths, "Libraries", ",");
parseClassPath(manifest, archive, paths, "Class-Path", " +"); // backward
......@@ -127,13 +130,11 @@ public class ClassicPluginStrategy implements PluginStrategy {
} else {
File classes = new File(expandDir, "WEB-INF/classes");
if (classes.exists())
paths.add(classes.toURI().toURL());
paths.add(classes);
File lib = new File(expandDir, "WEB-INF/lib");
File[] libs = lib.listFiles(JAR_FILTER);
if (libs != null) {
for (File jar : libs)
paths.add(jar.toURI().toURL());
}
if (libs != null)
paths.addAll(Arrays.asList(libs));
baseResourceURL = expandDir.toURI().toURL();
}
......@@ -176,8 +177,10 @@ public class ClassicPluginStrategy implements PluginStrategy {
ClassLoader dependencyLoader = new DependencyClassLoader(getClass()
.getClassLoader(), Util.join(dependencies,optionalDependencies));
ClassLoader classLoader = new URLClassLoader(paths.toArray(new URL[paths.size()]),
dependencyLoader);
// using AntClassLoader with Closeable so that we can predictably release jar files opened by URLClassLoader
AntClassLoader2 classLoader = new AntClassLoader2(dependencyLoader);
classLoader.addPathFiles(paths);
return new PluginWrapper(archive, manifest, baseResourceURL,
classLoader, disableFile, dependencies, optionalDependencies);
......@@ -247,7 +250,7 @@ public class ClassicPluginStrategy implements PluginStrategy {
return new File(base.getParentFile(),relative);
}
private static void parseClassPath(Manifest manifest, File archive, List<URL> paths, String attributeName, String separator) throws IOException {
private static void parseClassPath(Manifest manifest, File archive, List<File> paths, String attributeName, String separator) throws IOException {
String classPath = manifest.getMainAttributes().getValue(attributeName);
if(classPath==null) return; // attribute not found
for (String s : classPath.split(separator)) {
......@@ -259,12 +262,12 @@ public class ClassicPluginStrategy implements PluginStrategy {
fs.setDir(dir);
fs.setIncludes(file.getName());
for( String included : fs.getDirectoryScanner(new Project()).getIncludedFiles() ) {
paths.add(new File(dir,included).toURI().toURL());
paths.add(new File(dir,included));
}
} else {
if(!file.exists())
throw new IOException("No such file: "+file);
paths.add(file.toURI().toURL());
paths.add(file);
}
}
}
......@@ -359,4 +362,22 @@ public class ClassicPluginStrategy implements PluginStrategy {
// TODO: delegate resources? watch out for diamond dependencies
}
/**
* {@link AntClassLoader} with a few methods exposed and {@link Closeable} support.
*/
private static final class AntClassLoader2 extends AntClassLoader implements Closeable {
private AntClassLoader2(ClassLoader parent) {
super(parent,true);
}
public void addPathFiles(Collection<File> paths) throws IOException {
for (File f : paths)
addPathFile(f);
}
public void close() throws IOException {
cleanup();
}
}
}
......@@ -322,9 +322,8 @@ public final class PluginManager extends AbstractModelObject {
* Orderly terminates all the plugins.
*/
public void stop() {
for (PluginWrapper p : activePlugins) {
for (PluginWrapper p : activePlugins)
p.stop();
}
// Work around a bug in commons-logging.
// See http://www.szegedi.org/articles/memleak.html
LogFactory.release(uberClassLoader);
......
......@@ -30,13 +30,14 @@ import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Closeable;
import java.net.URL;
import java.util.List;
import java.util.jar.Manifest;
import java.util.logging.Logger;
import static java.util.logging.Level.WARNING;
import org.apache.commons.logging.LogFactory;
import org.kohsuke.stapler.StaplerRequest;
import org.kohsuke.stapler.StaplerResponse;
/**
......@@ -283,6 +284,13 @@ public final class PluginWrapper {
// Work around a bug in commons-logging.
// See http://www.szegedi.org/articles/memleak.html
LogFactory.release(classLoader);
if (classLoader instanceof Closeable)
try {
((Closeable) classLoader).close();
} catch (IOException e) {
LOGGER.log(WARNING, "Failed to shut down classloader",e);
}
}
/**
......@@ -369,12 +377,13 @@ public final class PluginWrapper {
// Action methods
//
//
public void doMakeEnabled(StaplerRequest req, StaplerResponse rsp) throws IOException {
public void doMakeEnabled(StaplerResponse rsp) throws IOException {
Hudson.getInstance().checkPermission(Hudson.ADMINISTER);
enable();
rsp.setStatus(200);
}
public void doMakeDisabled(StaplerRequest req, StaplerResponse rsp) throws IOException {
public void doMakeDisabled(StaplerResponse rsp) throws IOException {
Hudson.getInstance().checkPermission(Hudson.ADMINISTER);
disable();
rsp.setStatus(200);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册