[EMAIL PROTECTED] wrote:
So the task should do compiling and taskdefing?
Maybe caching the compiled data?
Jan
The languages do the compiling (Both beanshell and groovy currently use
asm - http://asm.objectweb.org) and return a class object when the BSF
eval method is called.
The task itself is very small:
Peter
-----Original Message-----
From: Peter Reilly [mailto:[EMAIL PROTECTED]
Sent: Monday, February 16, 2004 10:21 AM
To: Ant Developers List
Subject: [Fwd: [New task] scripttypedef (or refectdef)]
package org.apache.tools.ant.taskdefs.optional;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import org.apache.bsf.BSFManager;
import org.apache.bsf.BSFException;
import org.apache.tools.ant.AntTypeDefinition;
import org.apache.tools.ant.taskdefs.DefBase;
import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.ComponentHelper;
import org.apache.tools.ant.ProjectHelper;
/**
* Class to define an ant definition using a script that
* can return a class that is a normal ant task/datatype.
* If the language is beanshell it must be 2.0 or higher.
* The other scripting currently known to work is
* groovy (1.0beta3).
* <p>
* Note that if there is anything incorrect with the script
* the warning message is quite cryptic.
* </p>
* This class is based in part on o.a.t.ant.util.ScriptRunner.
* The main difference is that it does not define
* beans. This is for three reasons:
* <ol>
* <li>The definition may be used in another project.</li>
* <li>It should be possible to convert to java later.</li>
* </ol>
*
* @author Peter Reilly
* @since Ant 1.7
*/
public class ScriptTypeDef extends DefBase {
// 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.
static {
BSFManager.registerScriptingEngine(
"groovy",
"org.codehaus.groovy.bsf.GroovyEngine",
new String[] {"groovy", "gy"});
}
private String language;
private File src;
private String text;
private String eval;
private String name;
/**
* Defines the language (required).
*
* @param language the scripting language name for the script.
*/
public void setLanguage(String language) {
this.language = language;
}
/**
* A string to evaluate.
*
* @param eval a string to evaluate.
*/
public void setEval(String eval) {
this.eval = eval;
}
/**
* Load the script from an external file ; optional.
*
* @param src the file containing the script source.
*/
public void setSrc(File src) {
this.src = src;
}
/**
* Set the script text.
*
* @param text a component of the script text to be added.
*/
public void addText(String text) {
this.text = getProject().replaceProperties(text);
}
/**
* Name of the definition
* @param name the name of the definition
*/
public void setName(String name) {
this.name = name;
}
private boolean equalsHandleNull(Object a, Object b) {
if (a == null) {
return b == null;
}
if (b == null) {
return false;
}
return a.equals(b);
}
/**
* define the beanshell definition.
* check the attributes, get the class been defined and
* set the definition.
*/
public void execute() {
if (name == null) {
throw new BuildException("Missing attribute name");
}
if (text == null && src == null) {
throw new BuildException("Missing script or file");
}
if (language == null) {
throw new BuildException("Missing language");
}
ComponentHelper helper =
ComponentHelper.getComponentHelper(getProject());
String namespacedName = ProjectHelper.genComponentName(getURI(), name);
// Check if definition already present due to antcall type behaviour
AntTypeDefinition oldDef = helper.getDefinition(namespacedName);
if (oldDef != null && oldDef instanceof ScriptTypeDefinition) {
// See if the data is the same.
ScriptTypeDef other = ((ScriptTypeDefinition) oldDef).getOwner();
if (equalsHandleNull(src, other.src)
&& equalsHandleNull(text, other.text)
&& equalsHandleNull(eval, other.eval)
&& equalsHandleNull(language, other.language)) {
return; // Ingore new definition as it is the same
}
}
// Currently neither beanshell 2.0beta or groovy 1.0
// look at BSFManager#setClassLoader(),
// the following will work for groovy but not for beanshell
ClassLoader currentLoader =
Thread.currentThread().getContextClassLoader();
BSFManager manager = new BSFManager();
try {
ClassLoader cl = createLoader();
Thread.currentThread().setContextClassLoader(cl);
manager.setClassLoader(cl);
Object o = manager.eval(language, "ant", 0, 0, getScript());
if (!(o instanceof Class)) {
throw new BuildException("The object should be a Class");
}
Class cl = (Class) o;
ScriptTypeDefinition def = new ScriptTypeDefinition();
def.setName(ProjectHelper.genComponentName(getURI(), name));
def.setClassName(cl.getName());
def.setClass(cl);
def.setOwner(this);
ComponentHelper.getComponentHelper(getProject())
.addDataTypeDefinition(def);
} catch (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);
} catch (BuildException ex) {
throw ex;
} catch (Throwable t) {
throw new BuildException(t);
} finally {
manager.terminate();
try {
Thread.currentThread().setContextClassLoader(currentLoader);
} catch (Throwable t) {
// Ignore
}
}
}
private static class ScriptTypeDefinition extends AntTypeDefinition {
private ScriptTypeDef owner;
private void setOwner(ScriptTypeDef owner) {
this.owner = owner;
}
private ScriptTypeDef getOwner() {
return owner;
}
}
private String getFileString(File file) {
if (!file.exists()) {
throw new BuildException("file " + file.getPath() + " not found.");
}
int count = (int) file.length();
byte[] data = new byte[count];
try {
FileInputStream inStream = new FileInputStream(file);
inStream.read(data);
inStream.close();
} catch (IOException e) {
throw new BuildException(e);
}
return new String(data);
}
private String getScript() {
String ret = "";
if (src != null) {
ret = getFileString(src);
}
if (text != null) {
ret = ret + text;
}
if (eval != null) {
ret = ret + eval;
}
return ret;
}
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]