Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve functionality of the classloader task when applied to the core loader #4

Open
wants to merge 5 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 20 additions & 7 deletions src/main/org/apache/tools/ant/Project.java
Original file line number Diff line number Diff line change
Expand Up @@ -185,10 +185,9 @@ protected Boolean initialValue() {
};

/**
* The Ant core classloader--may be <code>null</code> if using
* parent classloader.
* The Ant core classloader
*/
private ClassLoader coreLoader = null;
private AntClassLoader coreLoader = null;

/** Records the latest task to be executed on a thread. */
private final Map<Thread,Task> threadTasks =
Expand Down Expand Up @@ -302,7 +301,8 @@ public void initSubProject(final Project subProject) {
*/
public void init() throws BuildException {
initProperties();

if (coreLoader == null)
setCoreLoader(null);
ComponentHelper.getComponentHelper(this).initDefaultDefinitions();
}

Expand Down Expand Up @@ -361,18 +361,31 @@ public AntClassLoader createClassLoader(
/**
* Set the core classloader for the project. If a <code>null</code>
* classloader is specified, the parent classloader should be used.
* <p>
* <em>Since Ant 1.9.5</em>, if the argument is not a
* non-<code>null</code> instance of {@link AntClassLoader}, then
* an ant class loader will be constructed around the specified
* class loader. This ensures that the core class loader is always
* an ant class loader which can be modified using the
* &lt;classloader&gt; task.
*
* @param coreLoader The classloader to use for the project.
* May be <code>null</code>.
*/
public void setCoreLoader(final ClassLoader coreLoader) {
this.coreLoader = coreLoader;
if (coreLoader == null || coreLoader instanceof AntClassLoader == false)
this.coreLoader = createClassLoader(coreLoader, null);
else
this.coreLoader = (AntClassLoader)coreLoader;
}

/**
* Return the core classloader to use for this project.
* This may be <code>null</code>, indicating that
* the parent classloader should be used.
* <p>
* <em>Since Ant 1.9.5</em> the returned loader will always be a
* non-<code>null</code> instance of {@link AntClassLoader}.
* In older versions, this might be <code>null</code>,
* indicating that the parent classloader should be used.
*
* @return the core classloader to use for this project.
*
Expand Down
27 changes: 18 additions & 9 deletions src/main/org/apache/tools/ant/taskdefs/Classloader.java
Original file line number Diff line number Diff line change
Expand Up @@ -161,17 +161,26 @@ public Path createClasspath() {
*/
public void execute() {
try {
// Gump friendly - don't mess with the core loader if only classpath
if ("only".equals(getProject().getProperty("build.sysclasspath"))
&& (name == null || SYSTEM_LOADER_REF.equals(name))) {
log("Changing the system loader is disabled "
+ "by build.sysclasspath=only", Project.MSG_WARN);
return;
String loaderName;
Object obj;
if (name == null || SYSTEM_LOADER_REF.equals(name)) {
if ("only".equals(getProject()
.getProperty("build.sysclasspath"))) {
// Gump friendly - don't mess with the core loader
// if only the system classpath is to be used
log("Changing the system loader is disabled "
+ "by build.sysclasspath=only", Project.MSG_WARN);
return;
}
name = null;
loaderName = SYSTEM_LOADER_REF;
obj = getProject().getCoreLoader();
}
else {
loaderName = name;
obj = getProject().getReference(loaderName);
}

String loaderName = (name == null) ? SYSTEM_LOADER_REF : name;

Object obj = getProject().getReference(loaderName);
if (reset) {
// Are any other references held ? Can we 'close' the loader
// so it removes the locks on jars ?
Expand Down
87 changes: 87 additions & 0 deletions src/tests/antunit/taskdefs/classloader-test.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<?xml version="1.0"?>
<!--
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

http://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.
-->

<project name="classloader-test" default="antunit" xmlns:au="antlib:org.apache.ant.antunit">
<import file="../antunit-base.xml" />

<target name="setUp">
<mkdir dir="${input}" />
<macrodef name="antCore">
<!--
Execute ant similar to how the launcher script does it,
but make sure to only include the core ant.jar in the library list.
That way we can see whether loading extra modules works as expected.
-->
<attribute name="target" />
<sequential>
<java classname="org.apache.tools.ant.launch.Launcher"
outputproperty="test.output"
fork="true"
failonerror="false">
<classpath>
<pathelement location="${ant.library.dir}/ant-launcher.jar" />
</classpath>
<sysproperty key="ant.home" value="${ant.home}" />
<sysproperty key="ant.library.dir" value="${input}" />
<arg value="-lib" />
<arg value="${ant.library.dir}/ant.jar" />
<arg value="-cp" />
<arg value="" />
<arg value="-f" />
<arg value="${ant.file}" />
<arg value="-Dorig.library.dir=${ant.library.dir}" />
<arg value="@{target}" />
</java>
</sequential>
</macrodef>
</target>

<available file="${ant.library.dir}/ant-junit.jar"
property="test.have.junit" />

<target name="testCannotLoadTask" if="test.have.junit">
<!-- Make sure we DON'T have <junit> available by default -->
<antCore target="runCannotLoadTask" />
<au:assertTrue message="Expected line not found:&#10;${test.output}">
<contains string="${test.output}"
substring="JUnitTask was not found" />
</au:assertTrue>
</target>

<target name="runCannotLoadTask">
<junit/>
</target>

<target name="testTweakCoreLoader" if="test.have.junit">
<!-- <junit> becomes available if we tweak the core class loader -->
<antCore target="runTweakCoreLoader" />
<au:assertTrue message="Expected line not found:&#10;${test.output}">
<!-- This error message is generated by the <junit> task,
so that task itself must have been loaded successfully -->
<contains string="${test.output}"
substring="must include junit.jar" />
</au:assertTrue>
</target>

<target name="runTweakCoreLoader">
<echo message="${orig.library.dir}/ant-junit.jar"/>
<classloader classpath="${orig.library.dir}/ant-junit.jar"/>
<junit/>
</target>

</project>