copy a file in ant based on condition - java

I have to copy a file if a property is set in ant target, but I always get an error for this code:
<condition property="component.is.x">
<equals arg1="${COMPONENT_ID}" arg2="x" />
</condition>
<target name="copyschemaparamsfile" if="sql.file.present" >
<if>
<equals arg1="${component.is.x}" arg2="true" />
<then>
<copy file="${in.root}/schema/${COMPONENT_ID}-schema.sql"
tofile="${tmp.dir}/${COMPONENT_ID}/x/schema/schema.sql"
failonerror="false" />
</then>
<else>
<copy file="${inf.root}/schema/${COMPONENT_ID}-schema.sql"
tofile="${tmp.dir}/${COMPONENT_ID}/${COMPONENT_ID}/schema/schema.sql" failonerror="false" />
</else>
</if>
</target>
Error is:
Ant could not find the task or a class this task relies upon.
This is common and has a number of causes; the usual
solutions are to read the manual pages then download and
install needed JAR files, or fix the build file:
- You have misspelt 'if'.
Fix: check your spelling.
- The task needs an external JAR file to execute
and this is not found at the right place in the classpath.
Fix: check the documentation for dependencies.
Fix: declare the task.
- The task is an Ant optional task and the JAR file and/or libraries
implementing the functionality were not found at the time you
yourself built your installation of Ant from the Ant sources.
Fix: Look in the ANT_HOME/lib for the 'ant-' JAR corresponding to the
task and make sure it contains more than merely a META-INF/MANIFEST.MF.
If all it contains is the manifest, then rebuild Ant with the needed
libraries present in ${ant.home}/lib/optional/ , or alternatively,
download a pre-built release version from apache.org
- The build file was written for a later version of Ant
Fix: upgrade to at least the latest release version of Ant
- The task is not an Ant core or optional task
and needs to be declared using <taskdef>.
- You are attempting to use a task defined using
<presetdef> or <macrodef> but have spelt wrong or not
defined it at the point of use
Remember that for JAR files to be visible to Ant tasks implemented
in ANT_HOME/lib, the files must be in the same directory or on the
classpath
I am always getting above error when I execute. Can someone please suggest how to check for a parameter and copy from one directory to other within an ant target?

Ant <if/> is part of Ant-Contrib. To use, follow the directions on the Ant-Contrib Tasks installation page:
(1) Copy ant-contrib-0.3.jar to the lib directory of your Ant
installation. If you want to use one of the tasks in your own project,
add the lines
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
to your build file.
(2) Keep ant-contrib-0.3.jar in a separate location. You now have to
tell Ant explicitly where to find it (say in /usr/share/java/lib):
<taskdef resource="net/sf/antcontrib/antcontrib.properties">
<classpath>
<pathelement location="/usr/share/java/lib/ant-contrib-0.3.jar"/>
</classpath>
</taskdef>

Related

Ant can't find Maven's "DependenciesTask"

I'm at a loss at what's wrong. I have an Ant build.xml that has the line
<path id="maven-ant-tasks.classpath" path="lib/maven-ant-tasks-2.1.3.jar" />
and then later
<target name="clean">
<artifact:mvn pom="${basedir}/pom.xml">
<arg value="clean"/>
</artifact:mvn>
The error I get is
java.lang.NoSuchMethodError: org.apache.maven.artifact.ant.DependenciesTask.setPathType(Ljava/lang/String;)V
The .jar file exists in the Ant's lib/ folder, and it also contains said function (unzipped it and looked at .class file). Also, when I change the path in the "path=" attribute, it doesn't complain, which means it's not even looking!
Anyone have an idea why it's not even considering the "path=" element here? Strangely enough, for other people in my group it works, and it has for me too in the past (had to rebuild my machine and reinstall everything).

I need to fail the build when a package imports from another package within the same project. How can I do so cleanly?

For a variety of reasons (regardless of whether or not this is a wise idea) we have a project with several packages (say one, two, three) that are similar in structure. There is one additional common package.
I want the build to fail when something in each of those packages imports something that isn't in common, e.g. because you accidentally accepted the wrong import completion, or because Eclipse silently brought over the wrong imports while copy-pasting bug fixes from one into two.
What works is copying all the source files, except for each package, over to a temporary folder and attempting to build the result:
<target name="enforce-no-cross-imports">
<phony-build without="one"/>
<phony-build without="two"/>
<phony-build without="three"/>
</target>
<macrodef name="phony-build">
<attribute name="without" />
<sequential>
<echo message="Checking there are no cross imports to the #{without} package." />
<mkdir dir="${java.io.tmpdir}/my-awesome-project/phony-build-#{without}/src" />
<mkdir dir="${java.io.tmpdir}/my-awesome-project/phony-build-#{without}/bin" />
<copy todir="${java.io.tmpdir}/my-awesome-project/phony-build-#{without}/src">
<fileset dir="${src.dir}">
<include name="**/*.java"/>
<exclude name="**/#{without}/"/>
</fileset>
</copy>
<javac srcdir="${java.io.tmpdir}/my-awesome-project/phony-build-#{without}/src"
destdir="${java.io.tmpdir}/my-awesome-project/phony-build-#{without}/bin"
classpathref="classpath" encoding="UTF-8" nowarn="on"/>
<delete dir="${java.io.tmpdir}/my-awesome-project" />
</sequential>
</macrodef>
However, when the build DOES break, the error obviously occurs inside ${java.io.tmpdir}.
enforce-no-cross-imports:
[echo] Checking there are no cross imports to the one package.
[mkdir] Created dir: C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\src
[mkdir] Created dir: C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\bin
[copy] Copying 47 files to C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\src
[javac] Compiling 47 source files to C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\bin
[javac] C:\Users\me\AppData\Local\Temp\my-awesome-project\phony-build-one\src\my\awesome\project\two\very\long\path\SomeController.java:43: package my.awesome.project.one.very.long.path.SomeConstantsClass does not exist
[javac] public static final String TEST = my.awesome.project.one.very.long.path.SomeConstantsClass.TEST;
As a result I can't click on the file name to jump directly to the issue. This adds way too much friction to the compilation process: it's bad enough that I'm effectively tripling the project build times.
What I thought I could do instead is not copy the files over and use the excludes attribute on the javac task instead:
excludes: Comma- or space-separated list of files (may be specified using wildcard patterns) that must be excluded; no files (except default excludes) are excluded when omitted.
...except this does not cause the build to break. What happens is that javac will not compile the other packages, but it will still look at them for confirmation. Turning on verbose shows this log line:
[javac] [checking my.awesome.project.one.very.long.path.SomeConstantsClass]
includeDestClasses seemed like another helpful flag, but setting it to false didn't help. <compilerarg value="-implicit:none"/> also was not helpful.
How can I tell javac that it really positively does need to exclude those files from the build, even if they are right there?
Alternatively, how can I take the output of javac and run find-replace on it so that the console output shows the correct path instead?
You could use the compilewithwalls or verifydesign tasks of ant-contrib, but the safest way to enforce separation like this is to isolate the modules into separate source directories and compile them independently. You'd first build the common module, then build each of the other modules with the compiled classes of "common" on their classpaths but not the classes of any of the other modules. This is the default approach when you're building with a higher level build tool like Maven. If you have a directory structure like this:
build.xml
lib
library JAR files
common
src
classes
one
src
classes
two
src
classes
then you could structure the build as
<macrodef name="compile-module">
<attribute name="module" />
<element name="depends" implicit="true" optional="true"/>
<sequential>
<javac srcDir="#{module}/src" destDir="#{module}/classes"
encoding="UTF-8" nowarn="on">
<classpath>
<path refid="classpath" />
<depends/>
</classpath>
</javac>
</sequential>
</macrodef>
<compile-module name="common" />
<compile-module name="one">
<pathelement location="common/classes" />
</compile-module>
<compile-module name="two">
<pathelement location="common/classes" />
</compile-module>
<compile-module name="three">
<pathelement location="common/classes" />
</compile-module>
You mention Eclipse in the question, so you'd need to do something similar there. Eclipse allows the root of one project to be inside another, so you could create one main Eclipse project "myapp-common" pointed at your project root with just common/src as its source directory (and common/classes as the corresponding output directory), then create separate "myapp-one", "myapp-two" etc. projects rooted at the one, two, etc. folders, each depending on the "myapp-common" project. That way you would never get Eclipse offering the "wrong" auto-completion, as project one simply cannot see project two or vice versa.

Apache Ant {Compile javac srcdir} does not exist

I am new to apache ant and I am currently working on an apache Ant project. I Just started out, imported the project into workspace and tried to run the build.xml. I added all the libraries that come with the original project to the build path. I am having the following problem. Please someone else wrote the code and I am supposed to improve it. The directories this is all about exist in the project directory.
BUILD FAILED
C:\workspace\MyApp\build.xml:83: srcdir "C:\workspace\MyApp\${compile.javac.srcdir}" does not exist!
The error code is referencing the following part of the build.xml file
<target name="compile.default" depends="init">
<javac fork="yes" srcdir="${compile.javac.srcdir}" destdir="${compile.javac.destdir}" includes="${compile.javac.include}" excludes="${compile.javac.exclude}" classpath="${compile.javac.classpath}" debug="${compile.javac.debug}" optimize="${compile.javac.optimize}" deprecation="${compile.javac.deprecation}" verbose="${compile.javac.verbose}">
</javac>
<copy todir="${compile.javac.destdir}">
<fileset dir="${compile.javac.srcdir}" includes="${compile.copy.include}" excludes="${compile.copy.exclude}"/>
</copy>
</target>
<target name="compile" depends="init,compile.default" description="Compile all java source">
</target>
<!--+++++++++++++++-->
<!-- lib target(s) -->
<!--+++++++++++++++-->
<target name="lib.default" depends="init,compile">
<xmlbean schema="config/schemas/validate/1.0/validate.xsd" destfile="lib/glx-beans.jar" classpath="lib/xbean.jar:lib/jsr173_1.0_api.jar" />
<jar jarfile="${lib.filename}">
<fileset dir="${lib.srcdir}" excludes="${lib.exclude}" />
</jar>
</target>
<target name="lib" depends="init,compile,lib.default" description="Create all Project Libraries">
</target>
Would you please tell me what I am missing?
The ${compile.javac.srcdir} isn't defined. There are a few possibilities:
This is defined not in the build.xml, but in some sort of properties file. See if you have something like <property file="..."/> in your build script. My recommendation is to have all properties defined in the build.xml file, and use a properties file to override those settings. This way, the only build file that a developer needs in the build.xml file and doesn't have to worry about setting up a separate build.porperties file.
This is defined in the build.xml file under a particular task, but you forgot to say that your target where you use thisis dependent upon this task.
One of the things you can do is use the -d parameter when running Ant. I run the following command when running Ant with the -d parameter:
$ and -d 2>&1 | tee ant.out
I can then look at ant.out and see if somehow I didn't define that particular property. Maybe I had the wrong capitalization or misspelled the property name. For example, it's very likely I'll define the property as copmile.javac.srcdir because I don't know how to spell. Looking at the -d output can quickly point these types of errors out.
By the way, you shouldn't have all of your tasks dependent upon init since they're dependent upon compile.default anyway:
<target name="compile.default" depends="init">
....
</target>
<target name="compile" depends="compile.default">
....
</target>
<target name="lib" depends="compile,lib.default">
....
</target>
If I run the target lib, it will see compile is dependent upon compile.default which is dependent upon init. Thus, your build will run init, then compile.default, then compile, then 'lib.defaultand finallylib`.
If the init task is just setting up properties, you can do that outside of any task. Then, these properties will be setup before any task is executed. This way, they're not forgotten. If your init is also creating directories, you may want to move those <mkdir/> tasks in front of the task where that directory is used. For example, you may want to make the destdir uses in javac before the <javac/> task.
I find assigning default properties outside of any task, and creating directories before they are needed to simplify the build.xml. Plus, you're not creating a whole flock of unused directories if the user is merely compiling and not packaging the jar/war/etc.

"Ant all" not working for me

I have got involved in a project. This project uses ant which is not something I am comfortable with. I have checked out the source code and tried running ant on the most outer directory.
Running 'ant' in commando prompt takes 1 sec and I get a BUILD SUCCESFULL message. If I run 'ant all' I get a
BUILD FAILED. Java.io.IOExceptio: Cannot run program "ant": CreateProcess=2, the system cannot find the file specified and then a long stacktrace.
Most of the people on the project runs OS-X while I use Windows XP.
Any help or information is appreciated :)
EDIT:
<target name="-all-submodules">
<subantlight target="all">
<filelist refid="ordered_build_files"/>
</subantlight>
</target>
In another xml file
<macrodef name="subantlight">
<attribute name="target"/>
<element name="files" optional="no" implicit="true" description="Filessets/lists of build files"/>
<sequential>
<apply executable="ant" failonerror="true">
<arg value="-f"/>
<srcfile/>
<arg value="#{target}"/>
<files/>
</apply>
</sequential>
</macrodef>
This is what throws IOException when it hits the line with "apply executeable..".
UPDATED EDIT:
If i set the absolute path like this
<macrodef name="subantlight">
<attribute name="target"/>
<element name="files" optional="no" implicit="true" description="Filessets/lists of build files"/>
<sequential>
<apply executable="MyAbsolutePathHereToAnt.bat" failonerror="true">
<arg value="-f"/>
<srcfile/>
<arg value="#{target}"/>
<files/>
</apply>
</sequential>
</macrodef>
Everything works.
I have set ANT_HOME to my ant directory. I have set my JAVA_HOME to Java JDK directory. In my PATH I have set %ANT_HOME%\bin;%JAVA_HOME%\bin
Calling echo %ANT_HOME% produces the right path.
I can't see what I am during wrong here.
ant with no attributes calls the default target on the build.xml file on the curent path. 'ant all' will call the 'all' target on the same build file.
First - double check the default ant target - is it 'all' or something different? I guess, the default target is not 'all' in your case and the 'all' build includes a build target, that itself calls ant. And this causes the problem.
Hard to tell from here, but scan the build file for an <ant> task inside some <target>. The IO error smells a bit like a violation of user access rights or missing files near/within this <ant> task.
EDIT
the build.xml starts with something like
<project name="Name" default="compile" basedir="/src">
The 'default' attribute names the default target. If the attribute is missing, all top level targets are executed (since ant 1.6) which should include all in your case.
If it works 'for everyone else' then 'everyone else' might have a different environment. Have a look at the environment variable ant references in the script (like 'env.JAVA_HOME' and so on) and compare with the actual environment. Maybe you find a broken path.
Do you have the bin directory of your Ant installation in your PATH? If not, then add it.
It looks like the all target tries to execute Ant (recursively) but can't find it.

specifying classpath for built-in ant tasks

I use the classpath attribute in custom Ant tasks to tell Ant where to find the external task jar, but how do I do the same for built-in tasks?
In my case I'd like to make sure ant uses my copy of jsch.jar for the scp task, and not one that my already be installed on the system. Is there any way I can <scp> while guaranteeing it's using my jsch.jar?
If your ant call uses $ANT_HOME, you could use just for that ant call a special ANT_HOME value to a custom ant installation, where you make sure your $ANT_HOME/lib contains the right copy of ant-jsch.jar.
See this SO question for more.
I think the best way to do it is to define your own task instead of messing with predefined tasks.
<taskdef name="myscp" class="..." classpath="jsch.jar"/>
<myscp .../>
I had the exact same problem and here's what I did: use Google's Jar Jar to change the package names.
Here's the build.xml i used:
<project name="Admin WAS Jython" default="jar">
<target name="jar" >
<taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask"
classpath="jarjar-1.0.jar"/>
<jarjar jarfile="dist/ant-jsch-copy.jar">
<zipfileset src="ant-jsch.jar"/>
<rule pattern="org.apache.tools.ant.taskdefs.optional.ssh.**" result="org.apache.tools.ant.taskdefs.optional.ssh.copy.#1"/>
</jarjar>
</target>
Then in your ant project use the following:
<taskdef name="scp2"
classname="org.apache.tools.ant.taskdefs.optional.ssh.copy.Scp"
classpath="ant-jsch-copy.jar;jsch-0.1.43.jar"/>
and use the scp2 task instead of scp

Categories

Resources