blob: cedeed0aac0772100ce3829c997a5bc78883b588 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
package org.apache.tools.ant;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.util.Collections;
import java.util.Enumeration;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.util.FileUtils;
import org.apache.tools.ant.util.JavaEnvUtils;
import org.junit.After;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
/**
* Test case for ant class loader
*
*/
public class AntClassLoaderTest {
@Rule
public BuildFileRule buildRule = new BuildFileRule();
@Rule
public ExpectedException thrown = ExpectedException.none();
private AntClassLoader loader;
@Before
public void setUp() {
buildRule.configureProject("src/etc/testcases/core/antclassloader.xml");
buildRule.executeTarget("setUp");
}
@After
public void tearDown() {
if (loader != null) {
loader.cleanup();
}
}
//test inspired by bug report 37085
@Test
public void testJarWithManifestInDirWithSpace() {
String mainjarstring = buildRule.getProject().getProperty("main.jar");
String extjarstring = buildRule.getProject().getProperty("ext.jar");
Path myPath = new Path(buildRule.getProject());
myPath.setLocation(new File(mainjarstring));
buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
loader = buildRule.getProject().createClassLoader(myPath);
String path = loader.getClasspath();
assertEquals(mainjarstring + File.pathSeparator + extjarstring, path);
}
@Test
public void testJarWithManifestInNonAsciiDir() {
String mainjarstring = buildRule.getProject().getProperty("main.jar.nonascii");
String extjarstring = buildRule.getProject().getProperty("ext.jar.nonascii");
Path myPath = new Path(buildRule.getProject());
myPath.setLocation(new File(mainjarstring));
buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
loader = buildRule.getProject().createClassLoader(myPath);
String path = loader.getClasspath();
assertEquals(mainjarstring + File.pathSeparator + extjarstring, path);
}
/**
* The test should fail if NullPointException is thrown
*
* @throws ClassNotFoundException if a class is not found, ignored
*/
@Test
public void testCleanup() throws ClassNotFoundException {
thrown.expect(ClassNotFoundException.class);
Path path = new Path(buildRule.getProject(), ".");
loader = buildRule.getProject().createClassLoader(path);
boolean canary = false;
try {
// we don't expect to find this
loader.findClass("fubar");
canary = true;
} finally {
assertFalse("Nonexistent class found", canary);
loader.cleanup();
try {
// we don't expect to find this
loader.findClass("fubar");
canary = true;
} finally {
assertFalse("Nonexistent class found", canary);
// tell the build it is finished
buildRule.getProject().fireBuildFinished(null);
try {
// we don't expect to find this
loader.findClass("fubar");
canary = true;
} finally {
assertFalse("Nonexistent class found", canary);
}
}
}
}
@Test
public void testGetPackage() throws Exception {
buildRule.executeTarget("prepareGetPackageTest");
Path myPath = new Path(buildRule.getProject());
myPath.setLocation(new File(buildRule.getProject().getProperty("test.jar")));
buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
loader = buildRule.getProject().createClassLoader(myPath);
assertNotNull("should find class", loader.findClass("org.example.Foo"));
assertNotNull("should find package",
new GetPackageWrapper(loader).getPackage("org.example"));
}
@Test
public void testCodeSource() throws Exception {
buildRule.executeTarget("prepareGetPackageTest");
Path myPath = new Path(buildRule.getProject());
File testJar = new File(buildRule.getProject().getProperty("test.jar"));
myPath.setLocation(testJar);
buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
loader = buildRule.getProject().createClassLoader(myPath);
Class<?> foo = loader.findClass("org.example.Foo");
URL codeSourceLocation =
foo.getProtectionDomain().getCodeSource().getLocation();
assertEquals(codeSourceLocation + " should point to test.jar",
FileUtils.getFileUtils().getFileURL(testJar), codeSourceLocation);
}
@Test
public void testSignedJar() throws Exception {
buildRule.executeTarget("signTestJar");
File jar = new File(buildRule.getProject().getProperty("test.jar"));
Path myPath = new Path(buildRule.getProject());
myPath.setLocation(jar);
buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
loader = buildRule.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());
}
/**
* @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=47593">bug 47593</a>
* request to log the name of corrupt zip files from which
* classes cannot be loaded
*/
@Test
public void testInvalidZipException() {
buildRule.executeTarget("createNonJar");
File jar = new File(buildRule.getProject().getProperty("tmp.dir")
+ "/foo.jar");
Path myPath = new Path(buildRule.getProject());
myPath.setLocation(jar);
buildRule.getProject().setUserProperty(MagicNames.BUILD_SYSCLASSPATH, "ignore");
loader = buildRule.getProject().createClassLoader(myPath);
PrintStream sysErr = System.err;
try {
StringBuffer errBuffer = new StringBuffer();
PrintStream err =
new PrintStream(new BuildFileRule.AntOutputStream(errBuffer));
System.setErr(err);
loader.getResource("foo.txt");
String log = buildRule.getLog();
int startMessage = log.indexOf("CLASSPATH element ");
assertTrue(startMessage >= 0);
assertTrue(log.indexOf("foo.jar is not a JAR", startMessage) > 0);
} finally {
System.setErr(sysErr);
}
}
/**
* Asserts that getResources won't return resources that cannot be
* seen by AntClassLoader but by ClassLoader.this.parent.
*
* @see <a href="https://issues.apache.org/bugzilla/show_bug.cgi?id=46752">bug 46752</a>
*/
@SuppressWarnings("resource")
@Test
public void testGetResources() throws IOException {
AntClassLoader acl = new AntClassLoader(new EmptyLoader(), null,
new Path(null), true);
assertNull(acl.getResource("META-INF/MANIFEST.MF"));
assertFalse(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements());
// double check using system classloader as parent
acl = new AntClassLoader(null, null, new Path(null), true);
assertNotNull(acl.getResource("META-INF/MANIFEST.MF"));
assertTrue(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements());
}
@Test
public void testGetResourcesUsingFactory() throws IOException {
AntClassLoader acl =
AntClassLoader.newAntClassLoader(new EmptyLoader(), null,
new Path(null), true);
assertNull(acl.getResource("META-INF/MANIFEST.MF"));
assertFalse(acl.getResources("META-INF/MANIFEST.MF").hasMoreElements());
}
/**
* Tests that {@link AntClassLoader} supports multi-release jar files while dealing with
* runtime resources in Java 9+ runtime environments.
*
* @see <a href="bz-62952">https://bz.apache.org/bugzilla/show_bug.cgi?id=62952</a>
*/
@Test
public void testMultiReleaseJar() {
buildRule.executeTarget("testMRJar");
final boolean atleastJava9 = JavaEnvUtils.isAtLeastJavaVersion(JavaEnvUtils.JAVA_9);
final String targetOutput = buildRule.getOutput();
Assert.assertNotNull("Multi-release jar test did not generate any output", targetOutput);
if (atleastJava9) {
Assert.assertTrue("Unexpected output from multi-release jar test for Java runtime >= 9",
targetOutput.contains("mrjar test result = 9"));
} else {
Assert.assertTrue("Unexpected output from multi-release jar test", targetOutput.contains("mrjar test result = default"));
}
}
private static class EmptyLoader extends ClassLoader {
public URL getResource(String n) {
return null;
}
public Enumeration<URL> getResources(String n) {
return Collections.emptyEnumeration();
}
}
private static class GetPackageWrapper extends ClassLoader {
GetPackageWrapper(ClassLoader parent) {
super(parent);
}
public Package getPackage(String s) {
return super.getPackage(s);
}
}
}