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
Related
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 am considering using XLIFF to standardize localization efforts within the enterprise.
I am very new to xliff and having done some research I figured the following general process to use it:
Extract strings from development project resources (.resx for .Net,
.properties for Java) - the good way to do it as I found is to use
Rainbow from Okapi Localization Toolbox - and use "Utilities =>
Translation Kit Creation" command
Then translate the extracted file, like it is described at
http://www.opentag.com/okapi/wiki/index.php?title=How_to_Translate_XLIFF_Documents
for example using Virtaal application
And finally convert the translated xliff back into original format (resx/properties) - which is possible to do with Rainbow as well "Utilities => Translation Kit Post-Processing"
So far everything is clear, however I would like to know what are the best practices when adding or modifying the string resources? I would prefer not to have all resources to be re-translated every time there is a new string added to the string resources in original format (resx/properties)
That will be also great if there is a versioning support for the translations - so that multiple languages translations will be consolidated (provide the same set of strings) if they are marked with the same version. And version is updated when new string are added or existing strings are modified.
Is there a ready to use solution for this? Or is it something we will have to build on our own?
EDIT:
I found the Diff Leverage step in Okapi Rainbow's Pipeline library, but I have a difficulty to get it working. Here are two xliff files. First one was the first version of the resources that was translated in French, the second one is an file generated from new version of resources with the following changes:
1 string updated (AdminTitleResource is now Administration Resource)
1 string removed (HomeLinkResource is gone)
2 new strings added (Project and Company)
But running Diff Leverage pipeline doesn't produce a smart merge of the translations. Any ideas why?
The translated xliff for previous version of resources:
<?xml version="1.0" encoding="windows-1252"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:okp="okapi-framework:xliff-extensions" version="1.2">
<file original="/Messages.resx" source-language="en-us" target-language="fr-fr" datatype="xml">
<body>
<trans-unit id="1" resname="AccessDenied" xml:space="preserve" approved="yes">
<source xml:lang="en-us">Access denied</source>
<target xml:lang="fr-fr" state="translated">Accès refusé </target>
<note>Error message</note>
</trans-unit>
<trans-unit id="2" resname="AdminTitleResource" xml:space="preserve" approved="yes">
<source xml:lang="en-us">Administration</source>
<target xml:lang="fr-fr" state="translated">Administration</target>
<note></note>
</trans-unit>
<trans-unit id="3" resname="HomeLinkResource" xml:space="preserve" approved="yes">
<source xml:lang="en-us">Main page</source>
<target xml:lang="fr-fr" state="translated">Page web principale</target>
<note></note>
</trans-unit>
<trans-unit id="4" resname="SelectCategoriesResource" xml:space="preserve" approved="yes">
<source xml:lang="en-us">Categories</source>
<target xml:lang="fr-fr" state="translated">Catégories</target>
<note></note>
</trans-unit>
<trans-unit id="5" resname="SelectConfigResource" xml:space="preserve">
<source xml:lang="en-us">Configuration</source>
<target xml:lang="fr-fr" state="needs-review-translation">Paramètres</target>
<note></note>
</trans-unit>
<trans-unit id="6" resname="SelectGroupsResource" xml:space="preserve">
<source xml:lang="en-us">User groups</source>
<target xml:lang="fr-fr" state="needs-review-translation">Utiliser le groupe</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
How do I get XLIFF file with only strings that need to be translated?
The new file with changes listed above:
<?xml version="1.0" encoding="windows-1252"?><xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:okp="okapi-framework:xliff-extensions" version="1.2">
<file original="/Messages_v2.resx" source-language="en-us" target-language="fr-fr" datatype="xml">
<body>
<trans-unit id="1" resname="AccessDenied" xml:space="preserve">
<source xml:lang="en-us">Access denied</source>
<target xml:lang="fr-fr">Access denied</target>
<note>Error message</note>
</trans-unit>
<trans-unit id="2" resname="AdminTitleResource" xml:space="preserve">
<source xml:lang="en-us">Administration Resource</source>
<target xml:lang="fr-fr">Administration Resource</target>
<note></note>
</trans-unit>
<trans-unit id="3" resname="SelectCategoriesResource" xml:space="preserve">
<source xml:lang="en-us">Categories</source>
<target xml:lang="fr-fr">Categories</target>
<note></note>
</trans-unit>
<trans-unit id="4" resname="SelectConfigResource" xml:space="preserve">
<source xml:lang="en-us">Configuration</source>
<target xml:lang="fr-fr">Configuration</target>
<note></note>
</trans-unit>
<trans-unit id="5" resname="SelectGroupsResource" xml:space="preserve">
<source xml:lang="en-us">User groups</source>
<target xml:lang="fr-fr">User groups</target>
<note></note>
</trans-unit>
<trans-unit id="6" resname="Project" xml:space="preserve">
<source xml:lang="en-us">Project</source>
<target xml:lang="fr-fr">Project</target>
<note></note>
</trans-unit>
<trans-unit id="7" resname="Company" xml:space="preserve">
<source xml:lang="en-us">Company</source>
<target xml:lang="fr-fr">Company</target>
<note></note>
</trans-unit>
</body>
</file>
</xliff>
There is an answer for this here:
http://tech.groups.yahoo.com/group/okapitools/message/2494
EDIT: content of linked message
Hi Paul,
I am trying to figure out how to use the diff leverage
to improve the translation experience and get an
update xliff file when merging/leveraging existing
translation with new version of the document with
added/modified/removed strings.
As Jim noted, with XLIFF files you may be able to take advantage of
ID-based steps.
But the Diff leverage step would work too. Here is how to do it:
I've assumed you have the XLIFF files and just want to update them.
You could create pipelines that do additional things like create a
translation kit etc. but this will keep things simple.
First you need to put the new source file in the Input List 1 and the
translated file in the Input List 2.
Then you can create the following pipeline:
Raw document to Filter Events
Diff Leveraging
Filter Events to Raw Document
In the parameters for the Diff Leverage step: make sure the option
"Copy to/over the target" is set.
Then execute the pipeline.
I've attached a comparison (compare_out.html) between the original new
file and the output file. As you can see all the text that could be
leveraged is now in the output. Your entry 'AdminTitleResource' is not
translated because it's the source in the translated file is
different, and your two new entries are also not translated.
You'll also note the new attributes approved='yes' that are there to
indicate the translation was done. That extra flag can be used to
differentiate entries that need translation from the one that have
been leveraged.
For some reason two of the leveraged entries do not have it: I'll have
to look at that and report back. It may be a bug or some condition I
don't recall (maybe Jim does).
The Id-Based Copy step could almost be better. It would copy the
translated text by matching in the resname of the entries. I say
almost because currently it does not look at the source texts, so you
get the translation even if the new source is different (it's not a
'leveraging' step). But we could add an option to make that extra
check and that would make the step work like a leveraging step. I'll
try to find the time do this.
Hope this helps,
-yves
lets say i have an xml file "path.xml" that goes like this:
<paths>
<path id="first">
<url>http://blablabla</url>
</path>
<path id="second">
<url>http://blablabla</url>
</path>
</paths>
i have a jsp file from which i want to read url based on the id.
for example:
i want to write in the jsp file some java code like:String path = get from xml file the "url", where path id = "second".
how is this done in jsp? i am not very experienced with Dom parsing in jsp
thanks a lot:)
You could use XML Tag Library
:
<x:parse doc="path.xml" var="doc" scope="application"/>
<x:out select="$doc/paths/path[id='second']/url"/>
First off, you shouldn't be writing scriptlets in your JSP to perform a processing like this. That should reside in your Java file, not JSP file.
To parse XML with Java, there are tons of examples you will find by just Googling around. Here's one to get you started: http://www.java-tips.org/java-se-tips/javax.xml.parsers/how-to-read-xml-file-in-java.html
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
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.