This is the AntNewbies page where newbies can ask difficult but clear questions.

Remember that the user mailing list is still the primary place for fellow Ant users to solve problems.

You can also browse http://stackoverflow.com/questions/tagged/ant to see frequently asked questions.

 <target name="RSM" depends="init">
        <property name="preflag" value="-wc -w"/>
        <property name="datfile" value="'File dat c:\rsm\MyProject_${tstamp}.dat'"/>
        <property name="flags"   value="-r h,cpp,java"/>
        <property name="project" value="c:\rsm\MyProject_v1.0_rsm\MyProject"/>
        <property name="string"  value="${preflag}${datfile} ${flags} ${project}"/>
        <echo message="${string}"/>
        <exec dir="c:\rsm\rsm" executable="rsm.exe" output="dir.txt">
                <arg line="${string}"/>
        </exec>

This is what I'm trying to duplicate on the command line with Ant.

rsm -wc -w "File dat c:\rsm\MyProject_${tstamp}.dat" -r h,cpp,java c:\rsm\MyProject_v1.0_rsm\MyProject

Answer #1 - I figured this one out on my own. Notice the "'s

  <target name="RSM" depends="init,splash">
        <property name="preflag" value="-H -wc -w"/>
        <property name="datfile" value="&quot;File dat c:\rsm\MyProject&quot;"/>
        <property name="flags"   value="-r h,cpp,java"/>
        <property name="project" value="c:\rsm\MyProject\MyProject"/>
        <property name="string"  value="${preflag} ${datfile} ${flags} ${project}"/>
        <echo message="${string}"/>
        <exec dir="c:\rsm" executable="c:\rsm\rsm\rsm.exe" output="dir.txt">
                <arg line="${string}"/>
        </exec>
  </target>

Note: if the MyProject file above happened to have spaces in its filename, then the easiest thing to do is to use its 8.3 representation. Persuading Ant to pass the necessary backslash doublequote characters to the exec task is tricky!


I tried to use the JDT to compile my Source but i don't know the right Syntax to start it correct in ANT. The Commandline is:

    java -classpath jdtcore.jar org/eclipse/jdt/internal/compiler/batch/Main <options> <Sources>

I tried it with this Options. (jdtcore.jar is in Classpath set)

<target name="buildSources">
        <javac includes="**/*.java, *.java" 
               srcdir="${dir.project.root}/src" destdir="${dir.build}" 
               verbose="true" fork="yes" 
               executable="org.eclipse.jdt.internal.compiler.batch.Main">
                <classpath refid="classpath"/>
        </javac>
</target>

Answer #1

the easiest solution for you is to use the Ant compiler adapter that ships with Eclipse http://help.eclipse.org/help21/index.jsp?topic=/org.eclipse.jdt.doc.isv/guide/jdt_api_compile.htm.

Answer #2

the more general solution. The javac task has a compiler attribute that you not only can use to select one of the compilers with built-in support, it can also point to a Java class that implements a certain Ant interface. The build.compiler Ant property can be used to set a default value for this attribute for all javac tasks.

This is exactly what Answer #1 uses, you just don't need to write the compiler adapter since somebody else has already done so for you.


Question#2.5 It doesnt work... I don't find the Bug in my Script... :(

No i tried as told with the Help from the Eclipse Page. I copied the directory $ECLIPSE_JDT_HOME/plugins/org.eclipse.jdt.core_2.1.3 to $BUILD_PATH/compiler. I also tried to copy the jdtCompilerAdapter.jar to local Directory, to $ANT_HOME/lib, and so on and it doesn't work. (I try to use the JDT Outside of Eclipse as Standalone Compiler)

<path id="classpath">
        <pathelement path="${classpath}"/>
        <pathelement location="${basedir}/compiler/jdtCompilerAdapter.jar"/>
</path>
<target name="buildSources">
        <property name="build.compiler" value="org.eclipse.jdt.core.JDTCompilerAdapter"/>
        <javac includes="**/*.java, *.java" srcdir="${dir.project.root}/src" destdir="${dir.build}">
                <classpath refid="classpath"/>
        </javac>
</target>

and all what i get is

BUILD FAILED
~/ant/build.xml:62: Compiler Adapter 'org/eclipse/jdt/core/JDTCompilerAdapter' can't be found.
        at org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory.resolveClassName(CompilerAdapterFactory.java:167)
        at org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory.getCompiler(CompilerAdapterFactory.java:131)
        at org.apache.tools.ant.taskdefs.Javac.compile(Javac.java:935)
        at org.apache.tools.ant.taskdefs.Javac.execute(Javac.java:764)
        at org.apache.tools.ant.UnknownElement.execute(UnknownElement.java:269)
        at org.apache.tools.ant.Task.perform(Task.java:364)
        at org.apache.tools.ant.Target.execute(Target.java:301)
        at org.apache.tools.ant.Target.performTasks(Target.java:328)
        at org.apache.tools.ant.Project.executeTarget(Project.java:1215)
        at org.apache.tools.ant.Project.executeTargets(Project.java:1063)
        at org.apache.tools.ant.Main.runBuild(Main.java:632)
        at org.apache.tools.ant.Main.startAnt(Main.java:183)
        at org.apache.tools.ant.launch.Launcher.run(Launcher.java:197)
        at org.apache.tools.ant.launch.Launcher.main(Launcher.java:56)
Caused by: java.lang.ClassNotFoundException: org/eclipse/jdt/core/JDTCompilerAdapter
        at java.lang.Class.forName0(Native Method)
        at java.lang.Class.forName(Class.java:141)
        at org.apache.tools.ant.taskdefs.compilers.CompilerAdapterFactory.resolveClassName(CompilerAdapterFactory.java:163)
        ... 13 more

Answer #2,5

I answer myself :-) I've found it. The JDT 2.1.3 could not be used as Standalone because of a Bug in it. Only Release 3.0 or higher could be used. See also (https://bugs.eclipse.org/bugs/show_bug.cgi?id=37779)


Question#3 Simple Beginner Question about If-Usage.

I have a new Problem. I sitt here and try to realise a Backuppart in my Tomcat-Application-Ant-Script (What a Word). I have the Book from Bernd Matzke from Addison-Wesly here and tried the Following Script:

<?xml version="1.0" encoding="UTF-8"?>
<project name="iftest" default="main" basedir=".">
        <property name="dir.tomcat.webapps" value="/usr/share/tomcat4/webapps"/>
        <property name="tomcat.projectname" value="myApplication"/>
        <target name="main" depends="doif">
                <echo message="The first Statement would be the last Statement... ;-)"/>
        </target>
        <target name="doif" depends="checkFileExists, if_target"/>
        <target name="checkFileExists">
                <condition property="p">
                        <available file="web.xml" filepath="${dir.tomcat.webapps}/${tomcat.projectname}/WEB-INF"/>
                </condition>
                <echo message="The Property &apos;p&apos; is ${p}"/>
        </target>
        <target name="if_target" if="${p}">
                <echo message="Hello i'm here in the if_target"/>
        </target>
</project>

If i run it the Answer is:

[root@vmaelv04t ant-enteich]# ant -f build_test.xml
Buildfile: build_test.xml

checkFileExists:
     [echo] The Property 'p' is true

if_target:

doif:

main:
     [echo] The first Statement would be the last Statement... ;-)

BUILD SUCCESSFUL
Total time: 1 second

Answer#3

Just change your target definition from

        <target name="if_target" if="${p}">

to

        <target name="if_target" if="p">

With your definition you referenced the value of p, not p itself. The if-statement just looks, if the given property exists anyway, not if the value is true.


This is what i tried:

        <target name="bzip2">
                <echo> BZipping ${in} to ${out} ... </echo>
                <bzip2> src="${in}" destfile="${out}" </bzip2>
        </target>

and this is how i tried to invoke it and the results:

C:\java>ant -Din=jit_interface.pdf -Dout=jit_interface.pdf.bz2 bzip2
Buildfile: build.xml

bzip2:
     [echo]  BZipping jit_interface.pdf to jit_interface.pdf.bz2 ...

BUILD FAILED
C:\java\build.xml:26: The <bzip2> type doesn't support nested text data.

Total time: 3 seconds
C:\java>

Is there any other way?

Answer #4

You can't set task attributes in the text content of a tag. You must set them as xml attributes of the tag. There is an example in the manual, which shows what it should look like - http://ant.apache.org/manual/CoreTasks/pack.html. So for your example it would become

        <target name="bzip2">
                <echo> BZipping ${in} to ${out} ... </echo>
                <bzip2 src="${in}" destfile="${out}" />
        </target>

The error message and the manual should have pointed you in the right direction here.


Just got an App Server (mandated company standard) which needs EAR or War files . I have a Servlet app running on another servlet engine and want to bundle it up as an EAR. How can that easily be done in Ant. I currently delivery the servlet application in two jars, one is third party so I dont have source for it, the other is all my code. There are config files involved as well.

Answer #5 - You should use the <war> and/or <ear> tasks. Probably the best thing is to create a war and use the <lib> element to include yor third party jar.


I'm JUST starting out with Ant, so please forgive me.

I know the documentation says you can't count on the FileSets task sorting your files. But this is exactly why I'm looking to something like Ant to handle my code compiles; I need them sorted.

Has anyone come up with a workaround so that the files can be sorted alphabetically by name? Any plans for future Ant enhancements to support this?

Answer #6 - Well, not really an answer - more of a follow up question. Why do you need your fileset sorted for compiles?

Answer #6 follow up - Why do you need your fileset sorted for compiles?

I cannot make a case specifically about the above question as I did not submit the question however I do have an interest in having a fileset sort files. The case is for using a fileset to determine the order of JUnits tests to execute. It would allow for a flow based on package name where we could have a setup package, a test package and a teardown package. These JUnits would not be typical unit tests but rather integration tests.

Answer #6 followup followup

You can't rely on Junit behaving predictably in this situation. Junit is a lot more complex than you expect, and far more quirky. Better to have one task/target to set up/deploy, another to run the tasks and a third to do teardown --outside junit. The trick is to not fail the junit task when the tests fail, just set a failure property and <fail> on that later, after doing cleanup. See also Apache Cactus for integrating webapp deployment into a test run.

Answer #6 followup #2 - Those needing this functionality should be pleased to know that Ant 1.7 will support a new concept--ResourceCollection--an interface which exposes objects of the existing Ant filelike-type Resource. Fileset, Dirset, Filelist, Path, etc. all implement this new interface. One of the new ResourceCollection implementations is the <sort> collection, which can sort resources according to their natural order, or by one or a combination of ResourceComparators. Several of these have been predefined; however a user can custom-implement and <typedef> his or her own ResourceComparator as well.

Answer #6 example

Run ls -l on each file in the current directory, sorted by size:

  <target name="sorttest">
    <apply executable="ls">
      <arg line="-l" />
      <sort id="sorted-set" xmlns:rcmp="antlib:org.apache.tools.ant.types.resources.comparators" >
        <rcmp:size/>
        <fileset dir="." includes="*" />
      </sort>
    </apply>
  </target>



This seems like it should just work, but it doesn't quite. When I have a tree of packages which are already compiled, then I have my updated versions of .java files which will override the existing .class files, there are cases where some of the sources will depend on other sources.

The problem is that if I'm compiling a .java file that depends on another .java file, but the .class file already exists for that other dependent file, then the .java file that is getting compiled might fail because a new method might have been added to the other .java file, but doesn't exist in the .class file.

In this case the order of compiling matters.

One simple solution would be to somehow delete all .class files that match .java files. Then javac will need to compile the .java version since it won't be able to find the methods otherwise.

Another solution would be to do more thorough dependency checking in javac where it would see that a .java file exists for a class and it will compile that file before using an existing .class file.

Any suggestions on how to do this with ant?

Answer #7 - Use the <depend> task. It will handle most of what you want.

Answer #7.5 - Alternatively try the <javamake/> variant of the <javac/> task, available from http://www.experimentalstuff.com/Technologies/JavaMake/.


Question#8 How can I perform an if-then-else construct for building multiple JARs/WARs within a single build.xml

I am attempting to merge two disparate code bases, but keep them logically separate at run-time. The used to live in two different app servers. I have refactored them, but am running into problems getting them to assign to each jar. I presume that I want to have a condition such as...

    <target name="jar" description="Determine what fileset goes to what jar.">
        <property name="DESTINATION_JAR" value="" />
        <condition property="${DESTINATION_JAR}" value="reporting.jar">
            <or>
            </or>
        </condition>
        <condition property="${DESTINATION_JAR}" value="reportsvr.jar">
            <or>
            </or>
        </condition>
    </target>

In the <or></or> block I'd like to test if a certain set of filenames exist within a directory and if so populate a fileset that will be built into the jar.


Question#9 Why am I getting: The <exec> type doesn't support the nested "echo" element.

An offshore developer is getting this strange message:

BUILD FAILED
F:\Vitria431\BW431\vant\buildfiles\bwsrc\bme\newbme.xml:22: Following error occured while executing this line
F:\Vitria431\BW431\vant\buildfiles\bwsrc\bme\newbme.xml:123: The <exec> type doesn't support the nested "echo" element.

Here's a snippet of the code:

    <!-- Small BME -->
    <echo message="Smalling bme..."/>
    <exec dir="${bwsrc.dir}/bme/commands" executable="makeall">
      <arg line="bmesmall"/>
    </exec>

The executable "makeall" outputs something like this:

$ makeall bmesmall
Using jvm.lib at "c:\local\jdk1.4.x\lib\jvm.lib"

Root directory: D:\ws\svn\jedi
Language: en/us, start time: Fri Apr 08 14:34:38 2005
WARNING! VCDIR not set. I'll try to find C++ stuff.
Building target "bmeSmall" (bwsrc\bme\bmesmall.bld:102)
del D:\ws\svn\jedi\export\bme\modules\ant.jar
del D:\ws\svn\jedi\export\bme\modules\applet.jar
del D:\ws\svn\jedi\export\bme\modules\autoupdate.jar

I'm thinking it either has to do with their version of JDK (1.4.1_02) or Ant (they claim it's 1.6.1). Anyone seen this error before? I can't get it to reproduce on my system.

Answer #9 - Any error message Element <a> doesn't support nested element of type <b> means that there is a bit of the build file that goes

<a> 
 <b/>
</a>

And the element "a" -be it task, datatype, whatever, does not support nested elements of type "b". It is a parse time error, done when mapping XML nodes to the implementation classes. In the initial problem snippet, there is no way the sample code could raise this error. There is something else wrong with the build file, something like <exec><echo>echo ... </echo></exec>. It has nothing to do with the JDK or Ant version, as no version of Ant supports <echo> as a nested element of <exec>.

If you see this error, here is what you should do


Question#10 I have downloaded ant, and now I am trying to install it using the directions on the apache page. I am typing 'build install' in the command prompt (I am on windows XP) but I get this error ::: 'build' is not recognized as an internal or external command, operable program or batch file.

Answer #10 Clearly then, "build" is not a valid command. Consult the section "Running Ant" in the documentation to get an up to date list of which commands Ant actually provides. or examine ANT_HOME/bin.


Question#11 Can I use the JUnitReport Task with Unit Tests that are not part of the JUnit framework?

Answer #12 The reporting task applies XSL transforms to XML files of test results. Anything that generates XML files of the appropriate naming policy and XML structure can be turned into the reports. Alternatively, you can extract the relevant XSL stylesheets from Ant's JAR/source tree and modify them to meet your needs.


Question#12 Sorry I am having all sorts of problems...I have installed ant, and when I try to run it I get this error

Exception in thread "main" java.lang.NoClassDefFoundError: org/apache/tools/ant/launch/Launcher

Answer #12 This is a FAQ; see http://ant.apache.org/faq.html#NoClassDefFoundError .


Question#13 I am having problems using the junit task. Ant is not recognizing the junit as a task. I have read the FAQ corresponding to this problem, but it does not make sense. I am using ant version 1.6.2 I have removed the classpath environment variable completely. I also copied the junit.jar file to my lib directory. I verified that the ant-junit.jar file is in the lib directory as well. In my build.xml file I declare the following path

<path id="library.junit.classpath">

</path> <junit>

</junit>

does anyone know what is going on? The FAQ confused me because I thought it was hinting at removing my ant-junit.jar file from the lib directory, and including in in a taskdef...was I misunderstanding the solution?

Answer#13

It's not enough to have junit.jar on the classpath for the tests, it has to be loaded in the same classloader as Ant's junit task. Either add junit.jar to ANT_HOME/lib ${user.home}/.ant/.lib. The alternate solution (a new declaration of the Ant junit tasks after removing ant-junit.jar from ANT_HOME/lib) is not recommended for beginners.

To verify that your libraries are set up right, run "ant -diagnostics". This will list tasks that are not available. Do not attempt to run JUnit if the -diagnostics option tells you that junit is not available or missing a dependency.


Question#14 Is it possible to change the working directory of a JUNIT task under ANT? My task looks like this:

But the following code, which loads a DTD file, tries to load it from the directory where ANT is being run. I need to tell ANT (or the JUnit task) to use the fileset "dir=" setting as the current working directory, since it is where the DTD file will be.


Question#15 How do I perform a task only if Ant is going to perform a task?

I want to create a file only if and only if at least one of my java source files needs to be compiled. I do not want the file created otherwise. Here is what I have:

This will create the file every time which is not desirable.

Answer#15

Use the uptodate task and a "timestamp file" (this could even be the ServiceVersion.java file itself) to determine whether any of the generated .class files (excluding ServiceVersion.class) are newer than this "timestamp file" and if so set a property that can be used as a condition on executing a target to re-create the ServiceVersion.java file (updating the "timestamp file" too if a separate file is used).


Question#16 I'm having trouble getting a merged inline and external manifest using the 'jar' task in ant 1.6.5. Here's a code snippet:

<jar destfile="${dst.file}" manifest="${manifest.file}">
   <!-- Create standard manifest -->
   <manifest>
      <section name="${company.name}">
         <attribute name="Product-Version" value="${bw.product.version}"/>
         <attribute name="Build-Date" value="${build.timestamp}"/>
         <attribute name="Build-Number" value="${label}"/>
      </section>
   </manifest>
   <!-- Specify files to be included in the META-INF directory  -->
   <metainf refid="metainf.fileset"/>
   <!-- Source includes/excludes passed in from calling build file -->
   <fileset refid="archive.fileset"/>
</jar>

What I get is just the content from ${manifest.file}. Any ideas why the nested manifest section isn't getting merged.

Answer #16 That's not what the options mean. Including your information in the <manifest> child node does not add it; it creates a new manifest file. As a rule, you should use either the manifest attribute or the <manifest> child node for the <jar> node, but not both. If you want to merge them, then consider using the current manifest file as a template, with some tokens in it for a filterset.


Question#17 I have a bunch of files in a folder, that I want to import into my build.xml. Can anybody give me a hint (or a solution), how to import all files from a directory, e.g. using a fileset? Otherwise, I'd have to change my code anytime, a new file is added to the directory...

Answer#17 The <import> task does not support <fileset>s or <resourcecollection>. Not sure about the problem with <fileset> but with <rc>s we dont know the basedir of the imported file, because URL or just String could be a resource, too.

What you can do is import a single (optional) file - a generated one, which imports all your files. If I have to do a kind of file listing, I use <pathconvert>. So this works for me:

<project default="generateImport">

    <property name="antfile.dir" value="buildfiles"/>
    <property name="antfile.gen" value="_generated_.xml"/>

    <import file="${antfile.gen}" optional="true"/>
    
    <target name="generateImport">
        <property name="import.start" value="&lt;import file=&quot;"/>
        <property name="import.end"   value="&quot;/&gt;"/>
        <property name="br"  value="${line.separator}"/>
        <property name="tab" value="    "/>
        <pathconvert property="antfiles.import" 
                     dirsep="/" 
                     pathsep="${import.end}${br}${tab}${import.start}">
            <map from="${basedir}/" to=""/>
            <fileset dir="${antfile.dir}" includes="*.xml" excludes="${antfile.gen}"/>
        </pathconvert>
        <echo file="${antfile.gen}">
            &lt;project&gt;
                ${import.start}${antfiles.import}${import.end}
            &lt;/project&gt;
        </echo>
    </target>
    
    <target name="test"/>

</project>

The first two properties define where your buildfiles (for import) are and where to store the generated buildfile. You could just change the names, but dont change the directory layout, because the file-locations of the imported files must be relative to the generated file. And the generator does not know any different. (Maybe you could play with the <map> on line 16...).

Line 6 is importing the generated buildfile. With optional=true, so that if you dont have generated the file, the build wont fail.

The target in line 26 "test" is just for (you guess) test.

The interisting stuff is in the target "generateImport" starting in line 8: first I define four properties. The syntax for import is: <import file="FILENAME"/>. So I define (xml-escaped) the part before and after the FILENAME (the filename will come from <pathconvert>). br and tab are for layout only.

The <pathconvert> collects all files and stores the list in the property antfiles.import. For platform purposes I use the / as directory separator. The nested <map> elements deletes the first part of the (absolute) paths so that you'll get relative ones (to the actual buildfile). The <fileset> defines which (your manually written) files to import.

The final buildfile is generated with the <echo> in combination with <pathconvert pathsep>. The pathsep (on Windows a semicolon) is between the individual filenames. So I need to put the import-end, a line break (layout only) and the import-start in between. Finally I need the project-start and an import-start before and an import-end and project-end after the whole list.

If you start a ant test you'll get no error. An ant -p just prints the generateImport and test target. After running a simple ant or ant generateImport the final ant -p will print all your written targets.


/!\ Edit conflict - other version:


Question#18 I am having problems with nested elements

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="BuildXmlUtilityTask" basedir="." default="buildXmlUtility">

    <property name="src.dir" value="src"/>
    <property name="classes.dir" value="classes"/>

    <target name="clean" description="Delete all generated files">
        <delete dir="${classes.dir}" failonerror="false"/>
        <delete file="${ant.project.name}.jar"/>
    </target>

    <target name="compile" description="Compiles the Task">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}"/>
    </target>

    <target name="jar" description="JARs the Task" depends="compile">
        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
    </target>


    <target name="buildXmlUtility"
            description="Taskdef the BuildXmlUtitily-Task"
            depends="jar">
        <taskdef name="buildUtility"
                 classname="com.corizon.xmlutility.XmlReaderUtility"                
                 classpath="${ant.project.name}.jar"/>
        <buildUtility> 
                      <Argument arg = "C:\\project.xml"/>
                      <Argument arg ="/projects/project[1]/@id"/>             
                      <Argument arg = "Id17000"/>
        </buildUtility>
    </target>

</project>



package com.corizon.xmlutility;

import java.util.Iterator;
import java.util.Vector;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;



public class XmlReaderUtility extends Task{
        
        private static XmlFileReader xmlFileReader;
        private String filePath;
        private String xpathExpression;
        private String value;
        Vector arguments = new Vector();
        
        
        
        public void setFilePath(String filePath) {
        this.filePath = filePath;
        }
        
        public void setXpathExpression(String xpathExpression) {
        this.xpathExpression = xpathExpression;
        }
        
        public void setValue(String value) {
        this.value = value;
        }

        /** Support for nested text. */
        public void addArgument(Argument text) {
                arguments.add(text);
        }
        
        
        // The method executing the task
        public void execute() throws BuildException {
                int i = 0;
                 // handle nested elements
                for (Iterator it = arguments.iterator(); it.hasNext(); ) 
                {
                Argument arg = (Argument)it.next();
                if(i== 0)
                {
                        setFilePath(arg.getArg());
                        i++;
                }
                if(i==1)
                {
                        setXpathExpression(arg.getArg());
                        i++;
                }
                if(i==2)
                {
                        setValue(arg.getArg());
                        i++;
                }
                }
                xmlFileReader = new XmlFileReader(filePath,xpathExpression,value);
        }
            
        
        /** A nested 'argument'. */
        public class Argument 
        {
                // Bean constructor
                public Argument() {}

                 /** Argument to pass on. */
                 String arg;
                 public void setArg(String arg) { this.arg = arg; }
                 public String getArg() { return arg; }
     }

         
 }

It complains The <buildUtility> type doesn't support the nested "Argument' element


/!\ Edit conflict - your version:


Answer#17 I am having problems with nested elements

<?xml version="1.0" encoding="ISO-8859-1"?>
<project name="BuildXmlUtilityTask" basedir="." default="buildXmlUtility">

    <property name="src.dir" value="src"/>
    <property name="classes.dir" value="classes"/>

    <target name="clean" description="Delete all generated files">
        <delete dir="${classes.dir}" failonerror="false"/>
        <delete file="${ant.project.name}.jar"/>
    </target>

    <target name="compile" description="Compiles the Task">
        <mkdir dir="${classes.dir}"/>
        <javac srcdir="${src.dir}" destdir="${classes.dir}"/>
    </target>

    <target name="jar" description="JARs the Task" depends="compile">
        <jar destfile="${ant.project.name}.jar" basedir="${classes.dir}"/>
    </target>


    <target name="buildXmlUtility"
            description="Taskdef the BuildXmlUtitily-Task"
            depends="jar">
        <taskdef name="buildUtility"
                 classname="com.corizon.xmlutility.XmlReaderUtility"                
                 classpath="${ant.project.name}.jar"/>
        <buildUtility> 
                      <Argument arg = "C:\\project.xml"/>
                      <Argument arg ="/projects/project[1]/@id"/>             
                      <Argument arg = "Id17000"/>
        </buildUtility>
    </target>

</project>



package com.corizon.xmlutility;

import java.util.Iterator;
import java.util.Vector;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.BuildException;



public class XmlReaderUtility extends Task{
        
        private static XmlFileReader xmlFileReader;
        private String filePath;
        private String xpathExpression;
        private String value;
        Vector arguments = new Vector();
        
        
        
        public void setFilePath(String filePath) {
        this.filePath = filePath;
        }
        
        public void setXpathExpression(String xpathExpression) {
        this.xpathExpression = xpathExpression;
        }
        
        public void setValue(String value) {
        this.value = value;
        }

        /** Support for nested text. */
        public void addArgument(Argument text) {
                arguments.add(text);
        }
        
        
        // The method executing the task
        public void execute() throws BuildException {
                int i = 0;
                 // handle nested elements
                for (Iterator it = arguments.iterator(); it.hasNext(); ) 
                {
                Argument arg = (Argument)it.next();
                if(i== 0)
                {
                        setFilePath(arg.getArg());
                        i++;
                }
                if(i==1)
                {
                        setXpathExpression(arg.getArg());
                        i++;
                }
                if(i==2)
                {
                        setValue(arg.getArg());
                        i++;
                }
                }
                xmlFileReader = new XmlFileReader(filePath,xpathExpression,value);
        }
            
        
        /** A nested 'argument'. */
        public class Argument 
        {
                // Bean constructor
                public Argument() {}

                 /** Argument to pass on. */
                 String arg;
                 public void setArg(String arg) { this.arg = arg; }
                 public String getArg() { return arg; }
     }

         
 }

It complains The <buildUtility> type doesn't support the nested "Argument' element

Question #19 Why I get the version of java when I type : ant -version

OS: Linux RH4EL

Ant version: 1.7.1

Java version : 1.4.2

ANT_HOME: /usr/local/bin/ant

[root@drago bin]# java -version
java version "1.4.2"
gcj (GCC) 3.4.6 20060404 (Red Hat 3.4.6-11)
Copyright © 2006 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.  Il n'y a PAS
GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

[root@drago bin]# ant -version
java version "1.4.2"
gcj (GCC) 3.4.6 20060404 (Red Hat 3.4.6-11)
Copyright © 2006 Free Software Foundation, Inc.
Ce logiciel est libre; voir les sources pour les conditions de copie.  Il n'y a PAS
GARANTIE; ni implicite pour le MARCHANDAGE ou pour un BUT PARTICULIER.

root@drago src]$ ant -f build.xml distrib.java.src
Exception in thread "main" java.lang.NoClassDefFoundError: org.apache.tools.ant.launch.Launcher
   at gnu.gcj.runtime.FirstThread.run() (/usr/lib/libgcj.so.5.0.0)
   at _Jv_ThreadRun(java.lang.Thread) (/usr/lib/libgcj.so.5.0.0)
   at _Jv_RunMain(java.lang.Class, byte const, int, byte const, boolean) (/usr/lib/libgcj.so.5.0.0)
   at __gcj_personality_v0 (/home/tmascc/decoms/src/java.version=1.4.2)
   at __libc_start_main (/lib/tls/libc-2.3.4.so)
   at _Jv_RegisterClasses (/home/tmascc/decoms/src/java.version=1.4.2)

I can get through this by using this command instead of ant : java -classpath /usr/local/bin/ant/lib/ant-launcher.jar -Dant.home=/usr/local/bin/ant org.apache.tools.ant.launch.Launcher -f build.xml distrib.java.src

Answer #19 - is /usr/local/bin/ant the ant script or a directory ? - try to unset the environment variable ANT_HOME to see if this improves things for you. - contact the ant user list to further this discussion.


CategoryCategory CategoryCategory

AntNewbies (last edited 2010-01-13 17:54:03 by antoine)