git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@439681 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -4,6 +4,8 @@ Changes from current Ant 1.7.0Beta1 version to current SVN version | |||||
| Changes that could break older environments: | Changes that could break older environments: | ||||
| ------------------------------------------- | ------------------------------------------- | ||||
| * <script> and <scriptdef> now set the current thread context. | |||||
| Fixed bugs: | Fixed bugs: | ||||
| ----------- | ----------- | ||||
| @@ -14,6 +16,13 @@ Fixed bugs: | |||||
| Other changes: | Other changes: | ||||
| -------------- | -------------- | ||||
| * added setbeans attribute to <script> to allow <script>'s to be | |||||
| run without referencing all references. | |||||
| Bugzilla report 37688. | |||||
| * added classpath attribute and nested element to <script> to allow | |||||
| the language jars to be specified in the build script. | |||||
| Bugzilla report 29676. | |||||
| Changes from Ant 1.6.5 to Ant 1.7.0Beta1 | Changes from Ant 1.6.5 to Ant 1.7.0Beta1 | ||||
| ======================================== | ======================================== | ||||
| @@ -18,6 +18,7 @@ See <a href="../install.html#librarydependencies">Library Dependencies</a> for m | |||||
| accessible from the script, using either their <code>name</code> or | accessible from the script, using either their <code>name</code> or | ||||
| <code>id</code> attributes (as long as their names are considered | <code>id</code> attributes (as long as their names are considered | ||||
| valid Java identifiers, that is). | 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 | 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 | used instead of the project name. The name "self" is a pre-defined reference to the actual | ||||
| <code><script></code>-Task instance.<br>From these objects you have access to the Ant Java API, see the | <code><script></code>-Task instance.<br>From these objects you have access to the Ant Java API, see the | ||||
| @@ -54,7 +55,50 @@ Groups@Google: "Rhino, enum.js, JavaAdapter?"</a> by Norris Boyd in the newsgrou | |||||
| <td valign="top">The location of the script as a file, if not inline</td> | <td valign="top">The location of the script as a file, if not inline</td> | ||||
| <td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
| </tr> | </tr> | ||||
| <tr> | |||||
| <td valign="top">setbeans</td> | |||||
| <td valign="top"> | |||||
| 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". <em>Since Ant 1.7</em> | |||||
| </td> | |||||
| <td valign="top" align="center">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">classpath</td> | |||||
| <td valign="top"> | |||||
| The classpath to pass into the script. <em>Since Ant 1.7</em> | |||||
| </td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| <tr> | |||||
| <td valign="top">classpathref</td> | |||||
| <td valign="top">The classpath to use, given as a | |||||
| <a href="../using.html#references">reference</a> to a path defined elsewhere. | |||||
| <em>Since Ant 1.7</em></td> | |||||
| <td align="center" valign="top">No</td> | |||||
| </tr> | |||||
| </table> | </table> | ||||
| <h3>Parameters specified as nested elements</h3> | |||||
| <h4>classpath</h4> | |||||
| <p><em>Since Ant 1.7</em></p> | |||||
| <p> | |||||
| <code>Script</code>'s <code>classpath</code> attribute is a | |||||
| <a href="../using.html#path">path-like structure</a> and can also be set via a nested | |||||
| <code><classpath></code> element. | |||||
| <p> | |||||
| 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. This can be usefull if one wants | |||||
| to keep ${user.home}/.ant/lib free of lots of scripting language specific jar files. | |||||
| </p> | |||||
| <p> | |||||
| <b>NB:</b> This classpath cannot (currently) be used to specify the location of | |||||
| the BSF jar file. | |||||
| </p> | |||||
| </p> | |||||
| <h3>Examples</h3> | <h3>Examples</h3> | ||||
| The following snippet shows use of five different languages: | The following snippet shows use of five different languages: | ||||
| <blockquote><pre> | <blockquote><pre> | ||||
| @@ -85,6 +129,9 @@ print "message is %s" % message | |||||
| Note that for the <i>jython</i> example, the script contents <b>must</b> | Note that for the <i>jython</i> example, the script contents <b>must</b> | ||||
| start on the first column. | start on the first column. | ||||
| </p> | </p> | ||||
| <p> | |||||
| Note also that for the <i>ruby</i> example, the names of the set variables are prefixed | |||||
| by a '$'. | |||||
| <p> | <p> | ||||
| The following script shows a little more complicated jruby example: | The following script shows a little more complicated jruby example: | ||||
| </p> | </p> | ||||
| @@ -103,6 +150,19 @@ print "message is %s" % message | |||||
| xmlfiles = new java.io.File(".").listFiles().findAll{ it =~ "\.xml$"} | xmlfiles = new java.io.File(".").listFiles().findAll{ it =~ "\.xml$"} | ||||
| xmlfiles.sort().each { self.log(it.toString())} | xmlfiles.sort().each { self.log(it.toString())} | ||||
| </script> | </script> | ||||
| </pre> | |||||
| </blockquote> | |||||
| <p> | |||||
| The following example shows the use of classpath to specify the location | |||||
| of the beanshell jar file. | |||||
| </p> | |||||
| <blockquote><pre> | |||||
| <script language="beanshell" setbeans="true"> | |||||
| <classpath> | |||||
| <fileset dir="${user.home}/lang/beanshell" includes="*.jar" /> | |||||
| </classpath> | |||||
| System.out.println("Hello world"); | |||||
| </script> | |||||
| </pre> | </pre> | ||||
| </blockquote> | </blockquote> | ||||
| <p> | <p> | ||||
| @@ -257,7 +317,7 @@ appropriate logging before and after invoking execute(). | |||||
| <hr> | <hr> | ||||
| <p align="center">Copyright © 2000-2005 The Apache Software Foundation. All rights | |||||
| <p align="center">Copyright © 2000-2006 The Apache Software Foundation. All rights | |||||
| Reserved.</p> | Reserved.</p> | ||||
| </body> | </body> | ||||
| @@ -21,6 +21,8 @@ import java.io.File; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.Task; | import org.apache.tools.ant.Task; | ||||
| import org.apache.tools.ant.util.ScriptRunner; | import org.apache.tools.ant.util.ScriptRunner; | ||||
| import org.apache.tools.ant.types.Path; | |||||
| import org.apache.tools.ant.types.Reference; | |||||
| /** | /** | ||||
| * Executes a script. | * Executes a script. | ||||
| @@ -29,9 +31,11 @@ import org.apache.tools.ant.util.ScriptRunner; | |||||
| */ | */ | ||||
| public class Script extends Task { | public class Script extends Task { | ||||
| private String language; | |||||
| private File src; | |||||
| private String text; | |||||
| private Path classpath; | |||||
| private String language; | |||||
| private File src; | |||||
| private String text; | |||||
| private boolean setBeans = true; | |||||
| /** | /** | ||||
| * Do the work. | * Do the work. | ||||
| @@ -49,8 +53,14 @@ public class Script extends Task { | |||||
| if (text != null) { | if (text != null) { | ||||
| runner.addText(text); | runner.addText(text); | ||||
| } | } | ||||
| runner.bindToComponent(this); | |||||
| if (classpath != null) { | |||||
| runner.setClasspath(classpath); | |||||
| } | |||||
| if (setBeans) { | |||||
| runner.bindToComponent(this); | |||||
| } else { | |||||
| runner.bindToComponentMinimum(this); | |||||
| } | |||||
| runner.executeScript("ANT"); | runner.executeScript("ANT"); | ||||
| } | } | ||||
| @@ -81,4 +91,49 @@ public class Script extends Task { | |||||
| public void addText(String text) { | public void addText(String text) { | ||||
| this.text = text; | this.text = text; | ||||
| } | } | ||||
| /** | |||||
| * Set the classpath to be used when searching for classes and resources. | |||||
| * | |||||
| * @param classpath an Ant Path object containing the search path. | |||||
| */ | |||||
| public void setClasspath(Path classpath) { | |||||
| createClasspath().append(classpath); | |||||
| } | |||||
| /** | |||||
| * Classpath to be used when searching for classes and resources. | |||||
| * | |||||
| * @return an empty Path instance to be configured by Ant. | |||||
| */ | |||||
| public Path createClasspath() { | |||||
| if (this.classpath == null) { | |||||
| this.classpath = new Path(getProject()); | |||||
| } | |||||
| return this.classpath.createPath(); | |||||
| } | |||||
| /** | |||||
| * Set the classpath by reference. | |||||
| * | |||||
| * @param r a Reference to a Path instance to be used as the classpath | |||||
| * value. | |||||
| */ | |||||
| public void setClasspathRef(Reference r) { | |||||
| createClasspath().setRefid(r); | |||||
| } | |||||
| /** | |||||
| * Set the setbeans attribute. | |||||
| * If this is true, <script> will create variables in the | |||||
| * script instance for all | |||||
| * properties, targets and references of the current project. | |||||
| * It this is false, only the project and self variables will | |||||
| * be set. | |||||
| * The default is true. | |||||
| * @param setBeans the value to set. | |||||
| */ | |||||
| public void setSetBeans(boolean setBeans) { | |||||
| this.setBeans = setBeans; | |||||
| } | |||||
| } | } | ||||
| @@ -20,8 +20,11 @@ package org.apache.tools.ant.util; | |||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileInputStream; | import java.io.FileInputStream; | ||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import org.apache.bsf.BSFException; | import org.apache.bsf.BSFException; | ||||
| import org.apache.bsf.BSFManager; | import org.apache.bsf.BSFManager; | ||||
| import org.apache.tools.ant.AntClassLoader; | |||||
| import org.apache.tools.ant.BuildException; | import org.apache.tools.ant.BuildException; | ||||
| import org.apache.tools.ant.ProjectComponent; | import org.apache.tools.ant.ProjectComponent; | ||||
| import org.apache.tools.ant.Project; | import org.apache.tools.ant.Project; | ||||
| @@ -29,6 +32,7 @@ import org.apache.tools.ant.Project; | |||||
| import java.util.Map; | import java.util.Map; | ||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.tools.ant.types.Path; | |||||
| /** | /** | ||||
| * This class is used to run BSF scripts | * This class is used to run BSF scripts | ||||
| @@ -57,6 +61,11 @@ public class ScriptRunner { | |||||
| /** Beans to be provided to the script */ | /** Beans to be provided to the script */ | ||||
| private Map beans = new HashMap(); | private Map beans = new HashMap(); | ||||
| /** Classpath to be used when running the script. */ | |||||
| private Path classpath = null; | |||||
| /** Project this runner is used in */ | |||||
| private Project project = null; | |||||
| /** | /** | ||||
| * Add a list of named objects to the list to be exported to the script | * Add a list of named objects to the list to be exported to the script | ||||
| @@ -111,8 +120,18 @@ public class ScriptRunner { | |||||
| throw new BuildException("script language must be specified"); | throw new BuildException("script language must be specified"); | ||||
| } | } | ||||
| ClassLoader origContextClassLoader = | |||||
| Thread.currentThread().getContextClassLoader(); | |||||
| ClassLoader scriptLoader = getClass().getClassLoader(); | |||||
| if (classpath != null && project != null) { | |||||
| AntClassLoader loader = project.createClassLoader(classpath); | |||||
| loader.setParent(scriptLoader); | |||||
| scriptLoader = loader; | |||||
| } | |||||
| try { | try { | ||||
| Thread.currentThread().setContextClassLoader(scriptLoader); | |||||
| BSFManager manager = new BSFManager (); | BSFManager manager = new BSFManager (); | ||||
| manager.setClassLoader(scriptLoader); | |||||
| for (Iterator i = beans.keySet().iterator(); i.hasNext();) { | for (Iterator i = beans.keySet().iterator(); i.hasNext();) { | ||||
| String key = (String) i.next(); | String key = (String) i.next(); | ||||
| @@ -141,6 +160,9 @@ public class ScriptRunner { | |||||
| } | } | ||||
| } | } | ||||
| throw new BuildException(t); | throw new BuildException(t); | ||||
| } finally { | |||||
| Thread.currentThread().setContextClassLoader( | |||||
| origContextClassLoader); | |||||
| } | } | ||||
| } | } | ||||
| @@ -162,6 +184,13 @@ public class ScriptRunner { | |||||
| return language; | return language; | ||||
| } | } | ||||
| /** | |||||
| * Set the class path to be used. | |||||
| */ | |||||
| public void setClasspath(Path classpath) { | |||||
| this.classpath = classpath; | |||||
| } | |||||
| /** | /** | ||||
| * Load the script from an external file ; optional. | * Load the script from an external file ; optional. | ||||
| * | * | ||||
| @@ -203,7 +232,7 @@ public class ScriptRunner { | |||||
| * @param component to become <code>self</code> | * @param component to become <code>self</code> | ||||
| */ | */ | ||||
| public void bindToComponent(ProjectComponent component) { | public void bindToComponent(ProjectComponent component) { | ||||
| Project project = component.getProject(); | |||||
| project = component.getProject(); | |||||
| addBeans(project.getProperties()); | addBeans(project.getProperties()); | ||||
| addBeans(project.getUserProperties()); | addBeans(project.getUserProperties()); | ||||
| addBeans(project.getTargets()); | addBeans(project.getTargets()); | ||||
| @@ -211,4 +240,15 @@ public class ScriptRunner { | |||||
| addBean("project", project); | addBean("project", project); | ||||
| addBean("self", component); | addBean("self", component); | ||||
| } | } | ||||
| /** | |||||
| * Bind the runner to a project component. | |||||
| * The project and self are the only beans set. | |||||
| * @param component to become <code>self</code> | |||||
| */ | |||||
| public void bindToComponentMinimum(ProjectComponent component) { | |||||
| project = component.getProject(); | |||||
| addBean("project", project); | |||||
| addBean("self", component); | |||||
| } | |||||
| } | } | ||||