Set a system property with ant - ant

I have an ant script which has a taskdef and the task creates an https internet connection and somethin with that SSL stuff is wrong. Thus I want to set the system property javax.net.debug=all to get some more information.
In java I would do this using the -D option, but in ant this is used for ant properties which is not the same as a system property.
If this wouldn't be a taskdef but instead a java task, I could use the sysproperty property, but it is no java-task.
Googling for this is frustratingly complicated because ant properties and system properties in ant are so similar that most search results are about the other (or about the java-task).
Obviously I am not the only one with the problem, but other people's questions that I have found (like here) are unanswered or went for hack (like here).

One way to set such a property is the ANT_OPTS system variable. You have to be very carefully to not simply skim over answers on google that state that options can be set that way, because it sounds so much like not what it does:
The documentation says:
ANT_OPTS - command-line arguments that should be passed to the JVM.
For example, you can define system properties or set the maximum Java
heap size here.
Who what have expected that? ANT_OPTS are options for the JVM and not for ant like the name suggests. The var which is used for ant options is called ANT_ARGS.
Now I can launch ant like this: ANT_OPTS="-Djavax.net.debug=all" ant myTarget and can see tons of log output.
(However this leaves the question open whether such a variable can be set using XML).

You can declare system properties in the xml with <sysproperty key="key" value="value"/>.
http://www.java2s.com/Code/Java/Ant/SetsystempropertiesinAntbuildscript.htm

You can use scripting:
<script language="javascript">
java.lang.System.setProperty('myKey', 'myValue');
</script>

Related

ant ${java.home} points to $JAVA_HOME/jre, not $JAVA_HOME

When trying to compile a Javadoc taglet, which requires $JAVA_HOME/lib/tools.jar, I discovered that ant (version 1.8.4) sets java.home to $JAVA_HOME/jre rather than just $JAVA_HOME. I verified this thusly:
<echo>${java.home}</echo>
<echo>${env.JAVA_HOME}</echo>
[echo] /usr/java/jdk1.7.0_21/jre
[echo] /usr/java/jdk1.7.0_21
According to ant -diagnostics, there isn't any property like a jdk.home. Thus, to use tools.jar I have to do:
<classpath location="${java.home}/../lib/tools.jar"/>
So, I have two questions:
1) Is there something wrong with my setup of ant that's causing java.home to point to the JRE instead of the JDK?
2) If this is the way ant is supposed to work, is using the .. in my classpath the way I'm supposed to do things? Or should I do ${env.JAVA_HOME}/lib/tools.jar? Or something else entirely?
Here are the answers:
"Is there something wrong with my setup ...?" No. Ant is setting it's internal java.home based on JVM System properties. The code for HotSpot (JVM internals) sets it with "/jre" appended on purpose. In fact, the Java(TM) Tutorials for System Properties describes it exactly that way. The "java.home" variable from inside ant really isn't one-in-the-same as the "JAVA_HOME" that is set in your environment -- different but with similar names.
"(What is) the way I'm supposed to do things?" You can really do whatever you feel is appropriate, but remember that Ant can and usually does run in a separate JVM process. I'd assume that your system environment is probably specifying the JVM that was used to develop the app, so I would just use "${env.JAVA_HOME}" to ensure that development expectations meet build expectations.
For more information, please see another similar answer here.
Also, consider that more info can be collected from ant by running it with the -debug, -diagnostics and/or -verbose flags.
Had the same problem. I found that adding fork="true" to the javac tag solves this issue. So do something like this:
<javac target="1.7" source="1.7" fork="true" ...>
I will thank whoever can explain why this works.

Dynamic basedir for Ant in Eclipse

The title might not be the best so let me explain what I am trying to do.
I have made an Ant buildfile that will help me with Maven goals. It's so much easier having to scope to Ant view and choose what I want to do. The biggest benefit with this is that I can use it in almost any project. Whether I deploy to tomcat or jboss or sakai(:deploy) or I handle mutiple instaces of the same server or skip tests... worst case I just change some path properties.
The drawback right now is that I have to keep a copy of this buildfile in every project.
What I am trying to do is have only 1 buildfile, in the workspace, and dinamicaly optain, from eclipse, the current project that I am working on. Be it module or parent I can refine that later.
So basically change the basedir for ant tasks based on the selected project in eclipse.
I have tried Ant Runtime Properties but for some reason properties like
${project_path}
fail to give me what their description say. I get this:
Variable references empty selection: ${project_path}
I hope it is clear what I am trying to do. So my question, I know it's possible, I'm just missing something and I hope some of you can help me with this.
I believe the trouble is in the Ant Runtime properties. I'm not 100% sure how I should use those.
Thank you!
EDIT after comment and further investigation..
Make the projectdir available as basedir property for ant like that :
Window > Preferences > Ant > Runtime > Properties
and create a property named basedir with value either :
${project_loc}
or
${workspace_loc}/${project_name}
and
<project basedir="${basedir}">
<echo>$${basedir} = ${basedir}</echo>
</project>
will work as expected, means echoing eclipse/yourworkspace/projectdir
Maybe there are other ways, i.e. via Ant Addon Ant4Eclipse, which aims to make Eclipse settings available for ant, never used it.

Is it possible to display the call "graph" of an ant extension-point?

I have an extension-point defined in ant :
<extension-point name="foo"/>
A lot of tasks contribute to this point in several imported ant files :
<bindtargets targets="bar" extensionPoint="foo" />
However I'm kinda lost as to exactly which tasks are contributing. Is there a way to have ant report the tasks that would be triggered by a given extension point ? More generaly, is there a way to display the "call-graph" (or simply the list of dependencies) of an ant task ?
I tried using verbose options for ant (-v and such), with no luck.
Thanks
First of all, you can try to debug the ANT process in your IDE using remote debugging by adding some parameters to ANT_OPTS (mine is set in ~/.profile):
http://blog.dahanne.net/2010/06/03/debugging-any-java-application/
And profiling may help. I found project Antro on ANT Wiki...
http://sourceforge.net/projects/antro
Maybe you can try it out. The project is said to be designed for ANT, which looks promising in solving your problem.
Also you can use Yourkit Java Profiler to do a CPU profiling. YJP can show the call graph of a java application, but I'm not sure if one can find out which are ANT targets.
The following document shows how to start a java application with YJP agent.
http://www.yourkit.com/docs/95/help/agent.jsp
I know of 2 ways to get this information:
You can get the effective target/extension-point invocation sequence from Ant's console logger. To do this, place Ant's logging facility into verbose mode by passing -verbose on the command line to Ant. There are two lines, one after the other, that dump to the console immediately before most targets as they are invoked in your build script:
A line that shows a summary of the targets in the call sequence starting with the text, Build sequence for target(s) 'artifact' is [...].
A line showing the detailed call sequence (nested targets and antcalls included). This line starts with the text, Complete build sequence is [...]. This listing considers, as much as reasonably possible, the evaluation of any if and unless attributes of each target listed at the point the line is logged to the console.
Simply invoke your Ant build as you would normally with the -verbose option and your console should have the information you're looking for.
You can get a pictorial representation of the call sequence using a tool called Grand. However, it hasn't been updated for quite some time and thus doesn't support extension-points (which is what you're concerned with here). It will interpret antcall's, ant, and depend'encies. It doesn't evaluate the if and unless attributes but simply identifies potential execution sequence - more of a dependency hierarchy than an actual call graph. The project is on Github so an update to support extension-points may not be too difficult.
The graphic is rendered using Graphviz.
For an actual call sequence, use option 1.
This is pretty sloppy, but it works. Ant is actually pretty easily scripted, and if you are using at least Java 6 (or it might be Java 7), javascript support is built in and thus can be used right out of the box. This defines a task that will echo the dependencies of any target in call order:
<scriptdef name="listdepends" language="javascript">
<attribute name="target"/>
<![CDATA[
var done = [];
var echo = project.createTask("echo")
function listdepend(t) {
done.push(t.getName());
var depends = t.getDependencies();
while (depends.hasMoreElements()) {
var t2 = depends.nextElement();
if (done.indexOf(t2)==-1) listdepend(project.getTargets().get(t2));
}
echo.setMessage(t.getName());
echo.perform();
}
var t = attributes.get("target");
if (t!=null) {
var targ = project.getTargets().get(t);
listdepend(targ);
}
]]>
</scriptdef>
In your case, you can create a new target (or not) and call it like so:
<target name="listfoo">
<listdepends target="foo"/>
</target>
As I said, this is somewhat sloppy. It probably isn't very fast (although unless your target triggers thousands of others, it probably isn't noticeably slow). It won't handle antcall tasks (although it could be modified to do so easily) or respond to if and unless attributes. If dependencies nest too far, it may hit a recursion depth limit (but I doubt any project nest them deep enough).
The array is used to make sure that each dependency is listed once (ant would only run them once).

Dynamic property names in ant

I am reading a file in ant and loading the properties through loadproperties. I am interested in using the value of a specific property, whose name is not known. I know that it follows a pattern because that is how I load the property.
I can echoproperties and see that it is being loaded.
But I dont know how to access its value, given that its name is actually a pattern rather that hardcoded.
How can I access this property's value to do some processing.
I hope this is clear. Please ask if I need to clarify some more.
Take a look at ant-contrib package. Its propertycopy task will do what you need. If you need to resolve an arbitrary number of properties following an established pattern, you would use ant-contrib's propertycopy in conjunction with ant-contribs "for" task.
http://ant-contrib.sourceforge.net/tasks/tasks/index.html
You should use Ant's script task.
I suggest using the beanshell script since it is pure java.
For example, to print all properties for your project, use the following:
<target name="echoprops">
<script language="beanshell">
System.out.println("All Properties: " + project.getProperties().keySet());
</script>
</target>
It should be easy to modify the above script to get the property you want.
To use this task, you will need to run the following in $ANT_HOME first:
ant -f fetch.xml script -Ddest=user
That will download all required optional jars to ~/.ant/lib .

Ant output to 2 different sources?

I'm running Ant with output fed to a log file:
ant -logfile file.txt target-name
I'd also like to print some simple progress information to the console though. The answer seems to be a BuildEvent listener that writes to the console every time a new target is hit, but the documentation explicitly states:
A listener must not access System.out and System.err directly since ouput on these streams is redirected by Ant's core to the build event system.
Did I miss something? Is there a way to do this?
Ant replaces the System.out & System.err streams to remap messages printed there through it's own logging system.
That said, you can still get access to the ACTUAL OS streams by using java.io.FileDescriptor#out
Actually, the answer is Log4jListener.
There is a sample log4j configuration for logging into both console and file shown in the above link. You can then use an <echo> task with an appropriate level parameter to selectively decide what gets printed to console.
Thanks for the answers! I'm slow, but this is still something that I'd like to get right.
I've managed to get something working more or less like I want using carej's suggested approach with the java.io.FileDescriptor#out stream and an Ant scriptdef like this:
<scriptdef name="progress-text" language="javascript" >
output = new java.io.PrintStream(new java.io.FileOutputStream(java.io.FileDescriptor.err))
output.println(self.text)
</scriptdef>
Now I'm just left wondering how wize is this approach? Is there inherit risk in using the underlying OS streams directly?
EDIT:
2 Points which might be useful to anyone else with a similar question:
This article has a very good description of the Ant I/O system: http://codefeed.com/blog/?p=68
java.lang.System does something very similar to set System.out and System.err in the first place.
All of this gave me a little more confidence in this approach.

Resources