You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by bo...@apache.org on 2017/02/20 16:58:54 UTC

[04/12] ant git commit: Scriptdef task new options : 'compiled' (if javax.script engine implements Compilable), 'encoding' to load resources

Scriptdef task new options : 'compiled' (if javax.script engine implements Compilable), 'encoding' to load resources


Project: http://git-wip-us.apache.org/repos/asf/ant/repo
Commit: http://git-wip-us.apache.org/repos/asf/ant/commit/4bd9b4a6
Tree: http://git-wip-us.apache.org/repos/asf/ant/tree/4bd9b4a6
Diff: http://git-wip-us.apache.org/repos/asf/ant/diff/4bd9b4a6

Branch: refs/heads/master
Commit: 4bd9b4a6e473a9188124989315f75b778ad2a363
Parents: 526df1e
Author: pyxide <op...@gmail.com>
Authored: Fri Jan 13 17:16:50 2017 +0100
Committer: Stefan Bodewig <bo...@apache.org>
Committed: Mon Feb 20 17:41:37 2017 +0100

----------------------------------------------------------------------
 .../ant/taskdefs/optional/script/ScriptDef.java |  22 +++-
 .../apache/tools/ant/util/ScriptRunnerBase.java |  87 +++++++++++++--
 .../tools/ant/util/ScriptRunnerHelper.java      |  40 +++++++
 .../ant/util/optional/JavaxScriptRunner.java    | 108 ++++++++++++++++---
 4 files changed, 230 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/ant/blob/4bd9b4a6/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
index ac9eb88..3f40a14 100644
--- a/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
+++ b/src/main/org/apache/tools/ant/taskdefs/optional/script/ScriptDef.java
@@ -67,7 +67,7 @@ public class ScriptDef extends DefBase {
 
     /**
      * Set the project.
-     * @param project the project that this def belows to.
+     * @param project the project that this definition belongs to.
      */
     public void setProject(Project project) {
         super.setProject(project);
@@ -237,7 +237,6 @@ public class ScriptDef extends DefBase {
                     + "attributes");
             }
 
-
             nestedElementMap.put(nestedElement.name, nestedElement);
         }
 
@@ -368,6 +367,15 @@ public class ScriptDef extends DefBase {
     }
 
     /**
+     * Defines the language (required).
+     *
+     * @param language the scripting language name for the script.
+     */
+    public void setCompiled(boolean compiled) {
+        helper.setCompiled(compiled);
+    }
+
+    /**
      * Load the script from an external file ; optional.
      *
      * @param file the file containing the script source.
@@ -377,6 +385,15 @@ public class ScriptDef extends DefBase {
     }
 
     /**
+     * Set the encoding of the script from an external file ; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     */
+    public void setEncoding(String encoding) {
+        helper.setEncoding(encoding);
+    }
+
+    /**
      * Set the script text.
      *
      * @param text a component of the script text to be added.
@@ -394,4 +411,3 @@ public class ScriptDef extends DefBase {
         helper.add(resource);
     }
 }
-

http://git-wip-us.apache.org/repos/asf/ant/blob/4bd9b4a6/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java b/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
index b8aa01a..ac08f98 100644
--- a/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
+++ b/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
@@ -19,12 +19,13 @@ package org.apache.tools.ant.util;
 
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileNotFoundException;
-import java.io.FileReader;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
+import java.io.UnsupportedEncodingException;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.Map;
@@ -34,6 +35,8 @@ import org.apache.tools.ant.Project;
 import org.apache.tools.ant.ProjectComponent;
 import org.apache.tools.ant.types.Resource;
 import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.PropertyResource;
+import org.apache.tools.ant.types.resources.StringResource;
 
 /**
  * This is a common abstract base case for script runners.
@@ -51,6 +54,11 @@ public abstract class ScriptRunnerBase {
     /** Script content */
     private String script = "";
 
+    private String encoding;
+
+    /** Enable script compilation. */
+    private boolean compiled;
+
     /** Project this runner is used in */
     private Project project;
 
@@ -187,7 +195,35 @@ public abstract class ScriptRunnerBase {
     }
 
     /**
+     * Whether to use script compilation if available. 
+     * @since Ant 1.10.1
+     * @param compiled if true, compile the script if possible.
+     */
+    public final void setCompiled(boolean compiled) {
+        this.compiled = compiled;
+    }
+
+    /**
+     * Get the compiled attribute.
+     * @since Ant 1.10.1
+     * @return the attribute.
+     */
+    public final boolean getCompiled() {
+        return compiled;
+    }
+
+    /**
+     * Set encoding of the script from an external file; optional.
+     * @since Ant 1.10.1
+     * @param encoding  encoding of the external file containing the script source.
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
      * Load the script from an external file; optional.
+     * @since Ant 1.10.1
      * @param file the file containing the script source.
      */
     public void setSrc(File file) {
@@ -195,12 +231,19 @@ public abstract class ScriptRunnerBase {
         if (!file.exists()) {
             throw new BuildException("file " + filename + " not found.");
         }
+        InputStream in = null;
         try {
-            readSource(new FileReader(file), filename);
+            in = new FileInputStream(file);
         } catch (FileNotFoundException e) {
             //this can only happen if the file got deleted a short moment ago
             throw new BuildException("file " + filename + " not found.");
         }
+
+        try {
+            readSource(in, filename);
+        } finally {
+             FileUtils.close(in);
+        }
     }
 
     /**
@@ -208,19 +251,25 @@ public abstract class ScriptRunnerBase {
      * @param reader the reader; this is closed afterwards.
      * @param name the name to use in error messages
      */
-    private void readSource(Reader reader, String name) {
-        BufferedReader in = null;
+    private void readSource(InputStream in, String name) {
+        Reader reader = null;
         try {
-            in = new BufferedReader(reader);
-            script += FileUtils.safeReadFully(in);
+            if (null == encoding) {
+                reader = new InputStreamReader(in);
+            } else {
+                reader = new InputStreamReader(in, encoding);
+            }
+            reader = new BufferedReader(reader);
+            script += FileUtils.safeReadFully(reader);
+        } catch(UnsupportedEncodingException e) {
+            throw new BuildException("Failed to decode " + name + " with encoding " + encoding, e);
         } catch (IOException ex) {
             throw new BuildException("Failed to read " + name, ex);
         } finally {
-            FileUtils.close(in);
+            FileUtils.close(reader);
         }
     }
 
-
     /**
      * Add a resource to the source list.
      * @since Ant 1.7.1
@@ -228,6 +277,20 @@ public abstract class ScriptRunnerBase {
      * @throws BuildException if the resource cannot be read
      */
     public void loadResource(Resource sourceResource) {
+    	if(sourceResource instanceof StringResource) {
+    		// Note: StringResource uses UTF-8 by default to encode/decode, not the default platform encoding
+    		script += ((StringResource) sourceResource).getValue();
+    		return;
+    	}
+    	if(sourceResource instanceof PropertyResource) {
+    		script += ((PropertyResource) sourceResource).getValue();
+    		return;
+    	}
+
+    	// Concat resource
+    	
+    	// FileResource : OK for default encoding
+
         String name = sourceResource.toLongString();
         InputStream in = null;
         try {
@@ -238,7 +301,12 @@ public abstract class ScriptRunnerBase {
             throw new BuildException(
                 "Failed to open " + name + " -it is not readable", e);
         }
-        readSource(new InputStreamReader(in), name);
+
+        try {
+            readSource(in, name);
+        } finally {
+            FileUtils.close(in);
+        }
     }
 
     /**
@@ -356,5 +424,4 @@ public abstract class ScriptRunnerBase {
         Thread.currentThread().setContextClassLoader(
                  origLoader);
     }
-
 }

http://git-wip-us.apache.org/repos/asf/ant/blob/4bd9b4a6/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java b/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
index 9e814d9..5cc23ab 100644
--- a/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
+++ b/src/main/org/apache/tools/ant/util/ScriptRunnerHelper.java
@@ -31,9 +31,11 @@ import org.apache.tools.ant.types.resources.Union;
 public class ScriptRunnerHelper {
     private ClasspathUtils.Delegate cpDelegate = null;
     private File    srcFile;
+    private String  encoding;
     private String  manager = "auto";
     private String  language;
     private String  text;
+    private boolean compiled = false;
     private boolean setBeans = true;
     private ProjectComponent projectComponent;
     private ClassLoader scriptLoader = null;
@@ -53,6 +55,12 @@ public class ScriptRunnerHelper {
      */
     public ScriptRunnerBase getScriptRunner() {
         ScriptRunnerBase runner = getRunner();
+        runner.setCompiled(compiled);
+
+        if (encoding != null) {
+        	// set it first, because runner.setSrc() loads immediately the file
+            runner.setEncoding(encoding);
+        }
         if (srcFile != null) {
             runner.setSrc(srcFile);
         }
@@ -108,6 +116,16 @@ public class ScriptRunnerHelper {
     }
 
     /**
+     * Set the encoding of the script from an external file ; optional.
+     *
+     * @param encoding the encoding of the file containing the script source.
+     * @since Ant 1.10.1
+     */
+	public void setEncoding(String encoding) {
+		this.encoding = encoding;
+	}
+
+    /**
      * Add script text.
      *
      * @param text a component of the script text to be added.
@@ -143,6 +161,28 @@ public class ScriptRunnerHelper {
     }
 
     /**
+     * Enable the compilation of the script if possible.
+     * If this is true and the compilation feature is available in
+     * the script engine, the script is compiled before the first
+     * evaluation, and should be cached for future evaluations.
+     * Otherwise, a script is evaluated is used.
+     * The default is false.
+     *
+     * @param compiled the value to set.
+     */
+    public void setCompiled(boolean compiled) {
+        this.compiled = compiled;
+    }
+
+    /**
+     * Get the compilation feature.
+     * @return the compilation feature.
+     */
+    public boolean getCompiled() {
+        return this.compiled;
+    }
+
+    /**
      * Set the setbeans attribute.
      * If this is true, &lt;script&gt; will create variables in the
      * script instance for all

http://git-wip-us.apache.org/repos/asf/ant/blob/4bd9b4a6/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
----------------------------------------------------------------------
diff --git a/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java b/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
index 7a5cfa4..2670b09 100644
--- a/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
+++ b/src/main/org/apache/tools/ant/util/optional/JavaxScriptRunner.java
@@ -21,6 +21,7 @@ package org.apache.tools.ant.util.optional;
 import java.util.Iterator;
 
 import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Project;
 import org.apache.tools.ant.util.ReflectWrapper;
 import org.apache.tools.ant.util.ScriptRunnerBase;
 
@@ -31,6 +32,11 @@ import org.apache.tools.ant.util.ScriptRunnerBase;
 public class JavaxScriptRunner extends ScriptRunnerBase {
     private ReflectWrapper engine;
 
+    /** Debug constant */
+    private static final boolean DEBUG = Boolean.getBoolean("JavaxScriptRunner.DEBUG");
+
+    private String compiledScriptRefName; 
+
     /**
      * Get the name of the manager prefix.
      * @return "javax"
@@ -79,28 +85,85 @@ public class JavaxScriptRunner extends ScriptRunnerBase {
         checkLanguage();
         ClassLoader origLoader = replaceContextLoader();
         try {
+
+            if(DEBUG) System.out.println("-- JavaxScriptRunner.evaluateScript : compile enabled [" + getCompiled() + "]");
+
+            if (getCompiled()) {
+
+            	if (null == compiledScriptRefName) {
+            		compiledScriptRefName = execName + ".compiledScript.0123456789";
+            	}
+                ReflectWrapper scriptRefObj = getProject().getReference(compiledScriptRefName);
+
+                if (null == scriptRefObj) {
+
+                    ReflectWrapper engine = createEngine();
+                    if (engine == null) {
+                        throw new BuildException(
+                            "Unable to create javax script engine for "
+                            + getLanguage());
+                    }
+
+                    final Class engineClass = Class.forName("javax.script.ScriptEngine");
+                    final Class compilableClass = Class.forName("javax.script.Compilable");
+                    final Object wrappedObject = engine.getObject();
+
+                    if (DEBUG) System.out.println("-- JavaxScriptRunner.evaluateScript : wrappedObject [" + wrappedObject.getClass().getName() + "]");
+                    if (engineClass.isAssignableFrom(wrappedObject.getClass()) && compilableClass.isAssignableFrom(wrappedObject.getClass())) {
+
+                        if(DEBUG) System.out.println("-- JavaxScriptRunner.evaluateScript : compilable [" + wrappedObject.getClass().getName() + "]");
+
+                        {
+                            getProject().log("compile script" + compiledScriptRefName, Project.MSG_VERBOSE);
+
+                            // compilable engine
+                            final Object compiledScript = engine.invoke("compile", String.class, getScript());
+                            scriptRefObj = new ReflectWrapper(compiledScript);
+                        }
+
+                        getProject().log("store compiled script, ref " + compiledScriptRefName, Project.MSG_DEBUG);
+
+                    } else {
+                        getProject().log("script compilation not available", Project.MSG_DEBUG);
+                        scriptRefObj = new ReflectWrapper(null);
+                    }
+
+                    getProject().addReference(compiledScriptRefName, scriptRefObj);
+                }
+
+                if (null != scriptRefObj.getObject()) {
+
+                    if (DEBUG) System.out.println("-- JavaxScriptRunner.evaluateScript : execute compiled script");
+
+                    final Object simpleBindings;
+                    {
+                        final Class simpleBindingsClass  = Class.forName("javax.script.SimpleBindings");
+                        simpleBindings = simpleBindingsClass.newInstance();
+                    }
+
+                    applyBindings(new ReflectWrapper(simpleBindings));
+                    if (DEBUG) System.out.println("-- JavaxScriptRunner.evaluateScript : bindings applied");
+
+                    getProject().log("run compiled script, ref " + compiledScriptRefName, Project.MSG_DEBUG);
+
+                    final Class bindingsClass  = Class.forName("javax.script.Bindings");
+
+                    return scriptRefObj.invoke("eval", bindingsClass, simpleBindings);
+                }
+            }
+
             ReflectWrapper engine = createEngine();
             if (engine == null) {
                 throw new BuildException(
                     "Unable to create javax script engine for "
                     + getLanguage());
             }
-            for (Iterator i = getBeans().keySet().iterator(); i.hasNext();) {
-                String key = (String) i.next();
-                Object value = getBeans().get(key);
-                if ("FX".equalsIgnoreCase(getLanguage())) {
-                    engine.invoke(
-                        "put", String.class, key
-                        + ":" + value.getClass().getName(),
-                        Object.class, value);
-                } else {
-                    engine.invoke(
-                        "put", String.class, key,
-                        Object.class, value);
-                }
-            }
+
+            applyBindings(engine);
+
             // execute the script
             return engine.invoke("eval", String.class, getScript());
+
         } catch (BuildException be) {
             //catch and rethrow build exceptions
 
@@ -126,6 +189,23 @@ public class JavaxScriptRunner extends ScriptRunnerBase {
         }
     }
 
+    private void applyBindings(ReflectWrapper engine) {
+        for (Iterator i = getBeans().keySet().iterator(); i.hasNext();) {
+            String key = (String) i.next();
+            Object value = getBeans().get(key);
+            if ("FX".equalsIgnoreCase(getLanguage())) {
+                engine.invoke(
+                    "put", String.class, key
+                    + ":" + value.getClass().getName(),
+                    Object.class, value);
+            } else {
+                engine.invoke(
+                    "put", String.class, key,
+                    Object.class, value);
+            }
+        }
+    }
+
     private ReflectWrapper createEngine() {
         if (engine != null) {
             return engine;