git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@276691 13f79535-47bb-0310-9956-ffa450edef68master
@@ -85,6 +85,8 @@ | |||
<property name="build.tests" value="${build.dir}/testcases"/> | |||
<property name="build.tests.javadocs" value="${build.dir}/javadocs.test/"/> | |||
<property name="manifest.tmp" value="${build.dir}/optional.manifest"/> | |||
<!-- the absolute path --> | |||
<property name="build.tests.value" location="${build.tests}"/> | |||
<!-- | |||
=================================================================== | |||
@@ -365,7 +367,7 @@ | |||
the java version | |||
=================================================================== | |||
--> | |||
<target name="javac.preset" depends="javac.preset.1.5+,javac.preset.1.5-"/> | |||
<target name="javac.preset.1.5+" depends="check_for_optional_packages" | |||
if="jdk1.5+"> | |||
@@ -1455,6 +1457,7 @@ | |||
<sysproperty key="ant.home" value="${ant.home}"/> | |||
<sysproperty key="build.tests" value="${build.tests}"/> | |||
<sysproperty key="build.tests.value" value="${build.tests.value}"/> | |||
<sysproperty key="tests-classpath.value" | |||
value="${tests-classpath.value}"/> | |||
@@ -1604,6 +1607,7 @@ | |||
<!-- <jvmarg value="-classic"/> --> | |||
<sysproperty key="ant.home" value="${ant.home}"/> | |||
<sysproperty key="build.tests" value="${build.tests}"/> | |||
<sysproperty key="build.tests.value" value="${build.tests.value}"/> | |||
<sysproperty key="tests-classpath.value" | |||
value="${tests-classpath.value}"/> | |||
<classpath refid="tests-classpath"/> | |||
@@ -1629,4 +1633,4 @@ | |||
description="--> creates a minimum distribution in ./dist" | |||
depends="dist-lite"/> | |||
</project> | |||
</project> |
@@ -684,22 +684,19 @@ | |||
<tr> | |||
<td valign="top"> algorithmclass </td> | |||
<td valign="top"> Classname of custom algorithm implementation. Lower | |||
priority than <i>algorithm</i>. | |||
<!-- NOTE --> (see <a href="#ModSelNote">note</a> for restrictions) </td> | |||
priority than <i>algorithm</i>. </td> | |||
<td valign="top" align="center"> No </td> | |||
</tr> | |||
<tr> | |||
<td valign="top"> cacheclass </td> | |||
<td valign="top"> Classname of custom cache implementation. Lower | |||
priority than <i>cache</i>. | |||
<!-- NOTE --> (see <a href="#ModSelNote">note</a> for restrictions) </td> | |||
priority than <i>cache</i>. </td> | |||
<td valign="top" align="center"> No </td> | |||
</tr> | |||
<tr> | |||
<td valign="top"> comparatorclass </td> | |||
<td valign="top"> Classname of custom comparator implementation. Lower | |||
priority than <i>comparator</i>. | |||
<!-- NOTE --> (see <a href="#ModSelNote">note</a> for restrictions) </td> | |||
priority than <i>comparator</i>. </td> | |||
<td valign="top" align="center"> No </td> | |||
</tr> | |||
<tr> | |||
@@ -803,6 +800,10 @@ | |||
</tr> | |||
</table> | |||
<p>The <code><modified></code> selector supports a nested | |||
<code><classpath></code> element that represents a <a href="../using.html#path"> | |||
PATH like structure</a> for finding custom interface implementations. </p> | |||
<p>Here are some examples of how to use the Modified Selector:</p> | |||
<blockquote><pre> | |||
@@ -868,23 +869,22 @@ | |||
Apache Forrest</a>). Here all <b>changed</b> files are uploaded to the server. The | |||
CacheSelector saves therefore much upload time.</p> | |||
<blockquote><pre> | |||
<modified cacheclassname="com.mycompany.MyCache"> | |||
<classpath> | |||
<pathelement location="lib/mycompony-antutil.jar"/> | |||
</classpath> | |||
</modified> | |||
</pre></blockquote> | |||
<p>Uses <tt>com.mycompany.MyCache</tt> from a jar outside of Ants own classpath | |||
as cache implementation</p> | |||
<!-- NOTE --> | |||
<i>(see <a href="#ModSelNote">note</a> for restrictions)</i> | |||
<a name="ModSelNote"></a> | |||
<h4>Note on RuleBasedCollator</h4> | |||
<p>The RuleBasedCollator needs a format for its work, but its needed while | |||
instantiation. There is a problem in the initialization algorithm for this | |||
case. Therefore you should not use this (or tell me the workaround :-).</p> | |||
<p>The selector can not find the specified algorithm-, cache- or comparator- | |||
class if the selector is loaded from a different classloader. | |||
To be able to use your own classes you have to ensure that the selector | |||
can find the classes by adding the your package to the core: <ul> | |||
<li> by placing your JAR in %ANT_HOME/lib </li> | |||
<li> by adding '-lib myclasses/' while invocation </li> | |||
<li> by placing your JAR in ${ant.home}/.ant/lib </li> | |||
</ul></p> | |||
<a name="selectcontainers"></a> | |||
@@ -250,7 +250,11 @@ | |||
algorithmclass="${pkg.test}.MockAlgorithm" | |||
cacheclass="${pkg.test}.MockCache" | |||
comparatorclass="${pkg.test}.MockComparator" | |||
/> | |||
> | |||
<classpath> | |||
<pathelement location="${build.tests.value}"/> | |||
</classpath> | |||
</modified> | |||
</fileset> | |||
<fileset id="fs.full" dir="${test.dir}/src"/> | |||
<property name="fs.mod.value" refid="fs.mod"/> | |||
@@ -32,6 +32,7 @@ import org.apache.tools.ant.BuildListener; | |||
import org.apache.tools.ant.BuildEvent; | |||
import org.apache.tools.ant.types.EnumeratedAttribute; | |||
import org.apache.tools.ant.types.Parameter; | |||
import org.apache.tools.ant.types.Path; | |||
import org.apache.tools.ant.types.selectors.BaseExtendSelector; | |||
@@ -82,6 +83,17 @@ import org.apache.tools.ant.types.selectors.BaseExtendSelector; | |||
* </copy> | |||
* </pre></p> | |||
* | |||
* <p>If you want to provide your own interface implementation you can do | |||
* that via the *classname attributes. If the classes are not on Ant´s core | |||
* classpath, you will have to provide the path via nested <classpath> | |||
* element, so that the selector can find the classes. <pre> | |||
* <modified cacheclassname="com.mycompany.MyCache"> | |||
* <classpath> | |||
* <pathelement location="lib/mycompony-antutil.jar"/> | |||
* </classpath> | |||
* </modified> | |||
* </p> | |||
* | |||
* <p>All these three examples copy the files from <i>src</i> to <i>dest</i> | |||
* using the ModifiedSelector. The ModifiedSelector uses the <i>PropertyfileCache | |||
* </i>, the <i>DigestAlgorithm</i> and the <i>EqualComparator</i> for its | |||
@@ -205,6 +217,8 @@ import org.apache.tools.ant.types.selectors.BaseExtendSelector; | |||
* </table> | |||
* If another name is used a BuildException "Invalid parameter" is thrown. </p> | |||
* | |||
* <p>Additionally this selector supports a nested <classpath>. </p> | |||
* | |||
* <p>This selector uses reflection for setting the values of its three interfaces | |||
* (using org.apache.tools.ant.IntrospectionHelper) therefore no special | |||
* 'configuration interfaces' has to be implemented by new caches, algorithms or | |||
@@ -214,7 +228,7 @@ import org.apache.tools.ant.types.selectors.BaseExtendSelector; | |||
* a nested <i><param name="algorithm.provider" value="MyProvider"/></i>. | |||
* | |||
* | |||
* @version 2004-07-09 | |||
* @version 2004-07-12 | |||
* @since Ant 1.6 | |||
*/ | |||
public class ModifiedSelector extends BaseExtendSelector implements BuildListener { | |||
@@ -283,6 +297,12 @@ public class ModifiedSelector extends BaseExtendSelector implements BuildListene | |||
*/ | |||
private Vector specialParameter = new Vector(); | |||
/** The classloader of this class. */ | |||
private ClassLoader myClassLoader = null; | |||
/** provided classpath for the classloader */ | |||
private Path classpath = null; | |||
// ----- constructors ----- | |||
@@ -467,22 +487,8 @@ public class ModifiedSelector extends BaseExtendSelector implements BuildListene | |||
protected Object loadClass(String classname, String msg, Class type) { | |||
try { | |||
// load the specified class | |||
Object rv = getClassLoader().loadClass(classname).newInstance(); | |||
/* TODO: the selector cant find the specified class if the | |||
* selector is loaded from a different classloader. | |||
* See ModifiedSelectorTest.testCustom<Algorithm|Cache|Comparator|Classes>(). | |||
* To be able to run these tests you have to ensure that <junit> can find | |||
* the classes by adding the test package to the core: | |||
* - by placing the ant-testutils.jar in %ANT_HOME/lib | |||
* - by adding '-lib build/testcases' while invocation | |||
* | |||
* IMO this is not only a problem for the Mock-Classes inside the | |||
* tests. The *classname attributes are designed for the user to | |||
* provide his own implementations. Therefore they should be | |||
* found ... Workaround again: -lib, ~/.ant/lib, ant.home/lib | |||
* JHM | |||
*/ | |||
Object rv = Class.forName(classname).newInstance(); | |||
if (!type.isInstance(rv)) { | |||
throw new BuildException("Specified class (" + classname + ") " + msg); | |||
} | |||
@@ -495,7 +501,6 @@ public class ModifiedSelector extends BaseExtendSelector implements BuildListene | |||
} | |||
// ----- the selection work ----- | |||
@@ -629,6 +634,48 @@ public class ModifiedSelector extends BaseExtendSelector implements BuildListene | |||
} | |||
/** | |||
* Add the classpath. | |||
* @param path the classpath | |||
*/ | |||
public void addClasspath(Path path) { | |||
if (classpath != null) { | |||
throw new BuildException("<classpath> can be set only once."); | |||
} | |||
classpath = path; | |||
} | |||
/** | |||
* Returns and initializes the classloader for this class. | |||
* @return the classloader | |||
*/ | |||
public ClassLoader getClassLoader() { | |||
if (myClassLoader == null) { | |||
myClassLoader = (classpath == null) | |||
// the usual classloader | |||
? getClass().getClassLoader() | |||
// additional use the provided classpath | |||
: new org.apache.tools.ant.AntClassLoader(getProject(), classpath); | |||
} | |||
return myClassLoader; | |||
} | |||
/** | |||
* Set the used ClassLoader. | |||
* If you invoke this selector by API (e.g. inside some testcases) the selector | |||
* will use a different classloader for loading the interface implementations than | |||
* the caller. Therefore you will get a ClassCastException if you get the | |||
* implementations from the selector and cast them. | |||
* @param loader the ClassLoader to use | |||
* @see ModifiedSelectorTest#doDelayUpdateTest(int key) | |||
*/ | |||
public void setClassLoader(ClassLoader loader) { | |||
myClassLoader = loader; | |||
} | |||
/** | |||
* Support for nested <param> tags. | |||
* @param key the key of the parameter | |||
@@ -28,6 +28,7 @@ import java.text.RuleBasedCollator; | |||
// Ant | |||
import org.apache.tools.ant.BuildException; | |||
import org.apache.tools.ant.types.Parameter; | |||
import org.apache.tools.ant.types.Path; | |||
// inside MockProject | |||
import org.apache.tools.ant.Project; | |||
@@ -42,7 +43,7 @@ import org.apache.tools.ant.types.selectors.modifiedselector.*; | |||
/** | |||
* Unit tests for ModifiedSelector. | |||
* | |||
* @version 2004-07-07 | |||
* @version 2004-07-12 | |||
* @since Ant 1.6 | |||
*/ | |||
public class ModifiedSelectorTest extends BaseSelectorTest { | |||
@@ -54,6 +55,9 @@ public class ModifiedSelectorTest extends BaseSelectorTest { | |||
/** Package of the CacheSelector classes. */ | |||
private static String pkg = "org.apache.tools.ant.types.selectors.modifiedselector"; | |||
/** Path where the testclasses are. */ | |||
private Path testclasses = null; | |||
// ===================== constructors, factories ===================== | |||
@@ -75,57 +79,22 @@ public class ModifiedSelectorTest extends BaseSelectorTest { | |||
// ===================== JUnit stuff ===================== | |||
public void setUp() { | |||
// project reference is set in super.setUp() | |||
super.setUp(); | |||
// init the testclasses path object | |||
Project prj = getProject(); | |||
if (prj != null) { | |||
testclasses = new Path(prj, prj.getProperty("build.tests.value")); | |||
} | |||
} | |||
/* There are two tests which cannot run until the test package is added | |||
* to the core classloader. See comment in ModifiedSelelector.loadClass(). | |||
* The tests should pass then - but because the usual build wont add | |||
* these classes I exclude them from being executed: | |||
* - classloaderProblem_testCustomAlgorithm2 | |||
* - classloaderProblem_testCustomClasses | |||
* | |||
* For activating decomment the suite method. | |||
* | |||
* the addTest-part can be generated via grep and sed: | |||
* grep "void test" ModifiedSelectorTest.java | |||
* | sed -e 's/() {/"));/' | |||
* -e 's/public void / suite.addTest(new ModifiedSelectorTest("/' | |||
*/ | |||
/* * / | |||
// for test only - ignore tests where we arent work at the moment | |||
public static junit.framework.Test suite() { | |||
junit.framework.TestSuite suite= new junit.framework.TestSuite(); | |||
suite.addTest(new ModifiedSelectorTest("testValidateWrongCache")); | |||
suite.addTest(new ModifiedSelectorTest("testValidateWrongAlgorithm")); | |||
suite.addTest(new ModifiedSelectorTest("testValidateWrongComparator")); | |||
suite.addTest(new ModifiedSelectorTest("testIllegalCustomAlgorithm")); | |||
suite.addTest(new ModifiedSelectorTest("testNonExistentCustomAlgorithm")); | |||
suite.addTest(new ModifiedSelectorTest("testCustomAlgorithm")); | |||
suite.addTest(new ModifiedSelectorTest("testPropcacheInvalid")); | |||
suite.addTest(new ModifiedSelectorTest("testPropertyfileCache")); | |||
suite.addTest(new ModifiedSelectorTest("testCreatePropertiesCacheDirect")); | |||
suite.addTest(new ModifiedSelectorTest("testCreatePropertiesCacheViaModifiedSelector")); | |||
suite.addTest(new ModifiedSelectorTest("testCreatePropertiesCacheViaCustomSelector")); | |||
suite.addTest(new ModifiedSelectorTest("testHashvalueAlgorithm")); | |||
suite.addTest(new ModifiedSelectorTest("testDigestAlgorithmMD5")); | |||
suite.addTest(new ModifiedSelectorTest("testDigestAlgorithmSHA")); | |||
suite.addTest(new ModifiedSelectorTest("testChecksumAlgorithm")); | |||
suite.addTest(new ModifiedSelectorTest("testChecksumAlgorithmCRC")); | |||
suite.addTest(new ModifiedSelectorTest("testChecksumAlgorithmAdler")); | |||
suite.addTest(new ModifiedSelectorTest("testEqualComparator")); | |||
suite.addTest(new ModifiedSelectorTest("testRuleComparator")); | |||
suite.addTest(new ModifiedSelectorTest("testEqualComparatorViaSelector")); | |||
suite.addTest(new ModifiedSelectorTest("testSeldirs")); | |||
suite.addTest(new ModifiedSelectorTest("testScenario1")); | |||
suite.addTest(new ModifiedSelectorTest("testScenarioCoreSelectorDefaults")); | |||
suite.addTest(new ModifiedSelectorTest("testScenarioCoreSelectorSettings")); | |||
suite.addTest(new ModifiedSelectorTest("testScenarioCustomSelectorSettings")); | |||
suite.addTest(new ModifiedSelectorTest("classloaderProblem_testDelayUpdateTaskFinished")); | |||
suite.addTest(new ModifiedSelectorTest("classloaderProblem_testDelayUpdateTargetFinished")); | |||
suite.addTest(new ModifiedSelectorTest("classloaderProblem_testDelayUpdateBuildFinished")); | |||
suite.addTest(new ModifiedSelectorTest("classloaderProblem_testCustomAlgorithm2")); | |||
suite.addTest(new ModifiedSelectorTest("classloaderProblem_testCustomClasses")); | |||
return suite; | |||
} | |||
/* */ | |||
@@ -216,13 +185,13 @@ public class ModifiedSelectorTest extends BaseSelectorTest { | |||
} | |||
public void classloaderProblem_testCustomAlgorithm2() { | |||
public void testCustomAlgorithm2() { | |||
String algo = getAlgoName("org.apache.tools.ant.types.selectors.MockAlgorithm"); | |||
assertTrue("Wrong algorithm used: "+algo, algo.startsWith("MockAlgorithm")); | |||
} | |||
public void classloaderProblem_testCustomClasses() { | |||
public void testCustomClasses() { | |||
BFT bft = new BFT(); | |||
bft.setUp(); | |||
try { | |||
@@ -248,17 +217,17 @@ public class ModifiedSelectorTest extends BaseSelectorTest { | |||
} | |||
public void classloaderProblem_testDelayUpdateTaskFinished() { | |||
public void testDelayUpdateTaskFinished() { | |||
doDelayUpdateTest(1); | |||
} | |||
public void classloaderProblem_testDelayUpdateTargetFinished() { | |||
public void testDelayUpdateTargetFinished() { | |||
doDelayUpdateTest(2); | |||
} | |||
public void classloaderProblem_testDelayUpdateBuildFinished() { | |||
public void testDelayUpdateBuildFinished() { | |||
doDelayUpdateTest(3); | |||
} | |||
@@ -281,6 +250,11 @@ public class ModifiedSelectorTest extends BaseSelectorTest { | |||
sel.setProject(project); | |||
sel.setUpdate(true); | |||
sel.setDelayUpdate(true); | |||
// sorry - otherwise we will get a ClassCastException because the MockCache | |||
// is loaded by two different classloader ... | |||
sel.setClassLoader(this.getClass().getClassLoader()); | |||
sel.addClasspath(testclasses); | |||
sel.setAlgorithmClass("org.apache.tools.ant.types.selectors.MockAlgorithm"); | |||
sel.setCacheClass("org.apache.tools.ant.types.selectors.MockCache"); | |||
sel.configure(); | |||
@@ -313,6 +287,8 @@ public class ModifiedSelectorTest extends BaseSelectorTest { | |||
*/ | |||
private String getAlgoName(String classname) { | |||
ModifiedSelector sel = new ModifiedSelector(); | |||
// add the test classes to its classpath | |||
sel.addClasspath(testclasses); | |||
sel.setAlgorithmClass(classname); | |||
// let the selector do its checks | |||
sel.validate(); | |||