I am using Apache Ant as a tool for tedious data collection and calculation tasks I have to do over and over again. I have defined some custom Ant Tasks and they work really well.
However, now I want to create new data-types using the <typedef>
tag. I want to define some data in the beginning of my build.xml
which I can reference to later, much like the following example from a regular build file from one of my Java projects:
<path id="classpath.build">
<fileset dir="${dir.lib}">
<include name="**/*.jar" />
<exclude name="**/junit*" />
</fileset>
</path>
So I created a simple HelloWorld example like follows:
<sampledata data="LOL" id="someid" />
and in a custom ant task I would like to refer to this data type:
<customtask dataref="someid" />
This seems reasonable simple, so after digging in the API docs I found out that my class has to extend org.apache.tools.ant.types.DataType
and has to have the method setRefid(org.apache.tools.ant.types.Reference r)
.
My custom Ant Task customtask uses the following code for the dataref attribute:
public class CustomTask extends Task {
private SampleData data;
public void setDataref(Reference r) {
data = new SampleData(getProject());
data.setRefid(r);
}
public void execute() {
System.out.println(data.getData());
}
}
And my SampleData implementation is like follows:
public class SampleData extends DataType {
private String data;
public SampleData(Project project) {
setProject(project);
}
public void setData(String data) {
this.data = data;
}
public String getData() {
return this.data;
}
public void setRefid(Reference r) {
super.setRefid(r);
}
}
Mind you, this is all based on the sources from org.apache.tools.ant.types.Path
which shows the behavior I want.
However, after creating a target with the customtask as defined above, the output is null
. So SampleData is instantiated but the reference is not set correctly. When I debug I find out that SampleData is correctly instantiated in my ant file with the data LOL
and even the refence is set to someid
. Also, the CustomTask
class setDataref
method indeed is passed a Reference named someid
, so it all goes wrong in the setDataref
method, but I have no clue what I have to do and the manual is lacking (or I am missing an important part).
I have the feeling I don't completely grasp the lifecycle of custom datatypes with id's.
EDIT 23-11-2012 9:24 :
After some more fiddling and looking in the source of org.apache.tools.ant.types.Path
I followed some of the methods there and changed my SampleData.getData to the following:
public String getData() {
if(isReference()) {
return ((SampleData)getCheckedRef()).getData();
}
return this.data;
}
I am a little bit further, however now I get the following Ant error in my build.xml
:
/home/arjan/dev/so-demo/build.xml:9: someid doesn't denote a SampleData
However when I check the class encapsulated by the Reference object it is the correct type. I am getting pretty fed up by this now. Any more tips?
EDIT 23-11-2012 11:46 :
I created a Gist with a clear testcase. My Ant version is 1.8.4. Hopefully someone will come with a solution, because I've looked in other libraries like Sonatype Aether Antlib and followed their way of reasoning.
It all goes wrong at the getCheckedRef
method, specifically in the Ant sourcefile src\main\org\apache\tools\ant\types\DataType.java:250
:
if (!(requiredClass.isAssignableFrom(o.getClass()))) {
log("Class " + o.getClass() + " is not a subclass of " + requiredClass,
Project.MSG_VERBOSE);
String msg = ref.getRefId() + " doesn\'t denote a " + dataTypeName;
throw new BuildException(msg);
}
What is going on? This is the simples testcase I could come up with.