Reputation: 7892
I have a <path id="...">
in my build.xml
. Before invoking the compiler I want to verify that every jar/directory on the classpath exists and print a warning with the missing ones. Does anybody know an existing solution or do I need to write my own task for that?
OK, I decided to go for a custom task. Here it is, in case anybody ever needs such a thing:
import java.io.File;
import java.util.Iterator;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.Reference;
import org.apache.tools.ant.types.ResourceCollection;
import org.apache.tools.ant.types.resources.Resources;
public class CheckClasspathTask extends Task {
private Reference reference;
public CheckClasspathTask() {
}
public void setRefId(Reference reference) {
this.reference = reference;
}
public void execute() throws BuildException {
Resources resources = new Resources();
resources.setProject(getProject());
resources.add((ResourceCollection) reference.getReferencedObject());
boolean isFirst = true;
for (Iterator i = resources.iterator(); i.hasNext(); ) {
String f = i.next().toString();
if (!new File(f).exists()) {
if (isFirst) {
isFirst = false;
System.out.println("WARNING: The following entries on your classpath do not exist:");
}
System.out.println(f);
}
}
}
}
Upvotes: 3
Views: 3496
Reputation: 12985
This will check that every file or folder in a classpath exists. If one of them does not, it will fail the build showing the name of the 1st one that can't be found.
<target name="check-classpath" depends="create-classpath">
<pathconvert pathsep="," property="myclasspath" refid="compile.classpath"/>
<foreach list="${myclasspath}" param="file" target="check-file-or-folder-exists" />
</target>
<target name="check-file-or-folder-exists">
<fail message="Error: ${file} not found">
<condition>
<not>
<available file="${file}" />
</not>
</condition>
</fail>
</target>
Note that <foreach>
is in ant-contribs -- Ant Contribs clickable LINK
This will be needed to load the ant-contrib jar and hook up all the targets in it:
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="${some.lib.dir}/ant-contrib-1.0b3.jar" />
</classpath>
</taskdef>
There is supposed to exist a <for>
task that will allow setting an option to continue through all the path elements and only show an error at the end. I found my version of Eclipse had <foreach>
already on the classpath, so I figured this was good enough for me.
Upvotes: 2
Reputation: 6683
I haven't found many ways to iterate over a path in the Ant script using the default tasks. If you're building on a machine which has a UNIX-like shell, you can call out to the shell to check the classpath elements.
When calling shell scripts, you can use the apply
task, but I couldn't get it to print when a classpath element didn't exist.
Let's assume you have the following classpath declaration:
<path id="your.classpath">
<fileset dir="your.libs"/>
<pathelement location="/some/missing/dir"/>
</path>
This will report if there are any missing elements, but doesn't tell you which ones:
<apply executable="test" type="file" ignoremissing="false">
<arg value="-e"/>
<srcfile/>
<path refid="build.classpath"/>
</apply>
You could combine this with a simple shell script and get what you want by changing the executable
attribute -- assuming you just want a big warning message and not a build failure:
#!/bin/sh
test -e "$1" || echo "WARNING: Classpath element $1 does not exist!"
If you want the build to fail, you can set the apply
task to fail if an error is reported (a missing file/directory in this case) and then modify the shell script to return a non-zero exit code after the warning is printed.
An alternative would be to use the exec
task and just execute a little script inline:
<pathconvert property="classpath" refid="build.classpath" pathsep=":"/>
<exec executable="sh">
<arg value="-c"/>
<arg value="for f in `echo ${classpath} | tr ':' '\n'`; do test -e $f || echo WARNING: Classpath element $f does not exist!; done"/>
</exec>
Upvotes: 1
Reputation: 1324537
I would say probably a custom ant task is in order, a little like the org.netbeans.modules.bpel.project.anttasks.ValidateBPELProjectTask
done in a 'pre-dist
' target of this build.xml.
Note: the ValidateBPELProjectTask ant task is a bit more complex than your usual custom task: it needs to have its own classpath to run (classpath not initially passed to the build.xml at first).
Since you cannot modify the classpath of the current ant task classloader, ValidateBPELProjectTask defines a new AntClassLoader
and calls setContextClassLoader()
.
You will not need such a mechanism though: you can just pass the list of directories to check to your task as a parameter.
Upvotes: 1