Browse Source

properly set CodeSource when loading classes. PR 20174

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@796702 13f79535-47bb-0310-9956-ffa450edef68
master
Stefan Bodewig 16 years ago
parent
commit
c8e91147e3
4 changed files with 101 additions and 12 deletions
  1. +4
    -1
      WHATSNEW
  2. +5
    -0
      src/etc/testcases/core/antclassloader.xml
  3. +50
    -5
      src/main/org/apache/tools/ant/AntClassLoader.java
  4. +42
    -6
      src/tests/junit/org/apache/tools/ant/AntClassLoaderTest.java

+ 4
- 1
WHATSNEW View File

@@ -410,7 +410,10 @@ Fixed bugs:

* The default stylesheets for <junitreport> failed to properly escape
XML content in exception stack traces.
Bugzilla Report 39492
Bugzilla Report 39492.

* AntClassLoader didn't set the proper CodeSource for loaded classes.
Bugzilla Report 20174.

Other changes:
--------------


+ 5
- 0
src/etc/testcases/core/antclassloader.xml View File

@@ -67,4 +67,9 @@ public class Foo {}
</jar>
</target>

<target name="signTestJar" depends="prepareGetPackageTest">
<signjar alias="testonly" keystore="../testkeystore"
storepass="apacheant" jar="${tmp.dir}/test.jar"/>
</target>

</project>

+ 50
- 5
src/main/org/apache/tools/ant/AntClassLoader.java View File

@@ -27,6 +27,9 @@ import java.io.Reader;
import java.lang.reflect.Constructor;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.security.cert.Certificate;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
@@ -37,6 +40,7 @@ import java.util.Vector;
import java.util.Locale;
import java.util.jar.Attributes;
import java.util.jar.Attributes.Name;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
@@ -1116,11 +1120,17 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener {
protected Class defineClassFromData(File container, byte[] classData, String classname)
throws IOException {
definePackage(container, classname);
// XXX should instead make a new ProtectionDomain with a CodeSource
// corresponding to container.toURI().toURL() and the same
// PermissionCollection as Project.class.protectionDomain had
return defineClass(classname, classData, 0, classData.length, Project.class
.getProtectionDomain());
ProtectionDomain currentPd = Project.class.getProtectionDomain();
String classResource = getClassFilename(classname);
CodeSource src = new CodeSource(FILE_UTILS.getFileURL(container),
getCertificates(container,
classResource));
ProtectionDomain classesPd =
new ProtectionDomain(src, currentPd.getPermissions(),
this,
currentPd.getPrincipals());
return defineClass(classname, classData, 0, classData.length,
classesPd);
}

/**
@@ -1179,6 +1189,41 @@ public class AntClassLoader extends ClassLoader implements SubBuildListener {
}
}

/**
* Get the certificates for a given jar entry, if it is indeed a jar.
*
* @param container the File from which to read the entry
* @param entry the entry of which the certificates are requested
*
* @return the entry's certificates or null is the container is
* not a jar or it has no certificates.
*
* @exception IOException if the manifest cannot be read.
*/
private Certificate[] getCertificates(File container, String entry)
throws IOException {
if (container.isDirectory()) {
return null;
}
JarFile jarFile = null;
InputStream is = null;
try {
jarFile = new JarFile(container);
JarEntry ent = jarFile.getJarEntry(entry);
if (ent != null) {
// must read the input in order to obtain certificates
is = jarFile.getInputStream(ent);
while (is.read() >= 0);
}
return ent == null ? null : ent.getCertificates();
} finally {
FileUtils.close(is);
if (jarFile != null) {
jarFile.close();
}
}
}

/**
* Define the package information when the class comes from a
* jar with a manifest


+ 42
- 6
src/tests/junit/org/apache/tools/ant/AntClassLoaderTest.java View File

@@ -28,6 +28,7 @@ import org.apache.tools.ant.types.Path;
public class AntClassLoaderTest extends BuildFileTest {

private Project p;
private AntClassLoader loader;

public AntClassLoaderTest(String name) {
super(name);
@@ -41,6 +42,9 @@ public class AntClassLoaderTest extends BuildFileTest {
}

public void tearDown() {
if (loader != null) {
loader.cleanup();
}
getProject().executeTarget("cleanup");
}
//test inspired by bug report 37085
@@ -50,8 +54,8 @@ public class AntClassLoaderTest extends BuildFileTest {
Path myPath = new Path(getProject());
myPath.setLocation(new File(mainjarstring));
getProject().setUserProperty("build.sysclasspath","ignore");
AntClassLoader myLoader = getProject().createClassLoader(myPath);
String path = myLoader.getClasspath();
loader = getProject().createClassLoader(myPath);
String path = loader.getClasspath();
assertEquals(mainjarstring + File.pathSeparator + extjarstring, path);
}
public void testJarWithManifestInNonAsciiDir() {
@@ -60,13 +64,13 @@ public class AntClassLoaderTest extends BuildFileTest {
Path myPath = new Path(getProject());
myPath.setLocation(new File(mainjarstring));
getProject().setUserProperty("build.sysclasspath","ignore");
AntClassLoader myLoader = getProject().createClassLoader(myPath);
String path = myLoader.getClasspath();
loader = getProject().createClassLoader(myPath);
String path = loader.getClasspath();
assertEquals(mainjarstring + File.pathSeparator + extjarstring, path);
}
public void testCleanup() throws BuildException {
Path path = new Path(p, ".");
AntClassLoader loader = p.createClassLoader(path);
loader = p.createClassLoader(path);
try {
// we don't expect to find this
loader.findClass("fubar");
@@ -105,12 +109,44 @@ public class AntClassLoaderTest extends BuildFileTest {
myPath.setLocation(new File(getProject().getProperty("tmp.dir")
+ "/test.jar"));
getProject().setUserProperty("build.sysclasspath","ignore");
AntClassLoader loader = getProject().createClassLoader(myPath);
loader = getProject().createClassLoader(myPath);
assertNotNull("should find class", loader.findClass("org.example.Foo"));
assertNotNull("should find package",
new GetPackageWrapper(loader).getPackage("org.example"));
}

public void testCodeSource() throws Exception {
executeTarget("prepareGetPackageTest");
Path myPath = new Path(getProject());
myPath.setLocation(new File(getProject().getProperty("tmp.dir")
+ "/test.jar"));
getProject().setUserProperty("build.sysclasspath","ignore");
loader = getProject().createClassLoader(myPath);
Class foo = loader.findClass("org.example.Foo");
String codeSourceLocation =
foo.getProtectionDomain().getCodeSource().getLocation().toString();
assertTrue(codeSourceLocation + " should point to test.jar",
codeSourceLocation.endsWith("test.jar"));
}

public void testSignedJar() throws Exception {
executeTarget("signTestJar");
File jar = new File(getProject().getProperty("tmp.dir")
+ "/test.jar");

Path myPath = new Path(getProject());
myPath.setLocation(jar);
getProject().setUserProperty("build.sysclasspath","ignore");
loader = getProject().createClassLoader(myPath);
Class foo = loader.findClass("org.example.Foo");

assertNotNull("should find class", foo);
assertNotNull("should have certificates",
foo.getProtectionDomain().getCodeSource()
.getCertificates());
assertNotNull("should be signed", foo.getSigners());
}

private static class GetPackageWrapper extends ClassLoader {
GetPackageWrapper(ClassLoader parent) {
super(parent);


Loading…
Cancel
Save