Ant substring by position - ant

I need to extract a substring from property value by length, f.e. :
<property name="prop1" value="nameBLABLABLA" />
I want get the value
name
Is it possible without using javascript code ?

Not with vanilla ant, you would need to add some Ant addon like Antcontrib (latest release 2006 !) or Ant Flaka - means you'll need additional jars/libraries.
With using the jdk builtin Javascript engine it's as easy as :
<project>
<!-- create a macrodef for reuse -->
<macrodef name="getsubstring">
<attribute name="src"/>
<attribute name="from"/>
<attribute name="to"/>
<attribute name="result"/>
<sequential>
<script language="javascript">
project.setProperty(
"#{result}", "#{src}".substring(#{from},#{to})
);
</script>
</sequential>
</macrodef>
<property name="foo" value="nameBLABLABLA"/>
<getsubstring src="${foo}" from="0" to="4" result="foobar"/>
<echo> $${foobar} => ${foobar}</echo>
</project>
No additional libraries needed.
Created a macrodef that works for properties respectively for strings in general.
The JavaScript engine understands Javascript and Java and you'll get full access to Ant api.

I'd use JavaScript as in Rebse's answer, but there is a way to do this without it using <loadresource> and a <tokenfilter>. This uses start/length rather than from/to for the substring:
<macrodef name="getsubstring">
<attribute name="src"/>
<attribute name="start"/>
<attribute name="length"/>
<attribute name="result"/>
<sequential>
<loadresource property="#{result}">
<string value="#{src}}" />
<filterchain>
<tokenfilter>
<replaceregex pattern="^.{#{start}}(.{#{length}}).*" replace="\1" />
</tokenfilter>
</filterchain>
</loadresource>
</sequential>
</macrodef>
<property name="prop1" value="nameBLABLABLA" />
<getsubstring src="${prop1}" start="0" length="4" result="p"/>
<echo message="${p}" />

Related

How to pass multiple values to one parameter outside the macro def in ant build

How to pass multiple parameters to a target in Ant?
A macrodef is defined as shown below:
<macrodef name="execEtlBinScript">
<attribute name="script" />
<attribute name="resultproperty" />
<sequential>
<exec executable="#{script}" resultproperty="#{resultproperty}" />
</sequential>
</macrodef>
We will be passing the values like this to the above macrodef:
<execEtlBinScript script="somescript" resultproperty="status1" />
But, can I pass like this?
<execEtlBinScript script="somescript, other script" resultproperty="status1, status2" />

Macrodef in Ant : passing a value outside the definition

I have the following macro definition in Ant and I would like to pass the "cmdStatus" value outside this macro def:
<macrodef name="execEtlBinScript">
<attribute name="script" />
<sequential>
<exec executable="#{script}" resultproperty="cmdStatus"/>
</sequential>
</macrodef>
Do you have any idea if it is possible or not ?
Thank you for any help.
Kind regards,
foxrafi
In your exemple, the property cmdStatus is set and is then available outside the macrodef. But I guess that your issue is that if your call several times your macro, you don't get the next status values as properties in Ant are immutable.
The way to handle it properly is to make the result property an attribute of the macro:
<macrodef name="execEtlBinScript">
<attribute name="script" />
<attribute name="resultproperty" />
<sequential>
<exec executable="#{script}" resultproperty="#{resultproperty}"/>
</sequential>
</macrodef>
Then each call to the macrodef will get its value via a different property:
<execEtlBinScript script="somescript" resultproperty="status1" />
<echo message="Result of the first call: ${status1}" />
<execEtlBinScript script="somescript" resultproperty="status2" />
<echo message="Result of the second call: ${status2}" />

How to pass paramters by refrence in ant

Hi all this is my code for target calling.
<target name="abc">
<var name="x" value="10"/>
<antcall target="def"/>
<!--Again Access The value of x here and also change it here-->
</target>
<target name="def">
<!--Access The value of x here and also change it here-->
</target>
and also i want to access this X in other build file,is there any way
This is not possible with ant. In an properties are immutable and cannot be reset. The var task from ant contrib can be used to override values, but should be used sparingly.
You could use a temporary file to achieve what you want. But probably you are trying something weird, which can be solved in a different way.
This would also work across buildfiles if they have access to the property file.
<target name="abc">
<var name="x" value="10"/>
<antcall target="def"/>
<!--Again Access The value of x here and also change it here-->
<var unset="true" file="myproperty.properties" /> <!-- read variable from property file-->
</target>
<target name="def">
<echo file="myproperty.properties" append="false">x=12</echo> <!-- create a new propertyfile-->
</target>
For the sake of justice, there is a hack that allows to alter ant's immutable properties without any additional libs (since java 6):
<scriptdef name="propertyreset" language="javascript"
description="Allows to assing #{property} new value">
<attribute name="name"/>
<attribute name="value"/>
project.setProperty(attributes.get("name"), attributes.get("value"));
</scriptdef>
Usage:
<target name="abc">
<property name="x" value="10"/>
<antcall target="def"/>
</target>
<target name="def">
<propertyreset name="x" value="11"/>
</target>
As #oers mentioned, this should be used with care after all canonical approaches proved not to fit.
It is difficult to suggest further without knowing the goal behind the question.

Ant: Convert class name to file path

How do I convert Java class names into file paths using Ant tasks?
For example, given a property containing foo.bar.Duck I'd like to get out foo/bar/Duck.class.
I tried (and failed) to implement this in terms of <pathconvert> and <regexpmapper>.
Here's a possible way to do this:
<property name="class.name" value="foo.bar.Duck"/>
<loadresource property="file.name">
<string value="${class.name}" />
<filterchain>
<replaceregex pattern="\." replace="/" flags="g" />
<replaceregex pattern="$" replace=".class" />
</filterchain>
</loadresource>
This puts the desired foo/bar/Duck.class into the file.name property.
Here's another way, using Ant resources and an unpackagemapper, which is designed for this purpose. The opposite package mapper is also available.
<property name="class.name" value="foo.bar.Duck"/>
<resources id="file.name">
<mappedresources>
<string value="${class.name}" />
<unpackagemapper from="*" to="*.class" />
</mappedresources>
</resources>
You use the resource value by means of the property helper syntax ${toString:...}, e.g.:
<echo message="File: ${toString:file.name}" />
Yields
[echo] File: foo/bar/Duck.class
I feel using ant script-javascript for this is much simpler
<property name="class.name" value="foo.bar.duck" />
<script language="javascript">
var className = project.getProperty("class.name");
println("before: " + className);
var filePath= className.replace("\\", "/");
println("File Path: "+filePath);
project.setProperty("filePath", filePath);
</script>
<echo message="${filePath}" />
note: that naming your variable same as argument e.g var wsPath may give error, it gave to me!
courtesy: https://stackoverflow.com/a/16099717/4979331

ant macrodefs and element naming

I have a macrodef with a an element called "libs"
<macrodef name="deploy-libs">
<element name="libs"/>
<sequential>
<copy todir="${glassfish.home}/glassfish/domains/domain1/lib">
<fileset dir="${lib}">
<libs/>
</fileset>
</copy>
</sequential>
</macrodef>
which is then invoked as
<deploy-libs>
<libs>
<include name="mysql-connector-*.jar"/>
<include name="junit-*.jar" />
<!-- .... -->
</libs>
</deploy-libs>
I then have another macrodef which calls several macrodefs including "deploy-libs". It would be nice if this macrodef had an element "libs" too but:
<macrodef name="init-glassfish">
<element name="libs"/>
<sequential>
<!-- other stuff -->
<deploy-libs>
<libs>
<libs/>
</libs>
</deploy-libs>
<!-- other stuff -->
</sequential>
</macrodef>
is obviously not working (because of <libs><libs/></libs>):
Commons/ant-glassfish-server.xml:116: unsupported element include
A solution could be to name the element in "init-glassfish" in a different way:
<macrodef name="init-glassfish">
<element name="libraries"/>
<sequential>
<!-- other stuff -->
<deploy-libs>
<libs>
<libraries/>
</libs>
</deploy-libs>
<!-- other stuff -->
</sequential>
</macrodef>
Is there a way to have the element to be named in the same way for both macrodefs?
I found a solution to my question which solves the original problem using a path id
<macrodef name="deploy-libs">
<attribute name="libraries-path-refid"/>
<sequential>
<copy todir="${glassfish.home}/glassfish/domains/domain1/lib">
<path refid="#{libraries-path-refid}"/>
</copy>
</sequential>
</macrodef>
Now this does not solve the issue with the nested elements tags but (XY problem) solves the practical issue. It would be still be nice to know if something similar to the original question is possible.
Apparently, the solution is wrapping additional <libs> elements around in the original call depending on how deep the macros nest. Of course this is a horrible solution because it requires that the macro nesting depth is known on invocation, e.g.:
<deploy-libs>
<libs>
<libs>
<include name="mysql-connector-*.jar"/>
<include name="junit-*.jar" />
<!-- .... -->
</libs>
</libs>
</deploy-libs>
Ant bug 29153 addressing this problem was unfortunately resolved as invalid :(.

Resources