From 753a6c60f47f3ac4f270005b65e9d6481de8eb68 Mon Sep 17 00:00:00 2001
From: Ashlee Young Execute a script in a
+ Apache BSF
+ or
+ JSR 223 supported language.
+ Note:
+ This task depends on external libraries not included in the Apache Ant distribution.
+ See Library Dependencies
+ for more information.
+
+ The task may use the BSF scripting manager or the JSR 223 manager that
+ is included in JDK6 and higher. This is controlled by the All items (tasks, targets, etc) of the running project are
+ accessible from the script, using either their If you are using JavaScript under BSF, a good resource is
+http://www.mozilla.org/rhino/doc.html as we are using their JavaScript interpreter. Scripts can do almost anything a task written in Java could do. Rhino provides a special construct - the JavaAdapter. With that you can
+create an object which implements several interfaces, extends classes and for which you
+can overwrite methods. Because this is an undocumented feature (yet), here is the link
+to an explanation:
+Groups@Google: "Rhino, enum.js, JavaAdapter?" by Norris Boyd in the newsgroup
+netscape.public.mozilla.jseng. If you are creating Targets programmatically, make sure you set the
+Location to a useful value. In particular all targets should have
+different location values. Since Ant 1.7
+
+ If a classpath is set, it will be used as the current thread
+ context classloader, and
+ as the classloader given to the BSF manager.
+ This means that it can be used to specify
+ the classpath containing the language implementation for BSF
+ or for JSR 223 managers.
+ This can be useful if one wants
+ to keep ${user.home}/.ant/lib free of lots of scripting language
+ specific jar files.
+
+ NB: (Since Ant 1.7.1)
+ This classpath can be used to
+ specify the location of
+ the BSF jar file and/or languages
+ that have engines in the BSF jar file. This includes the
+ javascript, jython, netrexx and jacl languages.
+ Script
+Description
+ manager
+ attribute. The JSR 223 scripting manager is indicated by "javax".
+ name
or
+ id
attributes (as long as their names are considered
+ valid Java identifiers, that is).
+ This is controlled by the "setbeans" attribute of the task.
+ The name "project" is a pre-defined reference to the Project, which can be
+ used instead of the project name. The name "self" is a pre-defined reference to the actual
+ <script>
-Task instance.
From these objects you have access to the Ant Java API, see the
+JavaDoc (especially for
+Project and
+Script) for more information.Parameters
+
+
+
+
+ Attribute
+ Description
+ Required
+
+
+ language
+ The programming language the script is written in.
+ Must be a supported Apache BSF or JSR 223 language
+ Yes
+
+
+ manager
+
+ Since: Ant 1.7.
+ The script engine manager to use. This can have
+ one of three values ("auto", "bsf" or "javax").
+ The default value is "auto".
+
+
+
No
+
+
+ src
+ The location of the script as a file, if not inline
+ No
+
+
+ setbeans
+
+ This attribute controls whether to set variables for
+ all properties, references and targets in the running script.
+ If this attribute is false, only the the "project" and "self" variables are set.
+ If this attribute is true all the variables are set. The default value of this
+ attribute is "true". Since Ant 1.7
+
+ No
+
+
+ classpath
+
+ The classpath to pass into the script. Since Ant 1.7
+
+ No
+
+
+classpathref
+ The classpath to use, given as a
+ reference to a path defined elsewhere.
+ Since Ant 1.7
+ No
+ Parameters specified as nested elements
+classpath
+ Script
's classpath
attribute is a
+ path-like structure and can also be set via a nested
+ <classpath>
element.
+
++ <property name="message" value="Hello world"/> + + <script language="groovy"> + println("message is " + message) + </script> + + <script language="beanshell"> + System.out.println("message is " + message); + </script> + + <script language="judoscript"> + println 'message is ', message + </script> + + <script language="ruby"> + print 'message is ', $message, "\n" + </script> + + <script language="jython"> +print "message is %s" % message + </script> ++
+ Note that for the jython example, the script contents must + start on the first column. +
++ Note also that for the ruby example, the names of the set variables are prefixed + by a '$'. +
+ The following script shows a little more complicated jruby example: +
+++<script language="ruby"> + xmlfiles = Dir.new(".").entries.delete_if { |i| ! (i =~ /\.xml$/) } + xmlfiles.sort.each { |i| $self.log(i) } +</script> ++
+ The same example in groovy is: +
+++<script language="groovy"> + xmlfiles = new java.io.File(".").listFiles().findAll{ it =~ "\.xml$"} + xmlfiles.sort().each { self.log(it.toString())} +</script> ++
+ The following example shows the use of classpath to specify the location + of the beanshell jar file. +
+++<script language="beanshell" setbeans="true"> + <classpath> + <fileset dir="${user.home}/lang/beanshell" includes="*.jar" /> + </classpath> + System.out.println("Hello world"); +</script> ++
+ The following script uses javascript to create a number of + echo tasks and execute them. +
+++<project name="squares" default="main" basedir="."> + + <target name="main"> + + <script language="javascript"> <![CDATA[ + + for (i=1; i<=10; i++) { + echo = squares.createTask("echo"); + echo.setMessage(i*i); + echo.perform(); + } + + ]]> </script> + + </target> + +</project> +
generates
++ ++main: +1 +4 +9 +16 +25 +36 +49 +64 +81 +100 + +BUILD SUCCESSFUL +
Now a more complex example using the Java API and the Ant API. The goal is to list the
+filesizes of all files a <fileset/>
caught.
++ +<?xml version="1.0" encoding="ISO-8859-1"?> +<project name="MyProject" basedir="." default="main"> + + <property name="fs.dir" value="src"/> + <property name="fs.includes" value="**/*.txt"/> + <property name="fs.excludes" value="**/*.tmp"/> + + <target name="main"> + <script language="javascript"> <![CDATA[ + + // import statements + // importPackage(java.io); + importClass(java.io.File); + + // Access to Ant-Properties by their names + dir = project.getProperty("fs.dir"); + includes = MyProject.getProperty("fs.includes"); + excludes = self.getProject() .getProperty("fs.excludes"); + + // Create a <fileset dir="" includes=""/> + fs = project.createDataType("fileset"); + fs.setDir( new File(dir) ); + fs.setIncludes(includes); + fs.setExcludes(excludes); + + // Get the files (array) of that fileset + ds = fs.getDirectoryScanner(project); + srcFiles = ds.getIncludedFiles(); + + // iterate over that array + for (i=0; i<srcFiles.length; i++) { + + // get the values via Java API + var basedir = fs.getDir(project); + var filename = srcFiles[i]; + var file = new File(basedir, filename); + var size = file.length(); + + // create and use a Task via Ant API + echo = MyProject.createTask("echo"); + echo.setMessage(filename + ": " + size + " byte"); + echo.perform(); + } + ]]></script> + </target> +</project> +
We want to use the Java API. Because we don't want always typing the package signature
+we do an import. Rhino knows two different methods for import statements: one for packages
+and one for a single class. By default only the java packages are available, so
+java.lang.System can be directly imported with importClass/importPackage
.
+For other packages you have to prefix the full classified name with Packages.
+For example Ant's FileUtils class can be imported with
+importClass(Packages.org.apache.tools.ant.util.FileUtils)
+
+The <script>
task populates the Project instance under
+the name project, so we can use that reference. Another way is to use its given name
+or getting its reference from the task itself.
+The Project provides methods for accessing and setting properties, creating DataTypes and
+Tasks and much more.
+After creating a FileSet object we initialize that by calling its set-methods. Then we can
+use that object like a normal Ant task (<copy>
for example).
+For getting the size of a file we instantiate a java.io.File
. So we are using
+normal Java API here.
+Finally we use the <echo>
task for producing the output. The task is not executed by
+its execute() method, because the perform() method (implemented in Task itself) does the
+appropriate logging before and after invoking execute().
+
+ Here is an example of using beanshell to create an ant + task. This task will add filesets and paths to a referenced + path. If the path does not exist, it will be created. +
+++<!-- + Define addtopath task + --> +<script language="beanshell"> + import org.apache.tools.ant.Task; + import org.apache.tools.ant.types.Path; + import org.apache.tools.ant.types.FileSet; + public class AddToPath extends Task { + private Path path; + public void setRefId(String id) { + path = getProject().getReference(id); + if (path == null) { + path = new Path(getProject()); + getProject().addReference(id, path); + } + } + public void add(Path c) { + path.add(c); + } + public void add(FileSet c) { + path.add(c); + } + public void execute() { + // Do nothing + } + } + project.addTaskDefinition("addtopath", AddToPath.class); +</script> +
+ An example of using this task to create a path + from a list of directories (using antcontrib's + + <for> task) follows: +
++ + + -- cgit 1.2.3-korg+<path id="main.path"> + <fileset dir="build/classes"/> +</path> +<ac:for param="ref" list="commons,fw,lps" + xmlns:ac="antlib:net.sf.antcontrib"> + <sequential> + <addtopath refid="main.path"> + <fileset dir="${dist.dir}/@{ref}/main" + includes="**/*.jar"/> + </addtopath> + </sequential> +</ac:for> +