Does Ant have any way of doing string uppercase/lowercase/captialize/uncaptialize string manipulations? I looked at PropertyRegex but I don't believe the last two are possible with that. Is that anything else?
From this thread, use an Ant <script> task:
<target name="capitalize">
<property name="foo" value="This is a normal line that doesn't say much"/>
<!-- Using Javascript functions to convert the string -->
<script language="javascript"> <![CDATA[
// getting the value
sentence = project.getProperty("foo");
// convert to uppercase
lowercaseValue = sentence.toLowerCase();
uppercaseValue = sentence.toUpperCase();
// store the result in a new property
project.setProperty("allLowerCase",lowercaseValue);
project.setProperty("allUpperCase",uppercaseValue);
]]> </script>
<!-- Display the values -->
<echo>allLowerCase=${allLowerCase}</echo>
<echo>allUpperCase=${allUpperCase}</echo>
</target>
Output
D:\ant-1.8.0RC1\bin>ant capitalize
Buildfile: D:\ant-1.8.0RC1\bin\build.xml
capitalize:
[echo] allLowerCase=this is a normal line that doesn't say much
[echo] allUpperCase=THIS IS A NORMAL LINE THAT DOESN'T SAY MUCH
BUILD SUCCESSFUL
Update for WarrenFaith's comment to separate the script into another target and pass a property from the called target back to the calling target
Use antcallback from the ant-contrib jar
<target name="testCallback">
<antcallback target="capitalize" return="allUpperCase">
<param name="param1" value="This is a normal line that doesn't say much"/>
</antcallback>
<echo>a = ${allUpperCase}</echo>
</target>
and capitalise task uses the passed in param1 thus
<target name="capitalize">
<property name="foo" value="${param1}"/>
Final output
[echo] a = THIS IS A NORMAL LINE THAT DOESN'T SAY MUCH
you could use the script task and use a jsr223-supported script language like javascript, jruby, jython,... to do your string handling
Related
I have an XML file with the following content:
<root-tag>
<entry name="name1" value="/usr/bin" />
<entry name="full_path" value="${name2}" />
<entry name="name2" value="${name1}/dpkg" />
</root-tag>
I want to read this file in Ant and put the attribute value of value in the <entry> node whose name value is "full_path" into a property with Ant.
I can easily do this, e.g. using <xmltask> with its <copy> element:
<copy path="root-tag/entry[#name='full_path']/#value" property="outputProperty" />
However, what I get is ${name2}, which is meaningless to me. I need ${name2} to be resolved into the ${name1}/dpkg and then the ${name1} part is resolved into /usr/bin, as a result, /usr/bin/dpkg.
And I must look for "full_path" because the other two names can't be predicted.
Since this is not entity reference, <xmltask> can't automatically expand it.
How should I achieve my goal in Ant build file?
You can use anttask propertycopy for the same.
Refer link - http://ant-contrib.sourceforge.net/tasks/tasks/propertycopy.html
I'm defining a macrodef in Ant, and using javascript to do the work. In this case I'm validating a timezone.
<macrodef name="validateTimeZone">
<attribute name="zone" />
<sequential>
<echo>result: ${envTZResult}</echo>
<echo> validating timezone: #{zone}</echo>
<script language="javascript"><![CDATA[
importClass(java.util.TimeZone);
importClass(java.util.Arrays);
var tz = project.getProperty("zone");
println(" got attribute: " + tz);
var result = Arrays.asList(TimeZone.getAvailableIDs()).contains(tz); //testing if timezone is known
project.setProperty("zoneIsValid", result);
]]>
</script>
</sequential>
</macrodef>
The problem is project.getProperty() doesn't retrieve values of passed attributes. Does somebody know how you could get the value of the attribute from within the javascript?
Turns out I was using the wrong type of tag. For using scripting to define an ant task, I should have used scriptdef and not macrodef. With scriptdef there are predefined objects to access the attributes and nested elements in your task.
This works for accessing attributes from javascript in Ant:
<scriptdef name="validateTimeZone" language="javascript">
<attribute name="zone" />
<![CDATA[
importClass(java.util.TimeZone);
importClass(java.util.Arrays);
var tz = attributes.get("zone"); //get attribute defined for scriptdef
println(" got attribute: " + tz);
var result = Arrays.asList(TimeZone.getAvailableIDs()).contains(tz); //testing if timezone is known
project.setProperty("zoneIsValid", result);
]]>
</scriptdef>
Best is to create a property with attribute as value, i.e.
<macrodef name="validateTimeZone">
<attribute name="zone" />
<sequential>
<echo>result: ${envTZResult}</echo>
<echo> validating timezone: #{zone}</echo>
<!-- edit use local with ant 1.8.x -->
<local name="zone"/>
<property name="zone" value="#{zone}"/>
<script language="javascript"><![CDATA[
importClass(java.util.TimeZone);
importClass(java.util.Arrays);
var tz = project.getProperty("zone");
println(" got attribute: " + tz);
var result = Arrays.asList(TimeZone.getAvailableIDs()).contains(tz); //testing if timezone is known
project.setProperty("zoneIsValid", result);
]]>
</script>
</sequential>
</macrodef>
I'm trying to do this in Ant:
<echo message="[44;1;37mSuccess![m" />
But it doesn't work:
BUILD FAILED
./build.xml:92: Character reference "&#
How to do it?
The 0x1B character is invalid in XML contents (Invalid Characters in XML). So you need some workaround. I would go with a javascript workaround, but I give also 2 additional solutions:
javascript
<script language="javascript">
project.setNewProperty("esc", "\u001b");
</script>
<echo>${esc}</echo>
native2ascii
If you want the output in a file, then you could first output it using java escape \u001b, then convert it using reverse Native2Ascii routine. Regardless of the selected encoding it always decodes \u sequences.
<echo file="a.enc">\u001b</echo>
<native2ascii includes="a.enc" ext=".txt" dest="${basedir}"
encoding="iso-8859-1" reverse="true" />
property file
Finally you may have the unfortunate string constant in a file:
<property file="prop.txt" />
<echo>myEsc:${myEsc}</echo>
while the prop.txt contents is:
myEsc=\u001b
Simply use CDATA :
<project>
<echo><![CDATA[
[44;1;37mSuccess![m
]]>
</echo>
</project>
& is a special character in ant, so you should replace it with '
<echo message="[44;1;37mSuccess![m" />
I have an XML file of the following form -
<map MAP_XML_VERSION="1.0">
<entry key="database.user" value="user1"/>
...
</map>
Does ant have a native ability to read this and let me perform an xquery to pull back values for keys? Going through the API I did not see such capabilities.
The optional Ant task XMLTask is designed to do this. Give it an XPath expression and you can select the above into (say) a property. Here's an article on how to use it, with examples. It'll do tons of other XML-related manipulations/querying/creation as well.
e.g.
<xmltask source="map.xml">
<!-- copies to a property 'user' -->
<copy path="/map/entry[#key='database.user']/#value" attrValue="true" property="user"/>
</xmltask>
Disclaimer: I'm the author.
You can use the scriptdef tag to create a JavaScript wrapper for your class. Inside JS, you pretty much have the full power of Java and can do any kind of complicated XML parsing you want.
For example:
<project default="build">
<target name="build">
<xpath-query query="//entry[#key='database.user']/#value"
xmlFile="test.xml" addproperty="value"/>
<echo message="Value is ${value}"/>
</target>
<scriptdef name="xpath-query" language="javascript">
<attribute name="query"/>
<attribute name="xmlfile"/>
<attribute name="addproperty"/>
<![CDATA[
importClass(java.io.FileInputStream);
importClass(javax.xml.xpath.XPath);
importClass(javax.xml.xpath.XPathConstants);
importClass(javax.xml.xpath.XPathFactory);
importClass(org.xml.sax.InputSource);
var exp = attributes.get("query");
var filename = attributes.get("xmlfile");
var input = new InputSource(new FileInputStream(filename));
var xpath = XPathFactory.newInstance().newXPath();
var value = xpath.evaluate(exp, input, XPathConstants.STRING);
self.project.setProperty( attributes.get("addproperty"), value );
]]>
</scriptdef>
</project>
Sounds like you want something like ant-xpath-task. I'm not aware of a built-in way to do this with Ant.
I'm currently in the process of replacing my homebrewn build script by an Ant build script.
Now I need to replace various tokens by the size of a specific file. I know how to get the size in bytes via the <length> task and store in in a property, but I need the size in kilobytes and megabytes too.
How can I access the file size in other representations (KB, MB) or compute these values from within the Ant target and store them in a property?
Edit: After I discovered the <script> task, it was fairly easy to calculate the other values using some JavaScript and add a new property to the project using project.setNewProperty("foo", "bar");.
I found a solution that does not require any third-party library or custom tasks using the <script> task that allows for using JavaScript (or any other Apache BSF or JSR 223 supported language) from within an Ant target.
<target name="insert-filesize">
<length file="${afile}" property="fs.length.bytes" />
<script language="javascript">
<![CDATA[
var length_bytes = project.getProperty("fs.length.bytes");
var length_kbytes = Math.round((length_bytes / 1024) * Math.pow(10,2))
/ Math.pow(10,2);
var length_mbytes = Math.round((length_kbytes / 1024) * Math.pow(10,2))
/ Math.pow(10,2);
project.setNewProperty("fs.length.kb", length_kbytes);
project.setNewProperty("fs.length.mb", length_mbytes);
]]>
</script>
<copy todir="${target.dir}">
<fileset dir="${source.dir}">
<include name="**/*" />
<exclude name="**/*.zip" />
</fileset>
<filterset begintoken="$$$$" endtoken="$$$$">
<filter token="SIZEBYTES" value="${fs.length.bytes}"/>
<filter token="SIZEKILOBYTES" value="${fs.length.kb}"/>
<filter token="SIZEMEGABYTES" value="${fs.length.mb}"/>
</filterset>
</copy>
</target>
There is a math task at http://ant-contrib.sourceforge.net/ that may be useful