Expose only extension-api to extensions

Unless a plugin declares "Gerrit-ApiType: plugin" in its manifest,
assume it is an extension and only make the gerrit-extension-api
available to it through the ClassLoader.

For non-plugins, do not make any Guice bindings available from the
server. This further restricts what an extension can see and do with
the system internals.

Change-Id: Ia38336c42786afb1419d64c06b0d908ae92a64d1
This commit is contained in:
Shawn O. Pearce
2012-05-10 16:54:28 -07:00
parent 6fa1e9121d
commit da4919abf6
8 changed files with 417 additions and 74 deletions

View File

@@ -31,9 +31,10 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.security.CodeSource;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.List;
import java.util.SortedMap;
import java.util.TreeMap;
import java.util.jar.Attributes;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
@@ -196,7 +197,7 @@ public final class GerritLauncher {
throw e;
}
final ArrayList<URL> jars = new ArrayList<URL>();
final SortedMap<String, URL> jars = new TreeMap<String, URL>();
try {
final ZipFile zf = new ZipFile(path);
try {
@@ -208,6 +209,7 @@ public final class GerritLauncher {
}
if (ze.getName().startsWith("WEB-INF/lib/")) {
String name = ze.getName().substring("WEB-INF/lib/".length());
final File tmp = createTempFile(safeName(ze), ".jar");
final FileOutputStream out = new FileOutputStream(tmp);
try {
@@ -224,7 +226,7 @@ public final class GerritLauncher {
} finally {
out.close();
}
jars.add(tmp.toURI().toURL());
jars.put(name, tmp.toURI().toURL());
}
}
} finally {
@@ -237,13 +239,38 @@ public final class GerritLauncher {
if (jars.isEmpty()) {
return GerritLauncher.class.getClassLoader();
}
Collections.sort(jars, new Comparator<URL>() {
public int compare(URL o1, URL o2) {
return o1.toString().compareTo(o2.toString());
}
});
return new URLClassLoader(jars.toArray(new URL[jars.size()]));
// The extension API needs to be its own ClassLoader, along
// with a few of its dependencies. Try to construct this first.
List<URL> extapi = new ArrayList<URL>();
move(jars, "gerrit-extension-api-", extapi);
move(jars, "guice-", extapi);
move(jars, "javax.inject-1.jar", extapi);
move(jars, "aopalliance-1.0.jar", extapi);
move(jars, "guice-servlet-", extapi);
move(jars, "servlet-api-", extapi);
ClassLoader parent = ClassLoader.getSystemClassLoader();
if (!extapi.isEmpty()) {
parent = new URLClassLoader(
extapi.toArray(new URL[extapi.size()]),
parent);
}
return new URLClassLoader(
jars.values().toArray(new URL[jars.size()]),
parent);
}
private static void move(SortedMap<String, URL> jars,
String prefix,
List<URL> extapi) {
SortedMap<String, URL> matches = jars.tailMap(prefix);
if (!matches.isEmpty()) {
String first = matches.firstKey();
if (first.startsWith(prefix)) {
extapi.add(jars.remove(first));
}
}
}
private static String safeName(final ZipEntry ze) {