Bug 52101

Summary: Could we please have ant properties in scope in javascript under <script/>
Product: Ant Reporter: bmargulies <bimargulies>
Component: Core tasksAssignee: Ant Notifications List <notifications>
Status: NEW ---    
Severity: enhancement CC: jglick
Priority: P2    
Version: 1.8.2   
Target Milestone: ---   
Hardware: PC   
OS: Mac OS X 10.4   

Description bmargulies 2011-10-27 14:43:41 UTC
In my dreams, the following could just get those properties by something like:

   project.properties["status.result"];

   or even allow

   project.properties["status.result"] = "new value";

I think I know enough Rhino to even code this, if you-all are sympathetic to the notion.



 <script language="javascript"><![CDATA[
          var fail = controlservices.createTask("fail");
          var result = project.getProperty("status.result");
	  var stdout = project.getProperty("status.output");
	  var statusproperty = project.getProperty("status.property");
	  if (result == 1 && stdout.match(/is not running/)) {
	      project.setProperty(statusproperty, "STOPPED");
          } else if (result != 0) {
	     var stderr = project.getProperty("status.error");
             fail.setMessage("Failed to obtain status: " + result + "\n" + stderr);
	     fail.perform();
	  } else {
	     var matches = stdout.match("Java:(.*)$");
             project.setProperty(statusproperty, matches[1]);
          }
      ]]></script>
Comment 1 Stefan Bodewig 2011-12-06 16:36:50 UTC
In order to code this you need to know BSF or javax.script rather than Rhino 8-)

Sure, if you can provide a patch the syntactic sugar may be nice.
Comment 2 Jesse Glick 2011-12-06 18:15:49 UTC
(In reply to comment #1)
> In order to code this you need to know BSF or javax.script

org.apache.tools.ant.util.optional.ScriptRunner and JavaxScriptRunner, respectively, but ScriptDef and ScriptRunnerBase are responsible for defining specific bindings.

Note that while Ant currently uses BSF 2.x with its proprietary API, 3.x just uses JSR 223 (and runs on older JDKs). By dropping support for 2.x we could simplify the Ant interface code - no indirection through ScriptRunnerBase, no reflection.
Comment 3 Jesse Glick 2011-12-06 18:36:53 UTC
Note that ScriptRunnerBase.bindToComponent already does

        addBeans(project.getProperties());

meaning that this works:

        <property name="foobie" value="bletch"/>
        <script language="javascript">
            println(foobie)
        <interpreted that, but it /script>

but this does not:

        <property name="foo.bie" value="bletch"/>
        <script language="javascript">
            println(foo.bie)
        </script>

The problem is that addBean will only define "variables" whose names look like Java identifiers, and this of course excludes typical dotted properties (which Rhino would anyway treat as nested lookups). This could be solved using java.util.Map for languages that interpret Java maps (Groovy etc. I think). Unfortunately Rhino does not; and

Index: src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
===================================================================
--- src/main/org/apache/tools/ant/util/ScriptRunnerBase.java	(revision 1204648)
+++ src/main/org/apache/tools/ant/util/ScriptRunnerBase.java	(working copy)
@@ -35,6 +35,7 @@
 import java.util.Map;
 import java.util.HashMap;
 import java.util.Iterator;
+import sun.org.mozilla.javascript.internal.NativeObject;
 
 /**
  * This is a common abstract base case for script runners.
@@ -98,6 +99,13 @@
 
         if (isValid) {
             beans.put(key, bean);
+        } else {
+            int dot = key.lastIndexOf('.');
+            if (dot != -1) {
+                NativeObject o = new NativeObject();
+                o.defineProperty(key.substring(dot + 1), bean, NativeObject.READONLY);
+                addBean(key.substring(0, dot), o);
+            }
         }
     }
 
as per [1] might work (on Rhino only!) if it were compilable, but it is not.

[1] http://stackoverflow.com/a/7575789/12916