| @@ -67,7 +67,7 @@ public class ScriptDef extends DefBase { | |||||
| /** | /** | ||||
| * Set the project. | * 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) { | public void setProject(Project project) { | ||||
| super.setProject(project); | super.setProject(project); | ||||
| @@ -237,7 +237,6 @@ public class ScriptDef extends DefBase { | |||||
| + "attributes"); | + "attributes"); | ||||
| } | } | ||||
| nestedElementMap.put(nestedElement.name, nestedElement); | nestedElementMap.put(nestedElement.name, nestedElement); | ||||
| } | } | ||||
| @@ -367,6 +366,15 @@ public class ScriptDef extends DefBase { | |||||
| helper.setLanguage(language); | helper.setLanguage(language); | ||||
| } | } | ||||
| /** | |||||
| * 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. | * Load the script from an external file ; optional. | ||||
| * | * | ||||
| @@ -376,6 +384,15 @@ public class ScriptDef extends DefBase { | |||||
| helper.setSrc(file); | helper.setSrc(file); | ||||
| } | } | ||||
| /** | |||||
| * 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. | * Set the script text. | ||||
| * | * | ||||
| @@ -394,4 +411,3 @@ public class ScriptDef extends DefBase { | |||||
| helper.add(resource); | helper.add(resource); | ||||
| } | } | ||||
| } | } | ||||
| @@ -19,12 +19,13 @@ package org.apache.tools.ant.util; | |||||
| import java.io.BufferedReader; | import java.io.BufferedReader; | ||||
| import java.io.File; | import java.io.File; | ||||
| import java.io.FileInputStream; | |||||
| import java.io.FileNotFoundException; | import java.io.FileNotFoundException; | ||||
| import java.io.FileReader; | |||||
| import java.io.IOException; | import java.io.IOException; | ||||
| import java.io.InputStream; | import java.io.InputStream; | ||||
| import java.io.InputStreamReader; | import java.io.InputStreamReader; | ||||
| import java.io.Reader; | import java.io.Reader; | ||||
| import java.io.UnsupportedEncodingException; | |||||
| import java.util.HashMap; | import java.util.HashMap; | ||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import java.util.Map; | 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.ProjectComponent; | ||||
| import org.apache.tools.ant.types.Resource; | import org.apache.tools.ant.types.Resource; | ||||
| import org.apache.tools.ant.types.ResourceCollection; | 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. | * This is a common abstract base case for script runners. | ||||
| @@ -51,6 +54,11 @@ public abstract class ScriptRunnerBase { | |||||
| /** Script content */ | /** Script content */ | ||||
| private String script = ""; | private String script = ""; | ||||
| private String encoding; | |||||
| /** Enable script compilation. */ | |||||
| private boolean compiled; | |||||
| /** Project this runner is used in */ | /** Project this runner is used in */ | ||||
| private Project project; | private Project project; | ||||
| @@ -186,8 +194,36 @@ public abstract class ScriptRunnerBase { | |||||
| return keepEngine; | return keepEngine; | ||||
| } | } | ||||
| /** | |||||
| * 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. | * Load the script from an external file; optional. | ||||
| * @since Ant 1.10.1 | |||||
| * @param file the file containing the script source. | * @param file the file containing the script source. | ||||
| */ | */ | ||||
| public void setSrc(File file) { | public void setSrc(File file) { | ||||
| @@ -195,12 +231,19 @@ public abstract class ScriptRunnerBase { | |||||
| if (!file.exists()) { | if (!file.exists()) { | ||||
| throw new BuildException("file " + filename + " not found."); | throw new BuildException("file " + filename + " not found."); | ||||
| } | } | ||||
| InputStream in = null; | |||||
| try { | try { | ||||
| readSource(new FileReader(file), filename); | |||||
| in = new FileInputStream(file); | |||||
| } catch (FileNotFoundException e) { | } catch (FileNotFoundException e) { | ||||
| //this can only happen if the file got deleted a short moment ago | //this can only happen if the file got deleted a short moment ago | ||||
| throw new BuildException("file " + filename + " not found."); | 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 reader the reader; this is closed afterwards. | ||||
| * @param name the name to use in error messages | * @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 { | 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) { | } catch (IOException ex) { | ||||
| throw new BuildException("Failed to read " + name, ex); | throw new BuildException("Failed to read " + name, ex); | ||||
| } finally { | } finally { | ||||
| FileUtils.close(in); | |||||
| FileUtils.close(reader); | |||||
| } | } | ||||
| } | } | ||||
| /** | /** | ||||
| * Add a resource to the source list. | * Add a resource to the source list. | ||||
| * @since Ant 1.7.1 | * @since Ant 1.7.1 | ||||
| @@ -228,6 +277,20 @@ public abstract class ScriptRunnerBase { | |||||
| * @throws BuildException if the resource cannot be read | * @throws BuildException if the resource cannot be read | ||||
| */ | */ | ||||
| public void loadResource(Resource sourceResource) { | 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(); | String name = sourceResource.toLongString(); | ||||
| InputStream in = null; | InputStream in = null; | ||||
| try { | try { | ||||
| @@ -238,7 +301,12 @@ public abstract class ScriptRunnerBase { | |||||
| throw new BuildException( | throw new BuildException( | ||||
| "Failed to open " + name + " -it is not readable", e); | "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( | Thread.currentThread().setContextClassLoader( | ||||
| origLoader); | origLoader); | ||||
| } | } | ||||
| } | } | ||||
| @@ -31,9 +31,11 @@ import org.apache.tools.ant.types.resources.Union; | |||||
| public class ScriptRunnerHelper { | public class ScriptRunnerHelper { | ||||
| private ClasspathUtils.Delegate cpDelegate = null; | private ClasspathUtils.Delegate cpDelegate = null; | ||||
| private File srcFile; | private File srcFile; | ||||
| private String encoding; | |||||
| private String manager = "auto"; | private String manager = "auto"; | ||||
| private String language; | private String language; | ||||
| private String text; | private String text; | ||||
| private boolean compiled = false; | |||||
| private boolean setBeans = true; | private boolean setBeans = true; | ||||
| private ProjectComponent projectComponent; | private ProjectComponent projectComponent; | ||||
| private ClassLoader scriptLoader = null; | private ClassLoader scriptLoader = null; | ||||
| @@ -53,6 +55,12 @@ public class ScriptRunnerHelper { | |||||
| */ | */ | ||||
| public ScriptRunnerBase getScriptRunner() { | public ScriptRunnerBase getScriptRunner() { | ||||
| ScriptRunnerBase runner = getRunner(); | 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) { | if (srcFile != null) { | ||||
| runner.setSrc(srcFile); | runner.setSrc(srcFile); | ||||
| } | } | ||||
| @@ -107,6 +115,16 @@ public class ScriptRunnerHelper { | |||||
| this.srcFile = file; | this.srcFile = file; | ||||
| } | } | ||||
| /** | |||||
| * 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. | * Add script text. | ||||
| * | * | ||||
| @@ -142,6 +160,28 @@ public class ScriptRunnerHelper { | |||||
| return language; | return language; | ||||
| } | } | ||||
| /** | |||||
| * 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. | * Set the setbeans attribute. | ||||
| * If this is true, <script> will create variables in the | * If this is true, <script> will create variables in the | ||||
| @@ -21,6 +21,7 @@ package org.apache.tools.ant.util.optional; | |||||
| import java.util.Iterator; | import java.util.Iterator; | ||||
| import org.apache.tools.ant.BuildException; | 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.ReflectWrapper; | ||||
| import org.apache.tools.ant.util.ScriptRunnerBase; | import org.apache.tools.ant.util.ScriptRunnerBase; | ||||
| @@ -31,6 +32,11 @@ import org.apache.tools.ant.util.ScriptRunnerBase; | |||||
| public class JavaxScriptRunner extends ScriptRunnerBase { | public class JavaxScriptRunner extends ScriptRunnerBase { | ||||
| private ReflectWrapper engine; | private ReflectWrapper engine; | ||||
| /** Debug constant */ | |||||
| private static final boolean DEBUG = Boolean.getBoolean("JavaxScriptRunner.DEBUG"); | |||||
| private String compiledScriptRefName; | |||||
| /** | /** | ||||
| * Get the name of the manager prefix. | * Get the name of the manager prefix. | ||||
| * @return "javax" | * @return "javax" | ||||
| @@ -79,28 +85,85 @@ public class JavaxScriptRunner extends ScriptRunnerBase { | |||||
| checkLanguage(); | checkLanguage(); | ||||
| ClassLoader origLoader = replaceContextLoader(); | ClassLoader origLoader = replaceContextLoader(); | ||||
| try { | 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(); | ReflectWrapper engine = createEngine(); | ||||
| if (engine == null) { | if (engine == null) { | ||||
| throw new BuildException( | throw new BuildException( | ||||
| "Unable to create javax script engine for " | "Unable to create javax script engine for " | ||||
| + getLanguage()); | + 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 | // execute the script | ||||
| return engine.invoke("eval", String.class, getScript()); | return engine.invoke("eval", String.class, getScript()); | ||||
| } catch (BuildException be) { | } catch (BuildException be) { | ||||
| //catch and rethrow build exceptions | //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() { | private ReflectWrapper createEngine() { | ||||
| if (engine != null) { | if (engine != null) { | ||||
| return engine; | return engine; | ||||