You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@ant.apache.org by pe...@apache.org on 2006/11/23 23:51:44 UTC
svn commit: r478700 - in /ant/core/trunk/src/main/org/apache/tools/ant:
taskdefs/optional/Script.java util/ScriptRunnerBase.java
util/optional/ScriptRunner.java
Author: peterreilly
Date: Thu Nov 23 14:51:44 2006
New Revision: 478700
URL: http://svn.apache.org/viewvc?view=rev&rev=478700
Log:
Refactoring ScriptRunner
* split into general non-bsf dependant part and bsf-dependant part
* get classloader to be set outside scriptrunner
* allow script engine to be reused in other scripts (not used in code yet)
* add api to check if language supported (not used in code yet)
Mods from Bugzilla 40908
* add clearing of text (not used in code yet)
* add impl of eval (not used in code yet)
* use fileutils reader functionality (note: need to allow
setting of file encoding)
Added:
ant/core/trunk/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
Modified:
ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/Script.java
ant/core/trunk/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java
Modified: ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/Script.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/Script.java?view=diff&rev=478700&r1=478699&r2=478700
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/Script.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/optional/Script.java Thu Nov 23 14:51:44 2006
@@ -21,6 +21,7 @@
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.util.optional.ScriptRunner;
+import org.apache.tools.ant.util.ScriptRunnerBase;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
@@ -43,7 +44,7 @@
* @exception BuildException if something goes wrong with the build
*/
public void execute() throws BuildException {
- ScriptRunner runner = new ScriptRunner();
+ ScriptRunnerBase runner = new ScriptRunner();
if (language != null) {
runner.setLanguage(language);
}
@@ -54,7 +55,9 @@
runner.addText(text);
}
if (classpath != null) {
- runner.setClasspath(classpath);
+ runner.setScriptClassLoader(
+ getProject().createClassLoader(
+ getClass().getClassLoader(), classpath));
}
if (setBeans) {
runner.bindToComponent(this);
Added: ant/core/trunk/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java?view=auto&rev=478700
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java (added)
+++ ant/core/trunk/src/main/org/apache/tools/ant/util/ScriptRunnerBase.java Thu Nov 23 14:51:44 2006
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ */
+package org.apache.tools.ant.util;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.ProjectComponent;
+import org.apache.tools.ant.Project;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+
+/**
+ * This is a common abstract base case for script runners.
+ * These classes need to implement executeScript, evalulateScript
+ * and supportsLanguage.
+ */
+public abstract class ScriptRunnerBase {
+ /** Whether to keep the engine between calls to execute/eval */
+ private boolean keepEngine = false;
+
+ /** Script language */
+ private String language;
+
+ /** Script content */
+ private String script = "";
+
+ /** Project this runner is used in */
+ private Project project;
+
+ /** Classloader to be used when running the script. */
+ private ClassLoader scriptLoader;
+
+ /** Beans to be provided to the script */
+ private Map beans = new HashMap();
+
+ /**
+ * Add a list of named objects to the list to be exported to the script
+ *
+ * @param dictionary a map of objects to be placed into the script context
+ * indexed by String names.
+ */
+ public void addBeans(Map dictionary) {
+ for (Iterator i = dictionary.keySet().iterator(); i.hasNext();) {
+ String key = (String) i.next();
+ try {
+ Object val = dictionary.get(key);
+ addBean(key, val);
+ } catch (BuildException ex) {
+ // The key is in the dictionary but cannot be retrieved
+ // This is usually due references that refer to tasks
+ // that have not been taskdefed in the current run.
+ // Ignore
+ }
+ }
+ }
+
+ /**
+ * Add a single object into the script context.
+ *
+ * @param key the name in the context this object is to stored under.
+ * @param bean the object to be stored in the script context.
+ */
+ public void addBean(String key, Object bean) {
+ boolean isValid = key.length() > 0
+ && Character.isJavaIdentifierStart(key.charAt(0));
+
+ for (int i = 1; isValid && i < key.length(); i++) {
+ isValid = Character.isJavaIdentifierPart(key.charAt(i));
+ }
+
+ if (isValid) {
+ beans.put(key, bean);
+ }
+ }
+
+ /**
+ * Get the beans used for the script.
+ * @return the map of beans.
+ */
+ protected Map getBeans() {
+ return beans;
+ }
+
+ /**
+ * Do the work.
+ * @param execName the name that will be passed to BSF for this script
+ * execution.
+ */
+ public abstract void executeScript(String execName);
+
+ /**
+ * Evalulate the script.
+ * @param execName the name that will be passed to BSF for this script
+ * execution.
+ * @return the result of evalulating the script.
+ */
+ public abstract Object evalulateScript(String execName);
+
+ /**
+ * Check if a script engine can be created for
+ * this language.
+ * @return true if a script engine can be created, false
+ * otherwise.
+ */
+ public abstract boolean supportsLanguage();
+
+ /**
+ * Defines the language (required).
+ * @param language the scripting language name for the script.
+ */
+ public void setLanguage(String language) {
+ this.language = language;
+ }
+
+ /**
+ * Get the script language
+ * @return the script language
+ */
+ public String getLanguage() {
+ return language;
+ }
+
+ /**
+ * Set the script classloader.
+ * @param classLoader the classloader to use.
+ */
+ public void setScriptClassLoader(ClassLoader classLoader) {
+ this.scriptLoader = classLoader;
+ }
+
+ /**
+ * Get the classloader used to load the script engine.
+ * @return the classloader.
+ */
+ protected ClassLoader getScriptClassLoader() {
+ return scriptLoader;
+ }
+
+ /**
+ * Whether to keep the script engine between calls.
+ * @param keepEngine if true, keep the engine.
+ */
+ public void setKeepEngine(boolean keepEngine) {
+ this.keepEngine = keepEngine;
+ }
+
+ /**
+ * Get the keep engine attribute.
+ * @return the attribute.
+ */
+ public boolean getKeepEngine() {
+ return keepEngine;
+ }
+
+ /**
+ * Load the script from an external file; optional.
+ * @param file the file containing the script source.
+ */
+ public void setSrc(File file) {
+ if (!file.exists()) {
+ throw new BuildException("file " + file.getPath() + " not found.");
+ }
+ BufferedReader in = null;
+ try {
+ in = new BufferedReader(new FileReader(file));
+ script += FileUtils.readFully(in);
+ } catch (IOException ex) {
+ throw new BuildException(ex);
+ } finally {
+ FileUtils.close(in);
+ }
+ }
+
+ /**
+ * Set the script text.
+ *
+ * @param text a component of the script text to be added.
+ */
+ public void addText(String text) {
+ this.script += text;
+ }
+
+ /**
+ * Get the current script text content.
+ * @return the script text.
+ */
+ public String getScript() {
+ return script;
+ }
+
+ /**
+ * Clear the current script text content.
+ */
+ public void clearScript() {
+ this.script = "";
+ }
+
+ /**
+ * Bind the runner to a project component.
+ * Properties, targets and references are all added as beans;
+ * project is bound to project, and self to the component.
+ * @param component to become <code>self</code>
+ */
+ public void bindToComponent(ProjectComponent component) {
+ project = component.getProject();
+ addBeans(project.getProperties());
+ addBeans(project.getUserProperties());
+ addBeans(project.getTargets());
+ addBeans(project.getReferences());
+ addBean("project", project);
+ 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);
+ }
+
+ /**
+ * Check if the language attribute is set.
+ * @throws BuildException if it is not.
+ */
+ protected void checkLanguage() {
+ if (language == null) {
+ throw new BuildException(
+ "script language must be specified");
+ }
+ }
+
+ /**
+ * Replace the current context classloader with the
+ * script context classloader.
+ * @return the current context classloader.
+ */
+ protected ClassLoader replaceContextLoader() {
+ ClassLoader origContextClassLoader =
+ Thread.currentThread().getContextClassLoader();
+ if (getScriptClassLoader() == null) {
+ setScriptClassLoader(getClass().getClassLoader());
+ }
+ Thread.currentThread().setContextClassLoader(getScriptClassLoader());
+ return origContextClassLoader;
+ }
+
+ /**
+ * Restore the context loader with the original context classloader.
+ *
+ * script context loader.
+ * @param origLoader the original context classloader.
+ */
+ protected void restoreContextLoader(ClassLoader origLoader) {
+ Thread.currentThread().setContextClassLoader(
+ origLoader);
+ }
+
+}
Modified: ant/core/trunk/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java?view=diff&rev=478700&r1=478699&r2=478700
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/util/optional/ScriptRunner.java Thu Nov 23 14:51:44 2006
@@ -17,35 +17,22 @@
*/
package org.apache.tools.ant.util.optional;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-
import org.apache.bsf.BSFException;
import org.apache.bsf.BSFManager;
+import org.apache.bsf.BSFEngine;
import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.ProjectComponent;
-import org.apache.tools.ant.Project;
-
-import org.apache.tools.ant.util.FileUtils;
-import java.util.Map;
-import java.util.HashMap;
import java.util.Iterator;
-import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.util.ScriptRunnerBase;
/**
* This class is used to run BSF scripts
*
*/
-public class ScriptRunner {
-
- // Register Groovy ourselves, since BSF does not
- // natively support it (yet).
- // This "hack" can be removed once BSF has been
- // modified to support Groovy or more dynamic
- // registration.
+public class ScriptRunner extends ScriptRunnerBase {
+ // Register Groovy ourselves, since BSF did not
+ // natively support it in versions previous to 1.2.4.
static {
BSFManager.registerScriptingEngine(
"groovy",
@@ -53,58 +40,30 @@
new String[] {"groovy", "gy"});
}
- /** Script language */
- private String language;
-
- /** Script content */
- private String script = "";
-
- /** Beans to be provided to the script */
- 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;
+ private BSFEngine engine;
+ private BSFManager manager;
/**
- * Add a list of named objects to the list to be exported to the script
- *
- * @param dictionary a map of objects to be placed into the script context
- * indexed by String names.
+ * Check if bsf supports the language.
+ * @return true if bsf can create an engine for this language.
*/
- public void addBeans(Map dictionary) {
- for (Iterator i = dictionary.keySet().iterator(); i.hasNext();) {
- String key = (String) i.next();
- try {
- Object val = dictionary.get(key);
- addBean(key, val);
- } catch (BuildException ex) {
- // The key is in the dictionary but cannot be retrieved
- // This is usually due references that refer to tasks
- // that have not been taskdefed in the current run.
- // Ignore
- }
+ public boolean supportsLanguage() {
+ if (manager != null) {
+ return true;
}
- }
-
- /**
- * Add a single object into the script context.
- *
- * @param key the name in the context this object is to stored under.
- * @param bean the object to be stored in the script context.
- */
- public void addBean(String key, Object bean) {
- boolean isValid = key.length() > 0
- && Character.isJavaIdentifierStart(key.charAt(0));
-
- for (int i = 1; isValid && i < key.length(); i++) {
- isValid = Character.isJavaIdentifierPart(key.charAt(i));
- }
-
- if (isValid) {
- beans.put(key, bean);
+ checkLanguage();
+ ClassLoader origLoader = replaceContextLoader();
+ try {
+ BSFManager m = createManager();
+ BSFEngine e =
+ engine != null
+ ? engine
+ : m.loadScriptingEngine(getLanguage());
+ return e != null;
+ } catch (Exception ex) {
+ return false;
+ } finally {
+ restoreContextLoader(origLoader);
}
}
@@ -117,139 +76,99 @@
* @exception BuildException if someting goes wrong exectuing the script.
*/
public void executeScript(String execName) throws BuildException {
- if (language == null) {
- throw new BuildException("script language must be specified");
- }
-
- ClassLoader origContextClassLoader =
- Thread.currentThread().getContextClassLoader();
- ClassLoader scriptLoader = getClass().getClassLoader();
- if (classpath != null && project != null) {
- scriptLoader = project.createClassLoader(
- scriptLoader, classpath);
- }
+ checkLanguage();
+ ClassLoader origLoader = replaceContextLoader();
try {
- Thread.currentThread().setContextClassLoader(scriptLoader);
- BSFManager manager = new BSFManager ();
- manager.setClassLoader(scriptLoader);
-
- for (Iterator i = beans.keySet().iterator(); i.hasNext();) {
- String key = (String) i.next();
- Object value = beans.get(key);
- if (value != null) {
- manager.declareBean(key, value, value.getClass());
- } else {
- // BSF uses a hashtable to store values
- // so cannot declareBean with a null value
- // So need to remove any bean of this name as
- // that bean should not be visible
- manager.undeclareBean(key);
- }
- }
-
+ BSFManager m = createManager();
+ declareBeans(m);
// execute the script
- manager.exec(language, execName, 0, 0, script);
- } catch (BSFException be) {
- Throwable t = be;
- Throwable te = be.getTargetException();
- if (te != null) {
- if (te instanceof BuildException) {
- throw (BuildException) te;
- } else {
- t = te;
- }
+ if (engine == null) {
+ m.exec(getLanguage(), execName, 0, 0, getScript());
+ } else {
+ engine.exec(execName, 0, 0, getScript());
}
- throw new BuildException(t);
+ } catch (BSFException be) {
+ throwBuildException(be);
} finally {
- Thread.currentThread().setContextClassLoader(
- origContextClassLoader);
+ restoreContextLoader(origLoader);
}
}
/**
- * Defines the language (required).
- *
- * @param language the scripting language name for the script.
- */
- public void setLanguage(String language) {
- this.language = language;
- }
-
- /**
- * Get the script language
- *
- * @return the script language
- */
- public String getLanguage() {
- return language;
- }
-
- /**
- * Set the class path to be used.
- * @param classpath the path to use.
- */
- public void setClasspath(Path classpath) {
- this.classpath = classpath;
- }
-
- /**
- * Load the script from an external file ; optional.
+ * Do the work.
*
- * @param file the file containing the script source.
+ * @param execName the name that will be passed to BSF for this script
+ * execution.
+ * @return the result of the evalulation
+ * @exception BuildException if someting goes wrong exectuing the script.
*/
- public void setSrc(File file) {
- if (!file.exists()) {
- throw new BuildException("file " + file.getPath() + " not found.");
- }
-
- int count = (int) file.length();
- byte[] data = new byte[count];
- FileInputStream inStream = null;
+ public Object evalulateScript(String execName)
+ throws BuildException {
+ checkLanguage();
+ ClassLoader origLoader = replaceContextLoader();
try {
- inStream = new FileInputStream(file);
- inStream.read(data);
- } catch (IOException e) {
- throw new BuildException(e);
+ BSFManager m = createManager();
+ declareBeans(m);
+ // execute the script
+ if (engine == null) {
+ return m.eval(getLanguage(), execName, 0, 0, getScript());
+ } else {
+ return engine.eval(execName, 0, 0, getScript());
+ }
+ } catch (BSFException be) {
+ throwBuildException(be);
+ // NotReached
+ return null;
} finally {
- FileUtils.close(inStream);
+ restoreContextLoader(origLoader);
}
-
- script += new String(data);
}
/**
- * Set the script text.
- *
- * @param text a component of the script text to be added.
+ * Throw a buildException in place of a BSFException.
+ * @param be BSFException to convert.
+ * @throws BuildException the conveted exception.
*/
- public void addText(String text) {
- this.script += text;
+ private void throwBuildException(BSFException be) {
+ Throwable t = be;
+ Throwable te = be.getTargetException();
+ if (te != null) {
+ if (te instanceof BuildException) {
+ throw (BuildException) te;
+ } else {
+ t = te;
+ }
+ }
+ throw new BuildException(t);
}
- /**
- * Bind the runner to a project component.
- * Properties, targets and references are all added as beans;
- * project is bound to project, and self to the component.
- * @param component to become <code>self</code>
- */
- public void bindToComponent(ProjectComponent component) {
- project = component.getProject();
- addBeans(project.getProperties());
- addBeans(project.getUserProperties());
- addBeans(project.getTargets());
- addBeans(project.getReferences());
- addBean("project", project);
- addBean("self", component);
+ private void declareBeans(BSFManager m) throws BSFException {
+ for (Iterator i = getBeans().keySet().iterator(); i.hasNext();) {
+ String key = (String) i.next();
+ Object value = getBeans().get(key);
+ if (value != null) {
+ m.declareBean(key, value, value.getClass());
+ } else {
+ // BSF uses a hashtable to store values
+ // so cannot declareBean with a null value
+ // So need to remove any bean of this name as
+ // that bean should not be visible
+ m.undeclareBean(key);
+ }
+ }
}
- /**
- * 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);
+ private BSFManager createManager() throws BSFException {
+ if (manager != null) {
+ return manager;
+ }
+ BSFManager m = new BSFManager();
+ m.setClassLoader(getScriptClassLoader());
+ if (getKeepEngine()) {
+ BSFEngine e = manager.loadScriptingEngine(getLanguage());
+ this.manager = m;
+ this.engine = e;
+ }
+ return m;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@ant.apache.org
For additional commands, e-mail: dev-help@ant.apache.org