This commit is contained in:
Daniel Mills 2021-08-07 21:18:39 -04:00
parent 271f308c36
commit 18465cf6cb
62 changed files with 9534 additions and 2 deletions

View File

@ -137,8 +137,8 @@ dependencies {
implementation "net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT" implementation "net.kyori:adventure-text-minimessage:4.1.0-SNAPSHOT"
implementation "net.kyori:adventure-platform-bukkit:4.0.0-SNAPSHOT" implementation "net.kyori:adventure-platform-bukkit:4.0.0-SNAPSHOT"
implementation 'net.kyori:adventure-api:4.8.1' implementation 'net.kyori:adventure-api:4.8.1'
\
// Dynamically Loaded // Dynamically Loaded
implementation 'it.unimi.dsi:fastutil:8.5.4' implementation 'it.unimi.dsi:fastutil:8.5.4'
implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2' implementation 'com.googlecode.concurrentlinkedhashmap:concurrentlinkedhashmap-lru:1.4.2'
implementation 'org.zeroturnaround:zt-zip:1.14' implementation 'org.zeroturnaround:zt-zip:1.14'
@ -146,4 +146,5 @@ dependencies {
implementation 'org.ow2.asm:asm:9.2' implementation 'org.ow2.asm:asm:9.2'
implementation 'com.google.guava:guava:30.1.1-jre' implementation 'com.google.guava:guava:30.1.1-jre'
} }

View File

@ -0,0 +1,33 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine;
import com.volmit.iris.engine.framework.Engine;
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
import lombok.Data;
@Data
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
private final Engine engine;
IrisExecutionEnvironment(Engine engine)
{
this.engine = engine;
}
}

View File

@ -0,0 +1,31 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.engine.scripting;
import com.volmit.iris.engine.framework.Engine;
public interface EngineExecutionEnvironment
{
Engine getEngine();
default void close()
{
}
}

View File

@ -0,0 +1,39 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.bsf;
/**
* BSFDeclaredBeans are used internally by BSF to encapsulate information being
* passed between a BSFManager and its various BSFEngines. Note that the
* constructor is not public because this is not a public class.
*
* @author Matthew J. Duftler
* @author Sanjiva Weerawarana
*/
public class BSFDeclaredBean {
public String name;
public Object bean;
public Class type;
BSFDeclaredBean(String name, Object bean, Class type) {
this.name = name;
this.bean = bean;
this.type = type;
}
}

View File

@ -0,0 +1,253 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.bsf;
import java.beans.PropertyChangeListener;
import java.util.Vector;
import com.volmit.iris.util.bsf.util.CodeBuffer;
/**
* This is the view of a scripting engine assumed by the Bean Scripting
* Framework. This interface is used when an application decides to
* run some script under application control. (This is the reverse of
* the more common situation, which is that of the scripting language
* calling into the application.)
* <p>
* When a scripting engine is first fired up, the initialize()
* method is called right after construction.
* <p>
* A scripting engine must provide two access points for applications
* to call into them: via function calls and via expression evaluation.
* It must also support loading scripts.
* <p>
* A scripting engine is a property change listener and will be notified
* when any of the relevant properties of the manager change. (See
* BSFManager to see which of its properties are bound.)
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
*/
public interface BSFEngine extends PropertyChangeListener {
/**
* This is used by an application to invoke an anonymous function. An
* anonymous function is a multi-line script which when evaluated will
* produce a value. These are separated from expressions and scripts
* because the prior are spsed to be good 'ol expressions and scripts
* are not value returning. We allow anonymous functions to have parameters
* as well for completeness.
*
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param funcBody the multi-line, value returning script to evaluate
* @param paramNames the names of the parameters above assumes
* @param arguments values of the above parameters
*
* @exception BSFException if anything goes wrong while doin' it.
*/
public Object apply(
String source,
int lineNo,
int columnNo,
Object funcBody,
Vector paramNames,
Vector arguments)
throws BSFException;
/**
* This is used by an application to call into the scripting engine
* to make a function/method call. The "object" argument is the object
* whose method is to be called, if that applies. For non-OO languages,
* this is typically ignored and should be given as null. For pretend-OO
* languages such as VB, this would be the (String) name of the object.
* The arguments are given in the args array.
*
* @param object object on which to make the call
* @param name name of the method / procedure to call
* @param args the arguments to be given to the procedure
*
* @exception BSFException if anything goes wrong while eval'ing a
* BSFException is thrown. The reason indicates the problem.
*/
public Object call(Object object, String name, Object[] args)
throws BSFException;
/**
* This is used by an application to compile an anonymous function. See
* comments in apply for more hdetails.
*
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param funcBody the multi-line, value returning script to evaluate
* @param paramNames the names of the parameters above assumes
* @param arguments values of the above parameters
* @param cb the CodeBuffer to compile into
*
* @exception BSFException if anything goes wrong while doin' it.
*/
public void compileApply(
String source,
int lineNo,
int columnNo,
Object funcBody,
Vector paramNames,
Vector arguments,
CodeBuffer cb)
throws BSFException;
/**
* This is used by an application to compile a value-returning expression.
* The expr may be string or some other type, depending on the language.
* The generated code is dumped into the <tt>CodeBuffer</tt>.
*
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param expr the expression to compile
* @param cb the CodeBuffer to compile into
*
* @exception BSFException if anything goes wrong while compiling a
* BSFException is thrown. The reason indicates the problem.
*/
public void compileExpr(
String source,
int lineNo,
int columnNo,
Object expr,
CodeBuffer cb)
throws BSFException;
/**
* This is used by an application to compile some script. The
* script may be string or some other type, depending on the
* language. The generated code is dumped into the <tt>CodeBuffer</tt>.
*
* @param source (context info) the source of this script
* (e.g., filename)
* @param lineNo (context info) the line number in source for script
* @param columnNo (context info) the column number in source for script
* @param script the script to compile
* @param cb the CodeBuffer to compile into
*
* @exception BSFException if anything goes wrong while compiling a
* BSFException is thrown. The reason indicates the problem.
*/
public void compileScript(
String source,
int lineNo,
int columnNo,
Object script,
CodeBuffer cb)
throws BSFException;
/**
* Declare a bean after the engine has been started. Declared beans
* are beans that are named and which the engine must make available
* to the scripts it runs in the most first class way possible.
*
* @param bean the bean to declare
*
* @exception BSFException if the engine cannot do this operation
*/
public void declareBean(BSFDeclaredBean bean) throws BSFException;
/**
* This is used by an application to evaluate an expression. The
* expression may be string or some other type, depending on the
* language. (For example, for BML it'll be an org.w3c.dom.Element
* object.)
*
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param expr the expression to evaluate
*
* @exception BSFException if anything goes wrong while eval'ing a
* BSFException is thrown. The reason indicates the problem.
*/
public Object eval(String source, int lineNo, int columnNo, Object expr)
throws BSFException;
/**
* This is used by an application to execute some script. The
* expression may be string or some other type, depending on the
* language. Returns nothing but if something goes wrong it excepts
* (of course).
*
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param script the script to execute
*
* @exception BSFException if anything goes wrong while exec'ing a
* BSFException is thrown. The reason indicates the problem.
*/
public void exec(String source, int lineNo, int columnNo, Object script)
throws BSFException;
/**
* This is used by an application to execute some script, as though
* one were interacting with the language in an interactive session.
* The expression may be string or some other type, depending on the
* language. Returns nothing but if something goes wrong it excepts (of
* course).
*
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param script the script to execute
*
* @exception BSFException if anything goes wrong while exec'ing a
* BSFException is thrown. The reason indicates the problem.
*/
public void iexec(String source, int lineNo, int columnNo, Object script)
throws BSFException;
/**
* This method is used to initialize the engine right after construction.
* This method will be called before any calls to eval or call. At this
* time the engine should capture the current values of interesting
* properties from the manager. In the future, any changes to those
* will be mirrored to me by the manager via a property change event.
*
* @param mgr The BSFManager that's hosting this engine.
* @param lang Language string which this engine is handling.
* @param declaredBeans Vector of BSFDeclaredObject containing beans
* that should be declared into the language runtime at init
* time as best as possible.
*
* @exception BSFException if anything goes wrong while init'ing a
* BSFException is thrown. The reason indicates the problem.
*/
public void initialize(BSFManager mgr, String lang, Vector declaredBeans)
throws BSFException;
/**
* Graceful termination
*/
public void terminate();
/**
* Undeclare a previously declared bean.
*
* @param bean the bean to undeclare
*
* @exception BSFException if the engine cannot do this operation
*/
public void undeclareBean(BSFDeclaredBean bean) throws BSFException;
}

View File

@ -0,0 +1,71 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.bsf;
/**
* If something goes wrong while doing some scripting stuff, one of these
* is thrown. The integer code indicates what's wrong and the message
* may give more details. The reason one exception with multiple meanings
* (via the code) [instead of multiple exception types] is used is due to
* the interest to keep the run-time size small.
*
* @author Sanjiva Weerawarana
*/
public class BSFException extends Exception {
public static final int REASON_INVALID_ARGUMENT = 0;
public static final int REASON_IO_ERROR = 10;
public static final int REASON_UNKNOWN_LANGUAGE = 20;
public static final int REASON_EXECUTION_ERROR = 100;
public static final int REASON_UNSUPPORTED_FEATURE = 499;
public static final int REASON_OTHER_ERROR = 500;
int reason;
Throwable targetThrowable;
public BSFException (int reason, String msg) {
super (msg);
this.reason = reason;
}
public BSFException (int reason, String msg, Throwable t) {
this (reason, msg);
targetThrowable = t;
}
public BSFException (String msg) {
this (REASON_OTHER_ERROR, msg);
}
public int getReason () {
return reason;
}
public Throwable getTargetException () {
return targetThrowable;
}
public void printStackTrace () {
if (targetThrowable != null) {
String msg = getMessage ();
if (msg != null && !msg.equals (targetThrowable.getMessage ())) {
System.err.print (msg + ": ");
}
targetThrowable.printStackTrace ();
} else {
super.printStackTrace ();
}
}
}

View File

@ -0,0 +1,913 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.bsf;
import java.beans.PropertyChangeSupport;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.security.AccessController;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.MissingResourceException;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
import com.volmit.iris.util.bsf.util.CodeBuffer;
import com.volmit.iris.util.bsf.util.ObjectRegistry;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This class is the entry point to the bean scripting framework. An
* application wishing to integrate scripting to a Java app would
* place an instance of a BSFManager in their code and use its services
* to register the beans they want to make available for scripting,
* load scripting engines, and run scripts.
* <p>
* BSFManager serves as the registry of available scripting engines
* as well. Loading and unloading of scripting engines is
* supported as well. Each BSFManager loads one engine per language.
* Several BSFManagers can be created per JVM.
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @author Sam Ruby
* @author Olivier Gruber (added original debugging support)
* @author Don Schwarz (added support for registering languages dynamically)
*/
public class BSFManager {
// version string is in the form "abc.yyyymmdd" where
// "abc" represents a dewey decimal number (three levels, each between 0 and 9),
// and "yyyy" a four digit year, "mm" a two digit month, "dd" a two digit day.
//
// Example: "240.20060925" stands for: BSF version "2.4.0" as of "2006-09-25"
protected static String version="240.20061006";
// table of registered scripting engines
protected static Hashtable registeredEngines = new Hashtable();
// mapping of file extensions to languages
protected static Hashtable extn2Lang = new Hashtable();
// table of scripting engine instances created by this manager.
// only one instance of a given language engine is created by a single
// manager instance.
protected Hashtable loadedEngines = new Hashtable();
// table of registered beans for use by scripting engines.
protected ObjectRegistry objectRegistry = new ObjectRegistry();
// prop change support containing loaded engines to inform when any
// of my interesting properties change
protected PropertyChangeSupport pcs;
// the class loader to use if a class loader is needed. Default is
// he who loaded me (which may be null in which case its Class.forName).
// protected ClassLoader classLoader = getClass().getClassLoader();
protected ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); // rgf, 2006-01-05
// temporary directory to use to dump temporary files into. Note that
// if class files are dropped here then unless this dir is in the
// classpath or unless the classloader knows to look here, the classes
// will not be found.
protected String tempDir = ".";
// classpath used by those that need a classpath
protected String classPath;
// stores BSFDeclaredBeans representing objects
// introduced by a client of BSFManager
protected Vector declaredBeans = new Vector();
private Log logger = LogFactory.getLog(this.getClass().getName());
//////////////////////////////////////////////////////////////////////
//
// pre-register engines that BSF supports off the shelf
//
//////////////////////////////////////////////////////////////////////
static {
try {
Enumeration e = BSFManager.class.getClassLoader().getResources("org/apache/bsf/Languages.properties");
while (e.hasMoreElements()) {
URL url = (URL)e.nextElement();
InputStream is = url.openStream();
Properties p = new Properties();
p.load(is);
for (Enumeration keys = p.propertyNames(); keys.hasMoreElements();) {
String key = (String) keys.nextElement();
String value = p.getProperty(key);
String className = value.substring(0, value.indexOf(","));
// get the extensions for this language
String exts = value.substring(value.indexOf(",")+1, value.length());
StringTokenizer st = new StringTokenizer(exts, "|");
String[] extensions = new String[st.countTokens()];
for (int i = 0; st.hasMoreTokens(); i++) {
extensions[i] = ((String) st.nextToken()).trim();
}
registerScriptingEngine(key, className, extensions);
}
}
} catch (IOException ex) {
ex.printStackTrace();
System.err.println("Error reading Languages file " + ex);
} catch (NoSuchElementException nsee) {
nsee.printStackTrace();
System.err.println("Syntax error in Languages resource bundle");
} catch (MissingResourceException mre) {
mre.printStackTrace();
System.err.println("Initialization error: " + mre.toString());
}
}
public BSFManager() {
pcs = new PropertyChangeSupport(this);
}
/** Returns the version string of BSF.
*
* @return version string in the form &quot;abc.yyyymmdd&quot; where
&quot;abc&quot; represents a dewey decimal number (three levels, each between 0 and 9), and
&quot;yyyy&quot; a four digit year, &quot;mm&quot; a two digit month,
&quot;dd&quot; a two digit day.
*
<br>Example: &quot;<code>240.20061006</code>&quot;
stands for: BSF version <code>2.4.0</code> as of <code>2006-10-06</code>.
*
*
* @since 2006-01-17
*/
public static String getVersion() {
return version;
}
/**
* Apply the given anonymous function of the given language to the given
* parameters and return the resulting value.
*
* @param lang language identifier
* @param source (context info) the source of this expression
(e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param funcBody the multi-line, value returning script to evaluate
* @param paramNames the names of the parameters above assumes
* @param arguments values of the above parameters
*
* @exception BSFException if anything goes wrong while running the script
*/
public Object apply(String lang,
String source,
int lineNo,
int columnNo,
Object funcBody,
Vector paramNames,
Vector arguments)
throws BSFException {
logger.debug("BSFManager:apply");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object funcBodyf = funcBody;
final Vector paramNamesf = paramNames;
final Vector argumentsf = arguments;
Object result = null;
try {
final Object resultf =
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
return e.apply(sourcef, lineNof, columnNof,
funcBodyf, paramNamesf, argumentsf);
}
});
result = resultf;
} catch (PrivilegedActionException prive) {
logger.error("Exception: ", prive);
throw (BSFException) prive.getException();
}
return result;
}
/**
* Compile the application of the given anonymous function of the given
* language to the given parameters into the given <tt>CodeBuffer</tt>.
*
* @param lang language identifier
* @param source (context info) the source of this expression
(e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param funcBody the multi-line, value returning script to evaluate
* @param paramNames the names of the parameters above assumes
* @param arguments values of the above parameters
* @param cb code buffer to compile into
*
* @exception BSFException if anything goes wrong while running the script
*/
public void compileApply(String lang,
String source,
int lineNo,
int columnNo,
Object funcBody,
Vector paramNames,
Vector arguments,
CodeBuffer cb)
throws BSFException {
logger.debug("BSFManager:compileApply");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object funcBodyf = funcBody;
final Vector paramNamesf = paramNames;
final Vector argumentsf = arguments;
final CodeBuffer cbf = cb;
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
e.compileApply(sourcef, lineNof, columnNof,
funcBodyf, paramNamesf,
argumentsf, cbf);
return null;
}
});
} catch (PrivilegedActionException prive) {
logger.error("Exception :", prive);
throw (BSFException) prive.getException();
}
}
/**
* Compile the given expression of the given language into the given
* <tt>CodeBuffer</tt>.
*
* @param lang language identifier
* @param source (context info) the source of this expression
(e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param expr the expression to compile
* @param cb code buffer to compile into
*
* @exception BSFException if any error while compiling the expression
*/
public void compileExpr(String lang,
String source,
int lineNo,
int columnNo,
Object expr,
CodeBuffer cb)
throws BSFException {
logger.debug("BSFManager:compileExpr");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object exprf = expr;
final CodeBuffer cbf = cb;
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
e.compileExpr(sourcef, lineNof, columnNof, exprf, cbf);
return null;
}
});
} catch (PrivilegedActionException prive) {
logger.error("Exception :", prive);
throw (BSFException) prive.getException();
}
}
/**
* Compile the given script of the given language into the given
* <tt>CodeBuffer</tt>.
*
* @param lang language identifier
* @param source (context info) the source of this script
(e.g., filename)
* @param lineNo (context info) the line number in source for script
* @param columnNo (context info) the column number in source for script
* @param script the script to compile
* @param cb code buffer to compile into
*
* @exception BSFException if any error while compiling the script
*/
public void compileScript(String lang,
String source,
int lineNo,
int columnNo,
Object script,
CodeBuffer cb)
throws BSFException {
logger.debug("BSFManager:compileScript");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object scriptf = script;
final CodeBuffer cbf = cb;
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
e.compileScript(sourcef, lineNof, columnNof,
scriptf, cbf);
return null;
}
});
} catch (PrivilegedActionException prive) {
logger.error("Exception :", prive);
throw (BSFException) prive.getException();
}
}
/**
* Declare a bean. The difference between declaring and registering
* is that engines are spsed to make declared beans "pre-available"
* in the scripts as far as possible. That is, if a script author
* needs a registered bean, he needs to look it up in some way. However
* if he needs a declared bean, the language has the responsibility to
* make those beans avaialable "automatically."
* <p>
* When a bean is declared it is automatically registered as well
* so that any declared bean can be gotton to by looking it up as well.
* <p>
* If any of the languages that are already running in this manager
* says they don't like this (by throwing an exception) then this
* method will simply quit with that exception. That is, any engines
* that come after than in the engine enumeration will not even be
* told about this new bean.
* <p>
* So, in general its best to declare beans before the manager has
* been asked to load any engines because then the user can be informed
* when an engine rejects it. Also, its much more likely that an engine
* can declare a bean at start time than it can at any time.
*
* @param beanName name to declare bean as
* @param bean the bean that's being declared
* @param type the type to represent the bean as
*
* @exception BSFException if any of the languages that are already
* running decides to throw an exception when asked to
* declare this bean.
*/
public void declareBean(String beanName, Object bean, Class type)
throws BSFException {
logger.debug("BSFManager:declareBean");
registerBean(beanName, bean);
BSFDeclaredBean tempBean = new BSFDeclaredBean(beanName, bean, type);
declaredBeans.addElement(tempBean);
Enumeration enginesEnum = loadedEngines.elements();
BSFEngine engine;
while (enginesEnum.hasMoreElements()) {
engine = (BSFEngine) enginesEnum.nextElement();
engine.declareBean(tempBean);
}
}
/**
* Evaluate the given expression of the given language and return the
* resulting value.
*
* @param lang language identifier
* @param source (context info) the source of this expression
(e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param expr the expression to evaluate
*
* @exception BSFException if anything goes wrong while running the script
*/
public Object eval(String lang,
String source,
int lineNo,
int columnNo,
Object expr)
throws BSFException {
logger.debug("BSFManager:eval");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object exprf = expr;
Object result = null;
try {
final Object resultf =
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
return e.eval(sourcef, lineNof, columnNof, exprf);
}
});
result = resultf;
} catch (PrivilegedActionException prive) {
logger.error("Exception: ", prive);
throw (BSFException) prive.getException();
}
return result;
}
//////////////////////////////////////////////////////////////////////
//
// Convenience functions for exec'ing and eval'ing scripts directly
// without loading and dealing with engines etc..
//
//////////////////////////////////////////////////////////////////////
/**
* Execute the given script of the given language.
*
* @param lang language identifier
* @param source (context info) the source of this expression
(e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param script the script to execute
*
* @exception BSFException if anything goes wrong while running the script
*/
public void exec(String lang,
String source,
int lineNo,
int columnNo,
Object script)
throws BSFException {
logger.debug("BSFManager:exec");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object scriptf = script;
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
e.exec(sourcef, lineNof, columnNof, scriptf);
return null;
}
});
} catch (PrivilegedActionException prive) {
logger.error("Exception :", prive);
throw (BSFException) prive.getException();
}
}
/**
* Execute the given script of the given language, attempting to
* emulate an interactive session w/ the language.
*
* @param lang language identifier
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param script the script to execute
*
* @exception BSFException if anything goes wrong while running the script
*/
public void iexec(String lang,
String source,
int lineNo,
int columnNo,
Object script)
throws BSFException {
logger.debug("BSFManager:iexec");
final BSFEngine e = loadScriptingEngine(lang);
final String sourcef = source;
final int lineNof = lineNo, columnNof = columnNo;
final Object scriptf = script;
try {
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
e.iexec(sourcef, lineNof, columnNof, scriptf);
return null;
}
});
} catch (PrivilegedActionException prive) {
logger.error("Exception :", prive);
throw (BSFException) prive.getException();
}
}
/**
* Get classLoader
*/
public ClassLoader getClassLoader() {
logger.debug("BSFManager:getClassLoader");
return classLoader;
}
/**
* Get classPath
*/
public String getClassPath() {
logger.debug("BSFManager:getClassPath");
if (classPath == null) {
try {
classPath = System.getProperty("java.class.path");
} catch (Throwable t) {
logger.debug("Exception :", t);
// prolly a security exception .. so no can do
}
}
return classPath;
}
/**
* Determine the language of a script file by looking at the file
* extension.
*
* @param fileName the name of the file
*
* @return the scripting language the file is in if the file extension
* is known to me (must have been registered via
* registerScriptingEngine).
*
* @exception BSFException if file's extension is unknown.
*/
public static String getLangFromFilename(String fileName)
throws BSFException {
int dotIndex = fileName.lastIndexOf(".");
if (dotIndex != -1) {
String extn = fileName.substring(dotIndex + 1);
String langval = (String) extn2Lang.get(extn);
String lang = null;
int index, loops = 0;
if (langval != null) {
while ((index = langval.indexOf(":", 0)) != -1) {
// Great. Multiple language engines registered
// for this extension.
// Try to find first one that is in our classpath.
lang = langval.substring(0, index);
langval = langval.substring(index + 1);
loops++;
// Test to see if in classpath
try {
String engineName =
(String) registeredEngines.get(lang);
Class.forName(engineName);
} catch (ClassNotFoundException cnfe) {
// Bummer.
lang = langval;
continue;
}
// Got past that? Good.
break;
}
if (loops == 0) { lang = langval; }
}
if (lang != null && lang != "") {
return lang;
}
}
throw new BSFException(BSFException.REASON_OTHER_ERROR,
"file extension missing or unknown: "
+ "unable to determine language for '"
+ fileName
+ "'");
}
/**
* Return the current object registry of the manager.
*
* @return the current registry.
*/
public ObjectRegistry getObjectRegistry() {
return objectRegistry;
}
/**
* Get tempDir
*/
public String getTempDir() {
return tempDir;
}
/**
* Determine whether a language is registered.
*
* @param lang string identifying a language
*
* @return true iff it is
*/
public static boolean isLanguageRegistered(String lang) {
return (registeredEngines.get(lang) != null);
}
//////////////////////////////////////////////////////////////////////
//
// Bean scripting framework services
//
//////////////////////////////////////////////////////////////////////
/**
* Load a scripting engine based on the lang string identifying it.
*
* @param lang string identifying language
* @exception BSFException if the language is unknown (i.e., if it
* has not been registered) with a reason of
* REASON_UNKNOWN_LANGUAGE. If the language is known but
* if the interface can't be created for some reason, then
* the reason is set to REASON_OTHER_ERROR and the actual
* exception is passed on as well.
*/
public BSFEngine loadScriptingEngine(String lang) throws BSFException {
logger.debug("BSFManager:loadScriptingEngine");
// if its already loaded return that
BSFEngine eng = (BSFEngine) loadedEngines.get(lang);
if (eng != null) {
return eng;
}
// is it a registered language?
String engineClassName = (String) registeredEngines.get(lang);
if (engineClassName == null) {
logger.error("unsupported language: " + lang);
throw new BSFException(BSFException.REASON_UNKNOWN_LANGUAGE,
"unsupported language: " + lang);
}
// create the engine and initialize it. if anything goes wrong
// except.
try {
Class engineClass =
(classLoader == null)
? Class.forName(engineClassName)
: classLoader.loadClass(engineClassName);
final BSFEngine engf = (BSFEngine) engineClass.newInstance();
final BSFManager thisf = this;
final String langf = lang;
final Vector dbf = declaredBeans;
AccessController.doPrivileged(new PrivilegedExceptionAction() {
public Object run() throws Exception {
engf.initialize(thisf, langf, dbf);
return null;
}
});
eng = engf;
loadedEngines.put(lang, eng);
pcs.addPropertyChangeListener(eng);
return eng;
} catch (PrivilegedActionException prive) {
logger.error("Exception :", prive);
throw (BSFException) prive.getException();
} catch (Throwable t) {
logger.error("Exception :", t);
throw new BSFException(BSFException.REASON_OTHER_ERROR,
"unable to load language: " + lang,
t);
}
}
/**
* return a handle to a bean registered in the bean registry by the
* application or a scripting engine. Returns null if bean is not found.
*
* @param beanName name of bean to look up
*
* @return the bean if its found or null
*/
public Object lookupBean(String beanName) {
logger.debug("BSFManager:lookupBean");
try {
return ((BSFDeclaredBean)objectRegistry.lookup(beanName)).bean;
} catch (IllegalArgumentException e) {
logger.debug("Exception :", e);
return null;
}
}
/**
* Registering a bean allows a scripting engine or the application to
* access that bean by name and to manipulate it.
*
* @param beanName name to register under
* @param bean the bean to register
*/
public void registerBean(String beanName, Object bean) {
logger.debug("BSFManager:registerBean");
BSFDeclaredBean tempBean;
if(bean == null) {
tempBean = new BSFDeclaredBean(beanName, null, null);
} else {
tempBean = new BSFDeclaredBean(beanName, bean, bean.getClass());
}
objectRegistry.register(beanName, tempBean);
}
/**
* Register a scripting engine in the static registry of the
* BSFManager.
*
* @param lang string identifying language
* @param engineClassName fully qualified name of the class interfacing
* the language to BSF.
* @param extensions array of file extensions that should be mapped to
* this language type. may be null.
*/
public static void registerScriptingEngine(String lang,
String engineClassName,
String[] extensions) {
registeredEngines.put(lang, engineClassName);
if (extensions != null) {
for (int i = 0; i < extensions.length; i++) {
String langstr = (String) extn2Lang.get(extensions[i]);
langstr = (langstr == null) ? lang : lang + ":" + langstr;
extn2Lang.put(extensions[i], langstr);
}
}
}
/**
* Set the class loader for those that need to use it. Default is he
* who loaded me or null (i.e., its Class.forName).
*
* @param classLoader the class loader to use.
*/
public void setClassLoader(ClassLoader classLoader) {
logger.debug("BSFManager:setClassLoader");
pcs.firePropertyChange("classLoader", this.classLoader, classLoader);
this.classLoader = classLoader;
}
/**
* Set the classpath for those that need to use it. Default is the value
* of the java.class.path property.
*
* @param classPath the classpath to use
*/
public void setClassPath(String classPath) {
logger.debug("BSFManager:setClassPath");
pcs.firePropertyChange("classPath", this.classPath, classPath);
this.classPath = classPath;
}
/**
* Set the object registry used by this manager. By default a new
* one is created when the manager is new'ed and this overwrites
* that one.
*
* @param objectRegistry the registry to use
*/
public void setObjectRegistry(ObjectRegistry objectRegistry) {
logger.debug("BSFManager:setObjectRegistry");
this.objectRegistry = objectRegistry;
}
/**
* Temporary directory to put stuff into (for those who need to). Note
* that unless this directory is in the classpath or unless the
* classloader knows to look in here, any classes here will not
* be found! BSFManager provides a service method to load a class
* which uses either the classLoader provided by the class loader
* property or, if that fails, a class loader which knows to load from
* the tempdir to try to load the class. Default value of tempDir
* is "." (current working dir).
*
* @param tempDir the temporary directory
*/
public void setTempDir(String tempDir) {
logger.debug("BSFManager:setTempDir");
pcs.firePropertyChange("tempDir", this.tempDir, tempDir);
this.tempDir = tempDir;
}
/**
* Gracefully terminate all engines
*/
public void terminate() {
logger.debug("BSFManager:terminate");
Enumeration enginesEnum = loadedEngines.elements();
BSFEngine engine;
while (enginesEnum.hasMoreElements()) {
engine = (BSFEngine) enginesEnum.nextElement();
engine.terminate();
}
loadedEngines = new Hashtable();
}
/**
* Undeclare a previously declared bean. This removes the bean from
* the list of declared beans in the manager as well as asks every
* running engine to undeclared the bean. As with above, if any
* of the engines except when asked to undeclare, this method does
* not catch that exception. Quietly returns if the bean is unknown.
*
* @param beanName name of bean to undeclare
*
* @exception BSFException if any of the languages that are already
* running decides to throw an exception when asked to
* undeclare this bean.
*/
public void undeclareBean(String beanName) throws BSFException {
logger.debug("BSFManager:undeclareBean");
unregisterBean(beanName);
BSFDeclaredBean tempBean = null;
boolean found = false;
for (Iterator i = declaredBeans.iterator(); i.hasNext();) {
tempBean = (BSFDeclaredBean) i.next();
if (tempBean.name.equals(beanName)) {
found = true;
break;
}
}
if (found) {
declaredBeans.removeElement(tempBean);
Enumeration enginesEnum = loadedEngines.elements();
while (enginesEnum.hasMoreElements()) {
BSFEngine engine = (BSFEngine) enginesEnum.nextElement();
engine.undeclareBean(tempBean);
}
}
}
/**
* Unregister a previously registered bean. Silent if name is not found.
*
* @param beanName name of bean to unregister
*/
public void unregisterBean(String beanName) {
logger.debug("BSFManager:unregisterBean");
objectRegistry.unregister(beanName);
}
}

View File

@ -0,0 +1,50 @@
#
# Iris is a World Generator for Minecraft Bukkit Servers
# Copyright (c) 2021 Arcane Arts (Volmit Software)
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# List of script types and their associated scripting engines
#
# languageDescriptor = engineClass, ext1|ext2|... {, codebaseURL, ...}
#
# where exti are extensions for the language. Note that we leave
# all the engines enabled now and allow them to fail at load time.
# This way engines can be added by just adding to the classpath
# without having to edit this file. Cheating, really, but it works.
#
javascript = com.volmit.iris.util.bsf.engines.javascript.JavaScriptEngine, js
jacl = com.volmit.iris.util.bsf.engines.jacl.JaclEngine, jacl
netrexx = com.volmit.iris.util.bsf.engines.netrexx.NetRexxEngine, nrx
java = com.volmit.iris.util.bsf.engines.java.JavaEngine, java
javaclass = com.volmit.iris.util.bsf.engines.javaclass.JavaClassEngine, class
bml = org.apache.bml.ext.BMLEngine, bml
vbscript = com.volmit.iris.util.bsf.engines.activescript.ActiveScriptEngine, vbs
jscript = com.volmit.iris.util.bsf.engines.activescript.ActiveScriptEngine, jss
perlscript = com.volmit.iris.util.bsf.engines.activescript.ActiveScriptEngine, pls
perl = com.volmit.iris.util.bsf.engines.perl.PerlEngine, pl
jpython = com.volmit.iris.util.bsf.engines.jpython.JPythonEngine, py
jython = com.volmit.iris.util.bsf.engines.jython.JythonEngine, py
lotusscript = com.volmit.iris.util.bsf.engines.lotusscript.LsEngine, lss
xslt = com.volmit.iris.util.bsf.engines.xslt.XSLTEngine, xslt
pnuts = pnuts.ext.PnutsBSFEngine, pnut
beanbasic = com.volmit.iris.util.bsf.engines.beanbasic.BeanBasicEngine, bb
beanshell = bsh.util.BeanShellBSFEngine, bsh
ruby = org.jruby.javasupport.bsf.JRubyEngine, rb
judoscript = com.judoscript.BSFJudoEngine, judo|jud
groovy = org.codehaus.groovy.bsf.GroovyEngine, groovy|gy
objectscript = oscript.bsf.ObjectScriptEngine, os
prolog = ubc.cs.JLog.Extras.BSF.JLogBSFEngine, plog|prolog
rexx = org.rexxla.bsf.engines.rexx.RexxEngine, rex | rexx | cls | rxj | rxs

View File

@ -0,0 +1,190 @@
/*
* Iris is a World Generator for Minecraft Bukkit Servers
* Copyright (c) 2021 Arcane Arts (Volmit Software)
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.volmit.iris.util.bsf;
import java.awt.Frame;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.io.Reader;
import java.util.Hashtable;
import com.volmit.iris.util.bsf.util.CodeBuffer;
import com.volmit.iris.util.bsf.util.IOUtils;
/**
* This is the main driver for BSF to be run on the command line
* to eval/exec/compile scripts directly.
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @author Sam Ruby
*/
public class Main {
private static String ARG_IN = "-in";
private static String ARG_LANG = "-lang";
private static String ARG_MODE = "-mode";
private static String ARG_OUT = "-out";
private static String ARG_VAL_EVAL = "eval";
private static String ARG_VAL_EXEC = "exec";
private static String ARG_VAL_COMPILE = "compile";
private static String DEFAULT_IN_FILE_NAME = "<STDIN>";
private static String DEFAULT_MODE = ARG_VAL_EVAL;
private static String DEFAULT_CLASS_NAME = "Test";
/**
* Static driver to be able to run BSF scripts from the command line.
*
* @param args command line arguments
*
* @exception IOException if any I/O error while loading script
*/
public static void main(String[] args) throws IOException {
try {
if ((args.length == 0) || (args.length % 2 != 0)) {
printHelp();
System.exit(1);
}
Hashtable argsTable = new Hashtable();
argsTable.put(ARG_OUT, DEFAULT_CLASS_NAME);
argsTable.put(ARG_MODE, DEFAULT_MODE);
for (int i = 0; i < args.length; i += 2) {
argsTable.put(args[i], args[i + 1]);
}
String inFileName = (String) argsTable.get(ARG_IN);
String language = (String) argsTable.get(ARG_LANG);
if (language == null) {
if (inFileName != null) {
language = BSFManager.getLangFromFilename(inFileName);
} else {
throw new BSFException(
BSFException.REASON_OTHER_ERROR,
"unable to determine language");
}
}
Reader in;
if (inFileName != null) {
in = new FileReader(inFileName);
} else {
in = new InputStreamReader(System.in);
inFileName = DEFAULT_IN_FILE_NAME;
}
BSFManager mgr = new BSFManager();
String mode = (String) argsTable.get(ARG_MODE);
if (mode.equals(ARG_VAL_COMPILE)) {
String outClassName = (String) argsTable.get(ARG_OUT);
FileWriter out = new FileWriter(outClassName + ".java");
PrintWriter pw = new PrintWriter(out);
CodeBuffer cb = new CodeBuffer();
cb.setClassName(outClassName);
mgr.compileScript(
language,
inFileName,
0,
0,
IOUtils.getStringFromReader(in),
cb);
cb.print(pw, true);
out.close();
} else {
if (mode.equals(ARG_VAL_EXEC)) {
mgr.exec(language, inFileName, 0, 0, IOUtils.getStringFromReader(in));
} else { /* eval */
Object obj = mgr.eval(language, inFileName, 0, 0, IOUtils.getStringFromReader(in));
// Try to display the result.
if (obj instanceof java.awt.Component) {
Frame f;
if (obj instanceof Frame) {
f = (Frame) obj;
} else {
f = new Frame ("BSF Result: " + inFileName);
f.add ((java.awt.Component) obj);
}
// Add a window listener to quit on closing.
f.addWindowListener(
new WindowAdapter () {
public void windowClosing (WindowEvent e) {
System.exit (0);
}
}
);
f.pack ();
// f.show(); // javac 1.5 warns to use f.show(), Apache build scripts abort as a result :(
f.setVisible(true); // available since Java 1.1
} else {
System.err.println("Result: " + obj);
}
System.err.println("Result: " + obj);
}
}
} catch (BSFException e) {
e.printStackTrace();
}
}
private static void printHelp() {
System.err.println("Usage:");
System.err.println();
System.err.println(" java " + Main.class.getName() + " [args]");
System.err.println();
System.err.println(" args:");
System.err.println();
System.err.println(
" [-in fileName] default: " + DEFAULT_IN_FILE_NAME);
System.err.println(
" [-lang languageName] default: "
+ "<If -in is specified and -lang");
System.err.println(
" "
+ " is not, attempt to determine");
System.err.println(
" "
+ " language from file extension;");
System.err.println(
" "
+ " otherwise, -lang is required.>");
System.err.println(
" [-mode (eval|exec|compile)] default: " + DEFAULT_MODE);
System.err.println();
System.err.println(
" Additional args used only if -mode is " + "set to \"compile\":");
System.err.println();
System.err.println(
" [-out className] default: " + DEFAULT_CLASS_NAME);
}
}

View File

@ -0,0 +1,107 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.jacl;
import com.volmit.iris.util.bsf.BSFEngine;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.EngineUtils;
import tcl.lang.Command;
import tcl.lang.Interp;
import tcl.lang.ReflectObject;
import tcl.lang.TCL;
import tcl.lang.TclException;
import tcl.lang.TclObject;
// class used to add "bsf" command to the Jacl runtime
class BSFCommand implements Command {
BSFManager mgr;
BSFEngine jengine;
BSFCommand (BSFManager mgr, BSFEngine jengine) {
this.mgr = mgr;
this.jengine = jengine;
}
public void cmdProc (Interp interp,
TclObject argv[]) throws TclException {
if (argv.length < 2) {
interp.setResult ("invalid # of args; usage: bsf " +
"lookupBean|registerBean|unregisterBean|addEventListener args");
throw new TclException (TCL.ERROR);
}
String op = argv[1].toString ();
if (op.equals ("lookupBean")) {
if (argv.length != 3) {
interp.setResult ("invalid # of args; usage: bsf " +
"lookupBean name-of-bean");
throw new TclException (TCL.ERROR);
}
String beanName = argv[2].toString ();
Object bean = mgr.lookupBean (beanName);
if (bean == null) {
interp.setResult ("unknown object: " + beanName);
throw new TclException (TCL.ERROR);
}
interp.setResult (ReflectObject.newInstance (interp, bean.getClass (),
bean));
} else if (op.equals ("registerBean")) {
if (argv.length != 4) {
interp.setResult ("invalid # of args; usage: bsf " +
"registerBean name-of-bean bean");
throw new TclException (TCL.ERROR);
}
mgr.registerBean (argv[2].toString (),
ReflectObject.get (interp, argv[3]));
interp.setResult ("");
} else if (op.equals ("unregisterBean")) {
if (argv.length != 3) {
interp.setResult ("invalid # of args; usage: bsf " +
"unregisterBean name-of-bean");
throw new TclException (TCL.ERROR);
}
mgr.unregisterBean (argv[2].toString ());
interp.setResult ("");
} else if (op.equals ("addEventListener")) {
if (argv.length != 6) {
interp.setResult ("invalid # of args; usage: bsf " +
"addEventListener object event-set-name filter " +
"script-to-run");
throw new TclException (TCL.ERROR);
}
try {
// usage: bsf addEventListener object event-set filter script
String filter = argv[4].toString ();
filter = filter.equals ("") ? null : filter;
EngineUtils.addEventListener (ReflectObject.get (interp, argv[2]),
argv[3].toString (), filter,
jengine, mgr, "<event-script>", 0, 0,
argv[5].toString ());
} catch (BSFException e) {
e.printStackTrace ();
interp.setResult ("got BSF exception: " + e.getMessage ());
throw new TclException (TCL.ERROR);
}
}
}
}

View File

@ -0,0 +1,136 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.jacl;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFDeclaredBean;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import tcl.lang.Interp;
import tcl.lang.ReflectObject;
import tcl.lang.TclDouble;
import tcl.lang.TclException;
import tcl.lang.TclInteger;
import tcl.lang.TclObject;
import tcl.lang.TclString;
/**
* This is the interface to Scriptics's Jacl (Tcl) from the
* Bean Scripting Framework.
* <p>
*
* @author Sanjiva Weerawarana
*/
public class JaclEngine extends BSFEngineImpl {
/* the Jacl interpretor object */
private Interp interp;
/**
*
* @param method The name of the method to call.
* @param args an array of arguments to be
* passed to the extension, which may be either
* Vectors of Nodes, or Strings.
*/
public Object call (Object obj, String method, Object[] args)
throws BSFException {
StringBuffer tclScript = new StringBuffer (method);
if (args != null) {
for( int i = 0 ; i < args.length ; i++ ) {
tclScript.append (" ");
tclScript.append (args[i].toString ());
}
}
return eval ("<function call>", 0, 0, tclScript.toString ());
}
/**
* Declare a bean
*/
public void declareBean (BSFDeclaredBean bean) throws BSFException {
String expr = "set " + bean.name + " [bsf lookupBean \"" + bean.name +
"\"]";
eval ("<declare bean>", 0, 0, expr);
}
/**
* This is used by an application to evaluate a string containing
* some expression.
*/
public Object eval (String source, int lineNo, int columnNo,
Object oscript) throws BSFException {
String script = oscript.toString ();
try {
interp.eval (script);
TclObject result = interp.getResult();
Object internalRep = result.getInternalRep();
// if the object has a corresponding Java type, unwrap it
if (internalRep instanceof ReflectObject)
return ReflectObject.get(interp,result);
if (internalRep instanceof TclString)
return result.toString();
if (internalRep instanceof TclDouble)
return new Double(TclDouble.get(interp,result));
if (internalRep instanceof TclInteger)
return new Integer(TclInteger.get(interp,result));
return result;
} catch (TclException e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"error while eval'ing Jacl expression: " +
interp.getResult (), e);
}
}
/**
* Initialize the engine.
*/
public void initialize (BSFManager mgr, String lang,
Vector declaredBeans) throws BSFException {
super.initialize (mgr, lang, declaredBeans);
// create interpreter
interp = new Interp();
// register the extension that user's can use to get at objects
// registered by the app
interp.createCommand ("bsf", new BSFCommand (mgr, this));
// Make java functions be available to Jacl
try {
interp.eval("jaclloadjava");
} catch (TclException e) {
throw new BSFException (BSFException.REASON_OTHER_ERROR,
"error while loading java package: " +
interp.getResult (), e);
}
int size = declaredBeans.size ();
for (int i = 0; i < size; i++) {
declareBean ((BSFDeclaredBean) declaredBeans.elementAt (i));
}
}
/**
* Undeclare a previously declared bean.
*/
public void undeclareBean (BSFDeclaredBean bean) throws BSFException {
eval ("<undeclare bean>", 0, 0, "set " + bean.name + " \"\"");
}
}

View File

@ -0,0 +1,352 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.java;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import com.volmit.iris.util.bsf.util.CodeBuffer;
import com.volmit.iris.util.bsf.util.EngineUtils;
import com.volmit.iris.util.bsf.util.JavaUtils;
import com.volmit.iris.util.bsf.util.MethodUtils;
import com.volmit.iris.util.bsf.util.ObjInfo;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This is the interface to Java from the
* Bean Scripting Framework.
* <p>
* The Java code must be written script-style -- that is, just the body of
* the function, without class or method headers or footers.
* The JavaEngine will generate those via a "boilerplate" wrapper:
* <pre>
* <code>
* import java.lang.*;
* import java.util.*;
* public class $$CLASSNAME$$ {
* static public Object BSFJavaEngineEntry(com.volmit.iris.util.bsf.BSFManager bsf) {
* // Your code will be placed here
* }
* }
* </code>
* </pre>
* $$CLASSNAME$$ will be replaced by a generated classname of the form
* BSFJava*, and the bsf parameter can be used to retrieve application
* objects registered with the Bean Scripting Framework.
* <p>
* If you use the placeholder string $$CLASSNAME$$ elsewhere
* in your script -- including within text strings -- BSFJavaEngine will
* replace it with the generated name of the class before the Java code
* is compiled.
* <p>
* <h2>Hazards:</h2>
* <p>
* NOTE that it is your responsibility to convert the code into an acceptable
* Java string. If you're invoking the JavaEngine directly (as in the
* JSPLikeInJava example) that means \"quoting\" characters that would
* otherwise cause trouble.
* <p>
* ALSO NOTE that it is your responsibility to return an object, or null in
* lieu thereof!
* <p>
* Since the code has to be compiled to a Java classfile, invoking it involves
* a fair amount of computation to load and execute the compiler. We are
* currently making an attempt to manage that by caching the class
* after it has been loaded, but the indexing is fairly primitive. It has
* been suggested that the Bean Scripting Framework may want to support
* preload-and-name-script and execute-preloaded-script-by-name options to
* provide better control over when and how much overhead occurs.
* <p>
* @author Joe Kesselman
*/
public class JavaEngine extends BSFEngineImpl {
Class javaclass = null;
static Hashtable codeToClass = new Hashtable();
static String serializeCompilation = "";
static String placeholder = "$$CLASSNAME$$";
String minorPrefix;
private Log logger = LogFactory.getLog(this.getClass().getName());
/**
* Create a scratchfile, open it for writing, return its name.
* Relies on the filesystem to provide us with uniqueness testing.
* NOTE THAT uniqueFileOffset continues to count; we don't want to
* risk reusing a classname we have previously loaded in this session
* even if the classfile has been deleted.
*/
private int uniqueFileOffset = -1;
private class GeneratedFile {
File file = null;
FileOutputStream fos = null;
String className = null;
GeneratedFile(File file, FileOutputStream fos, String className) {
this.file = file;
this.fos = fos;
this.className = className;
}
}
/**
* Constructor.
*/
public JavaEngine () {
// Do compilation-possible check here??????????????
}
public Object call (Object object, String method, Object[] args)
throws BSFException
{
throw new BSFException (BSFException.REASON_UNSUPPORTED_FEATURE,
"call() is not currently supported by JavaEngine");
}
public void compileScript (String source, int lineNo, int columnNo,
Object script, CodeBuffer cb) throws BSFException {
ObjInfo oldRet = cb.getFinalServiceMethodStatement ();
if (oldRet != null && oldRet.isExecutable ()) {
cb.addServiceMethodStatement (oldRet.objName + ";");
}
cb.addServiceMethodStatement (script.toString ());
cb.setFinalServiceMethodStatement (null);
}
/**
* This is used by an application to evaluate a string containing
* some expression. It should store the "bsf" handle where the
* script can get to it, for callback purposes.
* <p>
* Note that Java compilation imposes serious overhead,
* but in exchange you get full Java performance
* once the classes have been created (minus the cache lookup cost).
* <p>
* Nobody knows whether javac is threadsafe.
* I'm going to serialize access to protect it.
* <p>
* There is no published API for invoking javac as a class. There's a trick
* that seems to work for Java 1.1.x, but it stopped working in Java 1.2.
* We will attempt to use it, then if necessary fall back on invoking
* javac via the command line.
*/
public Object eval (String source, int lineNo, int columnNo,
Object oscript) throws BSFException
{
Object retval = null;
String classname = null;
GeneratedFile gf = null;
String basescript = oscript.toString();
String script = basescript; // May be altered by $$CLASSNAME$$ expansion
try {
// Do we already have a class exactly matching this code?
javaclass = (Class)codeToClass.get(basescript);
if(javaclass != null) {
classname=javaclass.getName();
} else {
gf = openUniqueFile(tempDir, "BSFJava",".java");
if( gf == null) {
throw new BSFException("couldn't create JavaEngine scratchfile");
}
// Obtain classname
classname = gf.className;
// Write the kluge header to the file.
gf.fos.write(("import java.lang.*;"+
"import java.util.*;"+
"public class "+classname+" {\n" +
" static public Object BSFJavaEngineEntry(com.volmit.iris.util.bsf.BSFManager bsf) {\n")
.getBytes());
// Edit the script to replace placeholder with the generated
// classname. Note that this occurs _after_ the cache was checked!
int startpoint = script.indexOf(placeholder);
int endpoint;
if(startpoint >= 0) {
StringBuffer changed = new StringBuffer();
for(; startpoint >=0; startpoint = script.indexOf(placeholder,startpoint)) {
changed.setLength(0); // Reset for 2nd pass or later
if(startpoint > 0) {
changed.append(script.substring(0,startpoint));
}
changed.append(classname);
endpoint = startpoint+placeholder.length();
if(endpoint < script.length()) {
changed.append(script.substring(endpoint));
}
script = changed.toString();
}
}
// MJD - debug
// BSFDeclaredBean tempBean;
// String className;
//
// for (int i = 0; i < declaredBeans.size (); i++) {
// tempBean = (BSFDeclaredBean) declaredBeans.elementAt (i);
// className = StringUtils.getClassName (tempBean.bean.getClass ());
//
// gf.fos.write ((className + " " +
// tempBean.name + " = (" + className +
// ")bsf.lookupBean(\"" +
// tempBean.name + "\");").getBytes ());
// }
// MJD - debug
// Copy the input to the file.
// Assumes all available -- probably mistake, but same as other engines.
gf.fos.write(script.getBytes());
// Close the method and class
gf.fos.write(("\n }\n}\n").getBytes());
gf.fos.close();
// Compile through Java to .class file
// May not be threadsafe. Serialize access on static object:
synchronized(serializeCompilation) {
JavaUtils.JDKcompile(gf.file.getPath(), classPath);
}
// Load class.
javaclass = EngineUtils.loadClass(mgr, classname);
// Stash class for reuse
codeToClass.put(basescript, javaclass);
}
Object[] callArgs = {mgr};
retval = internalCall(this,"BSFJavaEngineEntry",callArgs);
}
catch(Exception e) {
e.printStackTrace ();
throw new BSFException (BSFException.REASON_IO_ERROR, e.getMessage ());
} finally {
// Cleanup: delete the .java and .class files
// if(gf!=null && gf.file!=null && gf.file.exists())
// gf.file.delete(); // .java file
if(classname!=null) {
// Generated class
File file = new File(tempDir+File.separatorChar+classname+".class");
// if(file.exists())
// file.delete();
// Search for and clean up minor classes, classname$xxx.class
file = new File(tempDir); // ***** Is this required?
minorPrefix = classname+"$"; // Indirect arg to filter
String[] minorClassfiles = file.list(new FilenameFilter()
{
// Starts with classname$ and ends with .class
public boolean accept(File dir,String name) {
return
(0 == name.indexOf(minorPrefix))
&&
(name.lastIndexOf(".class") == name.length()-6);
}
});
for(int i = 0; i < minorClassfiles.length; ++i) {
file = new File(minorClassfiles[i]);
// file.delete();
}
}
}
return retval;
}
public void initialize (BSFManager mgr, String lang,
Vector declaredBeans) throws BSFException {
super.initialize (mgr, lang, declaredBeans);
}
/**
* Return an object from an extension.
* @param object Object on which to make the internal_call (ignored).
* @param method The name of the method to internal_call.
* @param args an array of arguments to be
* passed to the extension, which may be either
* Vectors of Nodes, or Strings.
*/
Object internalCall (Object object, String method, Object[] args)
throws BSFException
{
//***** ISSUE: Only static methods are currently supported
Object retval = null;
try {
if(javaclass != null) {
//***** This should call the lookup used in BML, for typesafety
Class[] argtypes = new Class[args.length];
for(int i=0; i<args.length; ++i) {
argtypes[i]=args[i].getClass();
}
Method m = MethodUtils.getMethod(javaclass, method, argtypes);
retval = m.invoke(null, args);
}
}
catch(Exception e) {
throw new BSFException (BSFException.REASON_IO_ERROR, e.getMessage ());
}
return retval;
}
private GeneratedFile openUniqueFile(String directory,String prefix,String suffix) {
File file = null;
FileOutputStream fos = null;
int max = 1000; // Don't try forever
GeneratedFile gf = null;
int i;
String className = null;
for(i=max,++uniqueFileOffset; fos==null && i>0;--i,++uniqueFileOffset) {
// Probably a timing hazard here... ***************
try {
className = prefix+uniqueFileOffset;
file = new File(directory+File.separatorChar+className+suffix);
if(file != null && !file.exists()) {
fos = new FileOutputStream(file);
}
}
catch(Exception e) {
// File could not be opened for write, or Security Exception
// was thrown. If someone else created the file before we could
// open it, that's probably a threading conflict and we don't
// bother reporting it.
if(!file.exists()) {
logger.error("openUniqueFile: unexpected ", e);
}
}
}
if(fos==null) {
logger.error("openUniqueFile: Failed "+max+"attempts.");
} else {
gf = new GeneratedFile(file,fos,className);
}
return gf;
}
}

View File

@ -0,0 +1,73 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.javaclass;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import com.volmit.iris.util.bsf.util.MethodUtils;
/**
* This is the interface to scripts consisting of Java objects from the
* Bean Scripting Framework.
*
* @author Sanjiva Weerawarana
*/
public class JavaClassEngine extends BSFEngineImpl {
/**
* call the named method of the given object. If object is an instance
* of Class, then the call is a static call on that object. If not, its
* an instance method call or a static call (as per Java) on the given
* object.
*/
public Object call (Object object, String method, Object[] args)
throws BSFException {
// determine arg types
Class[] argTypes = null;
if (args != null) {
argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = (args[i] != null) ? args[i].getClass () : null;
}
}
// now find method with the right signature, call it and return result
try {
Method m = MethodUtils.getMethod (object, method, argTypes);
return m.invoke (object, args);
} catch (Exception e) {
// something went wrong while invoking method
Throwable t = (e instanceof InvocationTargetException) ?
((InvocationTargetException)e).getTargetException () :
null;
throw new BSFException (BSFException.REASON_OTHER_ERROR,
"method invocation failed: " + e +
((t==null)?"":(" target exception: "+t)), t);
}
}
/**
* This is used by an application to evaluate an object containing
* some expression - clearly not possible for compiled code ..
*/
public Object eval (String source, int lineNo, int columnNo,
Object oscript) throws BSFException {
throw new BSFException (BSFException.REASON_UNSUPPORTED_FEATURE,
"Java bytecode engine can't evaluate expressions");
}
}

View File

@ -0,0 +1,233 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.javascript;
import java.util.Iterator;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFDeclaredBean;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import com.volmit.iris.util.bsf.util.BSFFunctions;
import org.mozilla.javascript.Context;
import org.mozilla.javascript.EvaluatorException;
import org.mozilla.javascript.Function;
import org.mozilla.javascript.ImporterTopLevel;
import org.mozilla.javascript.JavaScriptException;
import org.mozilla.javascript.NativeJavaObject;
import org.mozilla.javascript.Scriptable;
import org.mozilla.javascript.WrappedException;
import org.mozilla.javascript.Wrapper;
/**
* This is the interface to Netscape's Rhino (JavaScript) from the
* Bean Scripting Framework.
* <p>
* The original version of this code was first written by Adam Peller
* for use in LotusXSL. Sanjiva took his code and adapted it for BSF.
*
* @author Adam Peller <peller@lotus.com>
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @author Norris Boyd
*/
public class JavaScriptEngine extends BSFEngineImpl {
/**
* The global script object, where all embedded functions are defined,
* as well as the standard ECMA "core" objects.
*/
private Scriptable global;
/**
* Return an object from an extension.
* @param object Object on which to make the call (ignored).
* @param method The name of the method to call.
* @param args an array of arguments to be
* passed to the extension, which may be either
* Vectors of Nodes, or Strings.
*/
public Object call(Object object, String method, Object[] args)
throws BSFException {
Object retval = null;
Context cx;
try {
cx = Context.enter();
// REMIND: convert arg list Vectors here?
Object fun = global.get(method, global);
// NOTE: Source and line arguments are nonsense in a call().
// Any way to make these arguments *sensible?
if (fun == Scriptable.NOT_FOUND)
throw new EvaluatorException("function " + method +
" not found.", "none", 0);
cx.setOptimizationLevel(-1);
cx.setGeneratingDebug(false);
cx.setGeneratingSource(false);
cx.setOptimizationLevel(0);
cx.setDebugger(null, null);
retval =
((Function) fun).call(cx, global, global, args);
// ScriptRuntime.call(cx, fun, global, args, global);
if (retval instanceof Wrapper)
retval = ((Wrapper) retval).unwrap();
}
catch (Throwable t) {
handleError(t);
}
finally {
Context.exit();
}
return retval;
}
public void declareBean(BSFDeclaredBean bean) throws BSFException {
if ((bean.bean instanceof Number) ||
(bean.bean instanceof String) ||
(bean.bean instanceof Boolean)) {
global.put(bean.name, global, bean.bean);
}
else {
// Must wrap non-scriptable objects before presenting to Rhino
Scriptable wrapped = Context.toObject(bean.bean, global);
global.put(bean.name, global, wrapped);
}
}
/**
* This is used by an application to evaluate a string containing
* some expression.
*/
public Object eval(String source, int lineNo, int columnNo, Object oscript)
throws BSFException {
String scriptText = oscript.toString();
Object retval = null;
Context cx;
try {
cx = Context.enter();
cx.setOptimizationLevel(-1);
cx.setGeneratingDebug(false);
cx.setGeneratingSource(false);
cx.setOptimizationLevel(0);
cx.setDebugger(null, null);
retval = cx.evaluateString(global, scriptText,
source, lineNo,
null);
if (retval instanceof NativeJavaObject)
retval = ((NativeJavaObject) retval).unwrap();
}
catch (Throwable t) { // includes JavaScriptException, rethrows Errors
handleError(t);
}
finally {
Context.exit();
}
return retval;
}
private void handleError(Throwable t) throws BSFException {
if (t instanceof WrappedException)
t = ((WrappedException) t).getWrappedException();
String message = null;
Throwable target = t;
if (t instanceof JavaScriptException) {
message = t.getLocalizedMessage();
// Is it an exception wrapped in a JavaScriptException?
Object value = ((JavaScriptException) t).getValue();
if (value instanceof Throwable) {
// likely a wrapped exception from a LiveConnect call.
// Display its stack trace as a diagnostic
target = (Throwable) value;
}
}
else if (t instanceof EvaluatorException ||
t instanceof SecurityException) {
message = t.getLocalizedMessage();
}
else if (t instanceof RuntimeException) {
message = "Internal Error: " + t.toString();
}
else if (t instanceof StackOverflowError) {
message = "Stack Overflow";
}
if (message == null)
message = t.toString();
if (t instanceof Error && !(t instanceof StackOverflowError)) {
// Re-throw Errors because we're supposed to let the JVM see it
// Don't re-throw StackOverflows, because we know we've
// corrected the situation by aborting the loop and
// a long stacktrace would end up on the user's console
throw (Error) t;
}
else {
throw new BSFException(BSFException.REASON_OTHER_ERROR,
"JavaScript Error: " + message,
target);
}
}
/**
* Initialize the engine.
* Put the manager into the context-manager
* map hashtable too.
*/
public void initialize(BSFManager mgr, String lang, Vector declaredBeans)
throws BSFException {
super.initialize(mgr, lang, declaredBeans);
// Initialize context and global scope object
try {
Context cx = Context.enter();
global = new ImporterTopLevel(cx);
Scriptable bsf = Context.toObject(new BSFFunctions(mgr, this), global);
global.put("bsf", global, bsf);
for(Iterator it = declaredBeans.iterator(); it.hasNext();) {
declareBean((BSFDeclaredBean) it.next());
}
}
catch (Throwable t) {
}
finally {
Context.exit();
}
}
public void undeclareBean(BSFDeclaredBean bean) throws BSFException {
global.delete(bean.name);
}
}

View File

@ -0,0 +1,244 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.jython;
import java.io.ByteArrayInputStream;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFDeclaredBean;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import com.volmit.iris.util.bsf.util.BSFFunctions;
import org.python.core.Py;
import org.python.core.PyException;
import org.python.core.PyJavaInstance;
import org.python.core.PyObject;
import org.python.util.InteractiveInterpreter;
/**
* This is the interface to Jython (http://www.jython.org/) from BSF.
* It's derived from the JPython 1.x engine
*
* @author Sanjiva Weerawarana
* @author Finn Bock <bckfnn@worldonline.dk>
* @author Chuck Murcko
*/
public class JythonEngine extends BSFEngineImpl {
BSFPythonInterpreter interp;
/**
* call the named method of the given object.
*/
public Object call (Object object, String method, Object[] args)
throws BSFException {
try {
PyObject[] pyargs = Py.EmptyObjects;
if (args != null) {
pyargs = new PyObject[args.length];
for (int i = 0; i < pyargs.length; i++)
pyargs[i] = Py.java2py(args[i]);
}
if (object != null) {
PyObject o = Py.java2py(object);
return unwrap(o.invoke(method, pyargs));
}
PyObject m = interp.get(method);
if (m == null)
m = interp.eval(method);
if (m != null) {
return unwrap(m.__call__(pyargs));
}
return null;
} catch (PyException e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"exception from Jython:\n" + e, e);
}
}
/**
* Declare a bean
*/
public void declareBean (BSFDeclaredBean bean) throws BSFException {
interp.set (bean.name, bean.bean);
}
/**
* Evaluate an anonymous function (differs from eval() in that apply()
* handles multiple lines).
*/
public Object apply (String source, int lineNo, int columnNo,
Object funcBody, Vector paramNames,
Vector arguments) throws BSFException {
try {
/* We wrapper the original script in a function definition, and
* evaluate the function. A hack, no question, but it allows
* apply() to pretend to work on Jython.
*/
StringBuffer script = new StringBuffer(byteify(funcBody.toString()));
int index = 0;
script.insert(0, "def bsf_temp_fn():\n");
while (index < script.length()) {
if (script.charAt(index) == '\n') {
script.insert(index+1, '\t');
}
index++;
}
interp.exec (script.toString ());
Object result = interp.eval ("bsf_temp_fn()");
if (result != null && result instanceof PyJavaInstance)
result = ((PyJavaInstance)result).__tojava__(Object.class);
return result;
} catch (PyException e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"exception from Jython:\n" + e, e);
}
}
/**
* Evaluate an expression.
*/
public Object eval (String source, int lineNo, int columnNo,
Object script) throws BSFException {
try {
Object result = interp.eval (byteify(script.toString ()));
if (result != null && result instanceof PyJavaInstance)
result = ((PyJavaInstance)result).__tojava__(Object.class);
return result;
} catch (PyException e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"exception from Jython:\n" + e, e);
}
}
/**
* Execute a script.
*/
public void exec (String source, int lineNo, int columnNo,
Object script) throws BSFException {
try {
interp.exec (byteify(script.toString ()));
} catch (PyException e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"exception from Jython:\n" + e, e);
}
}
/**
* Execute script code, emulating console interaction.
*/
public void iexec (String source, int lineNo, int columnNo,
Object script) throws BSFException {
String scriptStr = byteify(script.toString());
int newline = scriptStr.indexOf("\n");
if (newline > -1)
scriptStr = scriptStr.substring(0, newline);
try {
if (interp.buffer.length() > 0)
interp.buffer.append("\n");
interp.buffer.append(scriptStr);
if (!(interp.runsource(interp.buffer.toString())))
interp.resetbuffer();
} catch (PyException e) {
interp.resetbuffer();
throw new BSFException(BSFException.REASON_EXECUTION_ERROR,
"exception from Jython:\n" + e, e);
}
}
/**
* Initialize the engine.
*/
public void initialize (BSFManager mgr, String lang,
Vector declaredBeans) throws BSFException {
super.initialize (mgr, lang, declaredBeans);
// create an interpreter
interp = new BSFPythonInterpreter ();
// ensure that output and error streams are re-directed correctly
interp.setOut(System.out);
interp.setErr(System.err);
// register the mgr with object name "bsf"
interp.set ("bsf", new BSFFunctions (mgr, this));
// Declare all declared beans to the interpreter
int size = declaredBeans.size ();
for (int i = 0; i < size; i++) {
declareBean ((BSFDeclaredBean) declaredBeans.elementAt (i));
}
}
/**
* Undeclare a previously declared bean.
*/
public void undeclareBean (BSFDeclaredBean bean) throws BSFException {
interp.set (bean.name, null);
}
public Object unwrap(PyObject result) {
if (result != null) {
Object ret = result.__tojava__(Object.class);
if (ret != Py.NoConversion)
return ret;
}
return result;
}
private String byteify (String orig) {
// Ugh. Jython likes to be fed bytes, rather than the input string.
ByteArrayInputStream bais =
new ByteArrayInputStream(orig.getBytes());
StringBuffer s = new StringBuffer();
int c;
while ((c = bais.read()) >= 0) {
s.append((char)c);
}
return s.toString();
}
private class BSFPythonInterpreter extends InteractiveInterpreter {
public BSFPythonInterpreter() {
super();
}
// Override runcode so as not to print the stack dump
public void runcode(PyObject code) {
try {
this.exec(code);
} catch (PyException exc) {
throw exc;
}
}
}
}

View File

@ -0,0 +1,497 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.netrexx;
import java.io.File;
import java.io.FileOutputStream;
import java.io.FilenameFilter;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Hashtable;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFDeclaredBean;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import com.volmit.iris.util.bsf.util.BSFFunctions;
import com.volmit.iris.util.bsf.util.EngineUtils;
import com.volmit.iris.util.bsf.util.MethodUtils;
import com.volmit.iris.util.bsf.util.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
* This is the interface to NetRexx from the
* Bean Scripting Framework.
* <p>
* The NetRexx code must be written script-style, without a "class" or
* "properties" section preceeding the executable code. The NetRexxEngine will
* generate a prefix for this code:
* <pre>
* <code>
* class $$CLASSNAME$$;
* method BSFNetRexxEngineEntry(bsf=com.volmit.iris.util.bsf.BSFManager) public static;
* </code>
* </pre>
* $$CLASSNAME$$ will be replaced by a generated classname of the form
* BSFNetRexx*, and the bsf parameter can be used to retrieve application
* objects registered with the Bean Scripting Framework.
* <p>
* If you use the placeholder string $$CLASSNAME$$ elsewhere
* in your script -- including within text strings -- BSFNetRexxEngine will
* replace it with the generated name of the class before the NetRexx code
* is compiled.
* <p>
* If you need to use full NetRexx functionality, we recommend that your
* NetRexx script define and invoke a "minor class", with or without the
* "dependent" keyword as suits your needs. You'll have to use $$CLASSNAME$$
* in naming the minor class, since the name of the main class is synthesized;
* for example, to create the minor class "bar" you'd write
* "class $$CLASSNAME$$.Bar".
* <p>
* <h2>Hazards:</h2>
* <p>
* Since NetRexx has to be _compiled_ to a Java classfile, invoking it involves
* a fair amount of computation to load and execute the compiler. We are
* currently making an attempt to manage that by caching the class
* after it has been loaded, but the indexing is fairly primitive; we
* hash against the script string to find the class for it.
* <p>
* Minor-class .class files are now being deleted after the major class loads.
* This coould potentially cause problems.
*
* @author Joe Kesselman
* @author Sanjiva Weerawarana
*/
public class NetRexxEngine extends BSFEngineImpl
{
BSFFunctions mgrfuncs;
static Hashtable codeToClass=new Hashtable();
static String serializeCompilation="";
static String placeholder="$$CLASSNAME$$";
String minorPrefix;
private Log logger = LogFactory.getLog(this.getClass().getName());
/**
* Create a scratchfile, open it for writing, return its name.
* Relies on the filesystem to provide us with uniqueness testing.
* NOTE THAT uniqueFileOffset continues to count; we don't want to
* risk reusing a classname we have previously loaded in this session
* even if the classfile has been deleted.
*
* I've made the offset static, due to concerns about reuse/reentrancy
* of the NetRexx engine.
*/
private static int uniqueFileOffset=0;
private class GeneratedFile
{
File file=null;
FileOutputStream fos=null;
String className=null;
GeneratedFile(File file,FileOutputStream fos,String className)
{
this.file=file;
this.fos=fos;
this.className=className;
}
}
// rexxclass used to be an instance variable, on the theory that
// each NetRexxEngine was an instance of a specific script.
// BSF is currently reusing Engines, so caching the class
// no longer makes sense.
// Class rexxclass;
/**
* Constructor.
*/
public NetRexxEngine ()
{
/*
The following line is intended to cause the constructor to
throw a NoClassDefFoundError if the NetRexxC.zip dependency
is not resolved.
If this line was not here, the problem would not surface until
the actual processing of a script. We want to know all is well
at the time the engine is instantiated, not when we attempt to
process a script.
*/
new netrexx.lang.BadArgumentException();
}
/**
* Return an object from an extension.
* @param object object from which to call our static method
* @param method The name of the method to call.
* @param args an array of arguments to be
* passed to the extension, which may be either
* Vectors of Nodes, or Strings.
*/
public Object call (Object object, String method, Object[] args)
throws BSFException
{
throw new BSFException(BSFException.REASON_UNSUPPORTED_FEATURE,
"NetRexx doesn't currently support call()",
null);
}
/**
* Invoke a static method.
* @param rexxclass Class to invoke the method against
* @param method The name of the method to call.
* @param args an array of arguments to be
* passed to the extension, which may be either
* Vectors of Nodes, or Strings.
*/
Object callStatic(Class rexxclass, String method, Object[] args)
throws BSFException
{
//***** ISSUE: Currently supports only static methods
Object retval = null;
try
{
if (rexxclass != null)
{
//***** This should call the lookup used in BML, for typesafety
Class[] argtypes=new Class[args.length];
for(int i=0;i<args.length;++i)
argtypes[i]=args[i].getClass();
Method m=MethodUtils.getMethod(rexxclass, method, argtypes);
retval=m.invoke(null,args);
}
else
{
logger.error("NetRexxEngine: ERROR: rexxclass==null!");
}
}
catch(Exception e)
{
e.printStackTrace ();
if (e instanceof InvocationTargetException)
{
Throwable t = ((InvocationTargetException)e).getTargetException ();
t.printStackTrace ();
}
throw new BSFException (BSFException.REASON_IO_ERROR,
e.getMessage (),
e);
}
return retval;
}
public void declareBean (BSFDeclaredBean bean) throws BSFException {}
/**
* Override impl of execute. In NetRexx, methods which do not wish
* to return a value should be invoked via exec, which will cause them
* to be generated without the "returns" clause.
* Those which wish to return a value should call eval instead.
* which will add "returns java.lang.Object" to the header.
*
* Note: It would be nice to have the "real" return type avaialable, so
* we could do something more type-safe than Object, and so we could
* return primitive types without having to enclose them in their
* object wrappers. BSF does not currently support that concept.
*/
public Object eval (String source, int lineNo, int columnNo,
Object script)
throws BSFException
{
return execEvalShared(source, lineNo, columnNo, script,true);
}
/**
* Override impl of execute. In NetRexx, methods which do not wish
* to return a value should be invoked via exec, which will cause them
* to be generated without the "returns" clause.
* Those which wish to return a value should call eval instead.
* which will add "returns java.lang.Object" to the header.
*/
public void exec (String source, int lineNo, int columnNo,
Object script)
throws BSFException
{
execEvalShared(source, lineNo, columnNo, script,false);
}
/**
* This is shared code for the exec() and eval() operations. It will
* evaluate a string containing a NetRexx method body -- which may be
* as simple as a single return statement.
* It should store the "bsf" handle where the
* script can get to it, for callback purposes.
* <p>
* Note that NetRexx compilation imposes serious overhead -- 11 seconds for
* the first compile, about 3 thereafter -- but in exchange you get
* Java-like speeds once the classes have been created (minus the cache
* lookup cost).
* <p>
* Nobody knows whether javac is threadsafe.
* I'm going to serialize access to the compilers to protect it.
*/
public Object execEvalShared (String source, int lineNo, int columnNo,
Object oscript,boolean returnsObject)
throws BSFException
{
Object retval=null;
String classname=null;
GeneratedFile gf=null;
// Moved into the exec process; see comment above.
Class rexxclass=null;
String basescript=oscript.toString();
String script=basescript; // May be altered by $$CLASSNAME$$ expansion
try {
// Do we already have a class exactly matching this code?
rexxclass=(Class)codeToClass.get(basescript);
if(rexxclass!=null)
{
logger.debug("NetRexxEngine: Found pre-compiled class" +
" for script '" + basescript + "'");
classname=rexxclass.getName();
}
else
{
gf=openUniqueFile(tempDir,"BSFNetRexx",".nrx");
if(gf==null)
throw new BSFException("couldn't create NetRexx scratchfile");
// Obtain classname
classname=gf.className;
// Decide whether to declare a return type
String returnsDecl="";
if(returnsObject)
returnsDecl="returns java.lang.Object";
// Write the kluge header to the file.
// ***** By doing so we give up the ability to use Property blocks.
gf.fos.write(("class "+classname+";\n")
.getBytes());
gf.fos.write(
("method BSFNetRexxEngineEntry(bsf=com.volmit.iris.util.bsf.util.BSFFunctions) "+
" public static "+returnsDecl+";\n")
.getBytes());
// Edit the script to replace placeholder with the generated
// classname. Note that this occurs _after_ the cache was
// checked!
int startpoint,endpoint;
if((startpoint=script.indexOf(placeholder))>=0)
{
StringBuffer changed=new StringBuffer();
for(;
startpoint>=0;
startpoint=script.indexOf(placeholder,startpoint))
{
changed.setLength(0); // Reset for 2nd pass or later
if(startpoint>0)
changed.append(script.substring(0,startpoint));
changed.append(classname);
endpoint=startpoint+placeholder.length();
if(endpoint<script.length())
changed.append(script.substring(endpoint));
script=changed.toString();
}
}
BSFDeclaredBean tempBean;
String className;
for (int i = 0; i < declaredBeans.size (); i++)
{
tempBean = (BSFDeclaredBean) declaredBeans.elementAt (i);
className = StringUtils.getClassName (tempBean.type);
gf.fos.write ((tempBean.name + " =" + className + " bsf.lookupBean(\"" +
tempBean.name + "\");").getBytes());
}
if(returnsObject)
gf.fos.write("return ".getBytes());
// Copy the input to the file.
// Assumes all available -- probably mistake, but same as
// other engines.
gf.fos.write(script.getBytes());
gf.fos.close();
logger.debug("NetRexxEngine: wrote temp file " +
gf.file.getPath () + ", now compiling");
// Compile through Java to .class file
String command=gf.file.getPath(); //classname;
if (logger.isDebugEnabled()) {
command += " -verbose4";
} else {
command += " -noverbose";
command += " -noconsole";
}
netrexx.lang.Rexx cmdline= new netrexx.lang.Rexx(command);
int retValue;
// May not be threadsafe. Serialize access on static object:
synchronized(serializeCompilation)
{
// compile to a .java file
retValue =
COM.ibm.netrexx.process.NetRexxC.main(cmdline,
new PrintWriter(System.err));
}
// Check if there were errors while compiling the Rexx code.
if (retValue == 2)
{
throw new BSFException(BSFException.REASON_EXECUTION_ERROR,
"There were NetRexx errors.");
}
// Load class.
logger.debug("NetRexxEngine: loading class "+classname);
rexxclass=EngineUtils.loadClass (mgr, classname);
// Stash class for reuse
codeToClass.put(basescript,rexxclass);
}
Object[] args={mgrfuncs};
retval=callStatic(rexxclass, "BSFNetRexxEngineEntry",args);
}
catch (BSFException e)
{
// Just forward the exception on.
throw e;
}
catch(Exception e)
{
e.printStackTrace ();
if (e instanceof InvocationTargetException)
{
Throwable t = ((InvocationTargetException)e).getTargetException ();
t.printStackTrace ();
}
throw new BSFException (BSFException.REASON_IO_ERROR,
e.getMessage (), e);
}
finally
{
// Cleanup: delete the .nrx and .class files
// (if any) generated by NetRexx Trace requests.
if(gf!=null && gf.file!=null && gf.file.exists())
gf.file.delete(); // .nrx file
if(classname!=null)
{
// Generated src
File file=new File(tempDir+File.separatorChar+classname+".java");
if(file.exists())
file.delete();
// Generated class
file=new File(classname+".class");
if(file.exists())
file.delete();
// Can this be done without disrupting trace?
file=new File(tempDir+File.separatorChar+classname+".crossref");
if(file.exists())
file.delete();
// Search for and clean up minor classes, classname$xxx.class
file=new File(tempDir);
minorPrefix=classname+"$"; // Indirect arg to filter
String[] minor_classfiles=
file.list(
// ANONYMOUS CLASS for filter:
new FilenameFilter()
{
// Starts with classname$ and ends with .class
public boolean accept(File dir,String name)
{
return
(0==name.indexOf(minorPrefix))
&&
(name.lastIndexOf(".class")==name.length()-6)
;
}
}
);
if(minor_classfiles!=null)
for(int i=minor_classfiles.length;i>0;)
{
file=new File(minor_classfiles[--i]);
file.delete();
}
}
}
return retval;
}
public void initialize(BSFManager mgr, String lang,Vector declaredBeans)
throws BSFException
{
super.initialize(mgr, lang, declaredBeans);
mgrfuncs = new BSFFunctions (mgr, this);
}
private GeneratedFile openUniqueFile(String directory,String prefix,String suffix)
{
File file=null,obj=null;
FileOutputStream fos=null;
int max=1000; // Don't try forever
GeneratedFile gf=null;
int i;
String className = null;
for(i=max,++uniqueFileOffset;
fos==null && i>0;
--i,++uniqueFileOffset)
{
// Probably a timing hazard here... ***************
try
{
className = prefix+uniqueFileOffset;
file=new File(directory+File.separatorChar+className+suffix);
obj=new File(directory+File.separatorChar+className+".class");
if(file!=null && !file.exists() & obj!=null & !obj.exists())
fos=new FileOutputStream(file);
}
catch(Exception e)
{
// File could not be opened for write, or Security Exception
// was thrown. If someone else created the file before we could
// open it, that's probably a threading conflict and we don't
// bother reporting it.
if(!file.exists())
{
logger.error("openUniqueFile: unexpected "+e);
}
}
}
if(fos==null)
logger.error("openUniqueFile: Failed "+max+"attempts.");
else
gf=new GeneratedFile(file,fos,className);
return gf;
}
public void undeclareBean (BSFDeclaredBean bean) throws BSFException {}
}

View File

@ -0,0 +1,193 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.xslt;
import java.io.File;
import java.io.Reader;
import java.io.StringReader;
import java.net.URL;
import java.util.Vector;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMResult;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamSource;
import com.volmit.iris.util.bsf.BSFDeclaredBean;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.BSFEngineImpl;
import com.volmit.iris.util.bsf.util.BSFFunctions;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.xpath.objects.XObject;
import org.w3c.dom.Node;
/**
* Xerces XSLT interface to BSF. Requires Xalan and Xerces from Apache.
*
* This integration uses the BSF registry to pass in any src document
* and stylesheet base URI that the user may wish to set.
*
* @author Sanjiva Weerawarana
* @author Sam Ruby
*
* Re-implemented for the Xalan 2 codebase
*
* @author Victor J. Orlikowski
*/
public class XSLTEngine extends BSFEngineImpl {
TransformerFactory tFactory;
Transformer transformer;
Log logger = LogFactory.getLog(this.getClass().getName());
/**
* call the named method of the given object.
*/
public Object call (Object object, String method, Object[] args)
throws BSFException {
throw new BSFException (BSFException.REASON_UNSUPPORTED_FEATURE,
"BSF:XSLTEngine can't call methods");
}
/**
* Declare a bean by setting it as a parameter
*/
public void declareBean (BSFDeclaredBean bean) throws BSFException {
transformer.setParameter (bean.name, new XObject (bean.bean));
}
/**
* Evaluate an expression. In this case, an expression is assumed
* to be a stylesheet of the template style (see the XSLT spec).
*/
public Object eval (String source, int lineNo, int columnNo,
Object oscript) throws BSFException {
// get the style base URI (the place from where Xerces XSLT will
// look for imported/included files and referenced docs): if a
// bean named "xslt:styleBaseURI" is registered, then cvt it
// to a string and use that. Otherwise use ".", which means the
// base is the directory where the process is running from
Object sbObj = mgr.lookupBean ("xslt:styleBaseURI");
String styleBaseURI = (sbObj == null) ? "." : sbObj.toString ();
// Locate the stylesheet.
StreamSource styleSource;
styleSource =
new StreamSource(new StringReader(oscript.toString ()));
styleSource.setSystemId(styleBaseURI);
try {
transformer = tFactory.newTransformer(styleSource);
} catch (Exception e) {
logger.error("Exception from Xerces XSLT:", e);
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"Exception from Xerces XSLT: " + e, e);
}
// get the src to work on: if a bean named "xslt:src" is registered
// and its a Node, then use it as the source. If its not a Node, then
// if its a URL parse it, if not treat it as a file and make a URL and
// parse it and go. If no xslt:src is found, use an empty document
// (stylesheet is treated as a literal result element stylesheet)
Object srcObj = mgr.lookupBean ("xslt:src");
Object xis = null;
if (srcObj != null) {
if (srcObj instanceof Node) {
xis = new DOMSource((Node)srcObj);
} else {
try {
String mesg = "as anything";
if (srcObj instanceof Reader) {
xis = new StreamSource ((Reader) srcObj);
mesg = "as a Reader";
} else if (srcObj instanceof File) {
xis = new StreamSource ((File) srcObj);
mesg = "as a file";
} else {
String srcObjstr=srcObj.toString();
xis = new StreamSource (new StringReader(srcObjstr));
if (srcObj instanceof URL) {
mesg = "as a URL";
} else {
((StreamSource) xis).setPublicId (srcObjstr);
mesg = "as an XML string";
}
}
if (xis == null) {
throw new Exception ("Unable to get input from '" +
srcObj + "' " + mesg);
}
} catch (Exception e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"BSF:XSLTEngine: unable to get " +
"input from '" + srcObj + "' as XML", e);
}
}
} else {
// create an empty document - real src must come into the
// stylesheet using "doc(...)" [see XSLT spec] or the stylesheet
// must be of literal result element type
xis = new StreamSource();
}
// set all declared beans as parameters.
for (int i = 0; i < declaredBeans.size (); i++) {
BSFDeclaredBean b = (BSFDeclaredBean) declaredBeans.elementAt (i);
transformer.setParameter (b.name, new XObject (b.bean));
}
// declare a "bsf" parameter which is the BSF handle so that
// the script can do BSF stuff if it wants to
transformer.setParameter ("bsf",
new XObject (new BSFFunctions (mgr, this)));
// do it
try {
DOMResult result = new DOMResult();
transformer.transform ((StreamSource) xis, result);
return new XSLTResultNode (result.getNode());
} catch (Exception e) {
throw new BSFException (BSFException.REASON_EXECUTION_ERROR,
"exception while eval'ing XSLT script" + e, e);
}
}
/**
* Initialize the engine.
*/
public void initialize (BSFManager mgr, String lang,
Vector declaredBeans) throws BSFException {
super.initialize (mgr, lang, declaredBeans);
tFactory = TransformerFactory.newInstance();
}
/**
* Undeclare a bean by setting he parameter represeting it to null
*/
public void undeclareBean (BSFDeclaredBean bean) throws BSFException {
// Cannot clear only one parameter in Xalan 2, so we set it to null
if ((transformer.getParameter (bean.name)) != null) {
transformer.setParameter (bean.name, null);
}
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.engines.xslt;
import org.w3c.dom.Node;
public class XSLTResultNode
{
Node node;
public XSLTResultNode(Node node)
{
this.node = node;
}
public Node getNode()
{
return node;
}
}

View File

@ -0,0 +1,74 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.io.File;
import java.io.FileInputStream;
import java.util.Hashtable;
/**
* This class loader knows to load a class from the tempDir dir
* of the environment of the given manager.
*
* @author Sanjiva Weerawarana
*/
class BSFClassLoader extends ClassLoader {
Hashtable cache = new Hashtable ();
String tempDir = ".";
// note the non-public constructor - this is only avail within
// this package.
BSFClassLoader () {
}
public synchronized Class loadClass (String name, boolean resolve)
throws ClassNotFoundException {
Class c = (Class) cache.get (name);
if (c == null) {
// is it a system class
try {
c = findSystemClass (name);
cache.put (name, c);
return c;
} catch (ClassNotFoundException e) {
// nope
}
try {
byte[] data = loadClassData (name);
c = defineClass (name, data, 0, data.length);
cache.put (name, c);
} catch (Exception e) {
e.printStackTrace ();
throw new ClassNotFoundException ("unable to resolve class '" +
name + "'");
}
}
if (resolve)
resolveClass (c);
return c;
}
private byte[] loadClassData (String name) throws Exception {
String fileName = tempDir + File.separatorChar + name + ".class";
FileInputStream fi = new FileInputStream (fileName);
byte[] data = new byte[fi.available ()];
fi.read (data);
fi.close();
return data;
}
public void setTempDir (String tempDir) {
this.tempDir = tempDir;
}
}

View File

@ -0,0 +1,203 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.beans.PropertyChangeEvent;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFDeclaredBean;
import com.volmit.iris.util.bsf.BSFEngine;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
/**
* This is a base implementation of the BSFEngine interface which
* engine implementations may choose to extend to get the basic
* methods of the interface implemented.
* <p>
*
* @author Sanjiva Weerawarana
* @author Olivier Gruber (added original debugging support)
*/
public abstract class BSFEngineImpl implements BSFEngine {
protected BSFManager mgr; // my manager
protected String lang; // my language string
protected Vector declaredBeans; // BSFDeclaredBeans
protected String classPath;
protected String tempDir;
protected ClassLoader classLoader;
/**
* Default impl of apply - calls eval ignoring parameters and returns
* the result.
*/
public Object apply(String source, int lineNo, int columnNo,
Object funcBody, Vector paramNames, Vector arguments)
throws BSFException {
return eval(source, lineNo, columnNo, funcBody);
}
/**
* Default impl of compileApply - calls compileExpr ignoring parameters.
*/
public void compileApply(String source, int lineNo, int columnNo,
Object funcBody, Vector paramNames,
Vector arguments, CodeBuffer cb)
throws BSFException {
compileExpr(source, lineNo, columnNo, funcBody, cb);
}
/**
* Default impl of compileExpr - generates code that'll create a new
* manager, evaluate the expression, and return the value.
*/
public void compileExpr(String source, int lineNo, int columnNo,
Object expr, CodeBuffer cb) throws BSFException {
ObjInfo bsfInfo = cb.getSymbol("bsf");
if (bsfInfo == null) {
bsfInfo = new ObjInfo(BSFManager.class, "bsf");
cb.addFieldDeclaration("com.volmit.iris.util.bsf.BSFManager bsf = " +
"new com.volmit.iris.util.bsf.BSFManager();");
cb.putSymbol("bsf", bsfInfo);
}
String evalString = bsfInfo.objName + ".eval(\"" + lang + "\", ";
evalString += "request.getRequestURI(), " + lineNo + ", " + columnNo;
evalString += "," + StringUtils.lineSeparator;
evalString += StringUtils.getSafeString(expr.toString()) + ")";
ObjInfo oldRet = cb.getFinalServiceMethodStatement();
if (oldRet != null && oldRet.isExecutable()) {
cb.addServiceMethodStatement(oldRet.objName + ";");
}
cb.setFinalServiceMethodStatement(new ObjInfo(Object.class,
evalString));
cb.addServiceMethodException("com.volmit.iris.util.bsf.BSFException");
}
/**
* Default impl of compileScript - generates code that'll create a new
* manager, and execute the script.
*/
public void compileScript(String source, int lineNo, int columnNo,
Object script, CodeBuffer cb)
throws BSFException {
ObjInfo bsfInfo = cb.getSymbol("bsf");
if (bsfInfo == null) {
bsfInfo = new ObjInfo(BSFManager.class, "bsf");
cb.addFieldDeclaration("com.volmit.iris.util.bsf.BSFManager bsf = " +
"new com.volmit.iris.util.bsf.BSFManager();");
cb.putSymbol("bsf", bsfInfo);
}
String execString = bsfInfo.objName + ".exec(\"" + lang + "\", ";
execString += "request.getRequestURI(), " + lineNo + ", " + columnNo;
execString += "," + StringUtils.lineSeparator;
execString += StringUtils.getSafeString(script.toString()) + ")";
ObjInfo oldRet = cb.getFinalServiceMethodStatement();
if (oldRet != null && oldRet.isExecutable()) {
cb.addServiceMethodStatement(oldRet.objName + ";");
}
cb.setFinalServiceMethodStatement(new ObjInfo(void.class, execString));
cb.addServiceMethodException("com.volmit.iris.util.bsf.BSFException");
}
public void declareBean(BSFDeclaredBean bean) throws BSFException {
throw new BSFException(BSFException.REASON_UNSUPPORTED_FEATURE,
"language " + lang +
" does not support declareBean(...).");
}
/**
* Default impl of execute - calls eval and ignores the result.
*/
public void exec(String source, int lineNo, int columnNo, Object script)
throws BSFException {
eval(source, lineNo, columnNo, script);
}
/**
* Default impl of interactive execution - calls eval and ignores the result.
*/
public void iexec(String source, int lineNo, int columnNo, Object script)
throws BSFException {
eval(source, lineNo, columnNo, script);
}
/**
* initialize the engine; called right after construction by
* the manager. Declared beans are simply kept in a vector and
* that's it. Subclasses must do whatever they want with it.
*/
public void initialize(BSFManager mgr, String lang, Vector declaredBeans)
throws BSFException {
this.mgr = mgr;
this.lang = lang;
this.declaredBeans = declaredBeans;
// initialize my properties from those of the manager. It'll send
// propagate change events to me
this.classPath = mgr.getClassPath();
this.tempDir = mgr.getTempDir();
this.classLoader = mgr.getClassLoader();
}
/**
* Receive property change events from the manager and update my fields
* as needed.
*
* @param e PropertyChange event with the change data
*/
public void propertyChange(PropertyChangeEvent e) {
String name = e.getPropertyName();
Object value = e.getNewValue();
if (name.equals("classPath")) {
classPath = (String) value;
}
else if (name.equals("tempDir")) {
tempDir = (String) value;
}
else if (name.equals("classLoader")) {
classLoader = (ClassLoader) value;
}
}
public void terminate() {
mgr = null;
declaredBeans = null;
classLoader = null;
}
public void undeclareBean(BSFDeclaredBean bean) throws BSFException {
throw new BSFException(BSFException.REASON_UNSUPPORTED_FEATURE,
"language " + lang +
" does not support undeclareBean(...).");
}
}

View File

@ -0,0 +1,92 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import com.volmit.iris.util.bsf.BSFEngine;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.event.EventProcessor;
/**
* This is used to support binding scripts to be run when an event
* occurs.
*
* @author Sanjiva Weerawarana
*/
public class BSFEventProcessor implements EventProcessor {
BSFEngine engine;
BSFManager manager;
String filter;
String source;
int lineNo;
int columnNo;
Object script;
/**
* Package-protected constructor makes this class unavailable for
* public use.
*/
BSFEventProcessor (BSFEngine engine, BSFManager manager, String filter,
String source, int lineNo, int columnNo, Object script)
throws BSFException {
this.engine = engine;
this.manager = manager;
this.filter = filter;
this.source = source;
this.lineNo = lineNo;
this.columnNo = columnNo;
this.script = script;
}
//////////////////////////////////////////////////////////////////////////
//
// event is delegated to me by the adapters using this. inFilter is
// in general the name of the method via which the event was received
// at the adapter. For prop/veto change events, inFilter is the name
// of the property. In any case, in the event processor, I only forward
// those events if for which the filters match (if one is specified).
public void processEvent (String inFilter, Object[] evtInfo) {
try {
processExceptionableEvent (inFilter, evtInfo);
} catch (RuntimeException re) {
// rethrow this .. I don't want to intercept run-time stuff
// that can in fact occur legit
throw re;
} catch (Exception e) {
// should not occur
System.err.println ("BSFError: non-exceptionable event delivery " +
"threw exception (that's not nice): " + e);
e.printStackTrace ();
}
}
//////////////////////////////////////////////////////////////////////////
//
// same as above, but used when the method event method may generate
// an exception which must go all the way back to the source (as in
// the vetoableChange case)
public void processExceptionableEvent (String inFilter, Object[] evtInfo) throws Exception
{
if ((filter != null) && !filter.equals (inFilter)) {
// ignore this event
return;
}
// run the script
engine.exec (source, lineNo, columnNo, script);
}
}

View File

@ -0,0 +1,164 @@
/*
* This software consists of voluntary contributions made by many individuals
* on behalf of the Apache Software Foundation and was originally created by
* Sanjiva Weerawarana and others at International Business Machines
* Corporation. For more information on the Apache Software Foundation,
* please see <http://www.apache.org/>.
*/
package com.volmit.iris.util.bsf.util;
import java.util.Vector;
import com.volmit.iris.util.bsf.BSFEngine;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
import com.volmit.iris.util.bsf.util.event.EventProcessor;
/*
* Copyright (C) 2001-2006 Rony G. Flatscher
*
* Licensed 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
*
* <a
* href="http://www.apache.org/licenses/LICENSE-2.0">http://www.apache.org/licenses/LICENSE-2.0</a>
*
* 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.
*
*/
/**
*
* This is used to support binding scripts to be run when an event occurs,
* forwarding the arguments supplied to the event listener. It is an adapted
* version of com.volmit.iris.util.bsf.util.BSFEventProcessor.
*
* @author Rony G. Flatscher, but most of the code copied from
* com.volmit.iris.util.bsf.util.BSFEventProcessor by Sanjiva Weerawarana
*/
public class BSFEventProcessorReturningEventInfos implements EventProcessor {
BSFEngine engine;
BSFManager manager;
String filter;
String source;
int lineNo;
int columnNo;
Object script;
Object dataFromScriptingEngine; // ---rgf, 2006-02-24: data coming from the
// script engine, could be
// e.g. an object reference to forward event with received arguments to
/**
* Package-protected constructor makes this class unavailable for public
* use.
*
* @param dataFromScriptingEngine
* this contains any object supplied by the scripting engine and
* gets sent back with the supplied script. This could be used
* e.g. for indicating which scripting engine object should be
* ultimately informed of the event occurrence.
*/
BSFEventProcessorReturningEventInfos(BSFEngine engine, BSFManager manager,
String filter, String source, int lineNo, int columnNo,
Object script, Object dataFromScriptingEngine) throws BSFException {
this.engine = engine;
this.manager = manager;
this.filter = filter;
this.source = source;
this.lineNo = lineNo;
this.columnNo = columnNo;
this.script = script;
this.dataFromScriptingEngine = dataFromScriptingEngine;
}
// ////////////////////////////////////////////////////////////////////////
//
// event is delegated to me by the adapters using this. inFilter is
// in general the name of the method via which the event was received
// at the adapter. For prop/veto change events, inFilter is the name
// of the property. In any case, in the event processor, I only forward
// those events if for which the filters match (if one is specified).
public void processEvent(String inFilter, Object[] evtInfo) {
try {
processExceptionableEvent(inFilter, evtInfo);
} catch (RuntimeException re) {
// rethrow this .. I don't want to intercept run-time stuff
// that can in fact occur legit
throw re;
} catch (Exception e) {
// should not occur
System.err.println("BSFError: non-exceptionable event delivery "
+ "threw exception (that's not nice): " + e);
e.printStackTrace();
}
}
// ////////////////////////////////////////////////////////////////////////
//
// same as above, but used when the method event method may generate
// an exception which must go all the way back to the source (as in
// the vetoableChange case)
public void processExceptionableEvent(String inFilter, Object[] evtInfo)
throws Exception {
// System.err.println(this+": inFilter=["+inFilter+"],
// filter=["+filter+"]");
if ((filter != null) && !filter.equals(inFilter)) {
// ignore this event
return;
}
// run the script
// engine.exec (source, lineNo, columnNo, script);
// create the parameter vectors for engine.apply()
Vector paramNames = new Vector(), paramValues = new Vector();
// parameter # 1
// supply the parameters as an array object as sent to the event object
// listener
// (usually the first entry is the sent event object)
paramNames.add("eventParameters");
paramValues.add(evtInfo);
// parameter # 2
// supply the data object received from the scripting engine to be sent
// with the event
paramNames.add("dataFromScriptingEngine");
paramValues.add(this.dataFromScriptingEngine); // can be null as well
// parameter # 3
// event filter in place
paramNames.add("inFilter");
paramValues.add(inFilter); // event name that has occurred
// parameter # 4
// event filter in place
paramNames.add("eventFilter");
paramValues.add(this.filter); // can be null as well
// parameter # 5
// BSF manager instance (e.g. allows access to its registry)
paramNames.add("BSFManager");
paramValues.add(this.manager);
engine.apply(source, lineNo, columnNo, this.script, paramNames,
paramValues);
}
}

View File

@ -0,0 +1,54 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import com.volmit.iris.util.bsf.BSFEngine;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
/**
* This is a utility that engine implementors may use as the Java
* object they expose in the scripting language as "bsf". This has
* essentially a subset of the methods in BSFManager plus some
* stuff from the utils. Currently used by Javascript (Rhino) & BML.
*
* @author Sanjiva Weerawarana
*/
public class BSFFunctions {
BSFManager mgr;
BSFEngine engine;
public BSFFunctions (BSFManager mgr, BSFEngine engine) {
this.mgr = mgr;
this.engine = engine;
}
public void addEventListener (Object src, String eventSetName,
String filter, Object script)
throws BSFException {
EngineUtils.addEventListener (src, eventSetName, filter, engine,
mgr, "<event-binding>", 0, 0, script);
}
public Object lookupBean (String name) {
return mgr.lookupBean (name);
}
public void registerBean (String name, Object bean) {
mgr.registerBean (name, bean);
}
public void unregisterBean (String name) {
mgr.unregisterBean (name);
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
/**
* A <em>Bean</em> is the class used to represent a bean: it holds a
* type and a value. This is needed because otherwise we can't represent
* the types of null-valued beans (or primitives) correctly. This was
* originally in the BML player.
*
* @author Sanjiva Weerawarana
*/
public class Bean {
// type of this bean
public Class type;
// its current value (mebbe null)
public Object value;
public Bean (Class type, Object value) {
this.type = type;
this.value = value;
}
}

View File

@ -0,0 +1,479 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.util.Hashtable;
import java.util.Stack;
import java.util.Vector;
import com.volmit.iris.util.bsf.util.cf.CodeFormatter;
/**
* A <code>CodeBuffer</code> object is used as a code repository for generated Java code.
* It provides buffers which correspond to the various sections of a Java class.
*
* @author Matthew J. Duftler
*/
public class CodeBuffer
{
private StringWriter fieldDeclSW = new StringWriter(),
methodDeclSW = new StringWriter(),
initializerSW = new StringWriter(),
constructorSW = new StringWriter(),
serviceMethodSW = new StringWriter();
private PrintWriter fieldDeclPW = new PrintWriter(fieldDeclSW),
methodDeclPW = new PrintWriter(methodDeclSW),
initializerPW = new PrintWriter(initializerSW),
constructorPW = new PrintWriter(constructorSW),
serviceMethodPW = new PrintWriter(serviceMethodSW);
private Stack symbolTableStack = new Stack();
private Hashtable symbolTable = new Hashtable(),
usedSymbolIndices = new Hashtable();
private ObjInfo finalStatementInfo;
private CodeBuffer parent;
{
symbolTableStack.push(symbolTable);
}
// New stuff...
private Vector imports = new Vector(),
constructorArguments = new Vector(),
constructorExceptions = new Vector(),
serviceMethodExceptions = new Vector(),
implementsVector = new Vector();
private String packageName = null,
className = "Test",
serviceMethodName = "exec",
extendsName = null;
private Class serviceMethodReturnType = void.class;
public CodeBuffer()
{
}
public CodeBuffer(CodeBuffer parent)
{
this.parent = parent;
}
public void addConstructorArgument(ObjInfo arg)
{
constructorArguments.addElement(arg);
}
public void addConstructorException(String exceptionName)
{
if (!constructorExceptions.contains(exceptionName))
{
constructorExceptions.addElement(exceptionName);
}
}
public void addConstructorStatement(String statement)
{
constructorPW.println(statement);
}
public void addFieldDeclaration(String statement)
{
fieldDeclPW.println(statement);
}
public void addImplements(String importName)
{
if (!implementsVector.contains(importName))
{
implementsVector.addElement(importName);
}
}
public void addImport(String importName)
{
if (!imports.contains(importName))
{
imports.addElement(importName);
}
}
public void addInitializerStatement(String statement)
{
initializerPW.println(statement);
}
public void addMethodDeclaration(String statement)
{
methodDeclPW.println(statement);
}
public void addServiceMethodException(String exceptionName)
{
if (!serviceMethodExceptions.contains(exceptionName))
{
serviceMethodExceptions.addElement(exceptionName);
}
}
public void addServiceMethodStatement(String statement)
{
serviceMethodPW.println(statement);
}
// Used internally by merge(...).
private void appendIfNecessary(PrintWriter pw, StringBuffer buf)
{
if (buf.length() > 0)
{
pw.print(buf.toString());
}
}
public String buildNewSymbol(String prefix)
{
Integer nextNum = getSymbolIndex(prefix);
if (nextNum == null)
{
nextNum = new Integer(0);
}
int iNextNum = nextNum.intValue();
String symbol = prefix + "_" + iNextNum;
while (getSymbol(symbol) != null)
{
iNextNum++;
symbol = prefix + "_" + iNextNum;
}
putSymbolIndex(prefix, new Integer(iNextNum + 1));
return symbol;
}
public void clearSymbolTable()
{
symbolTable = new Hashtable();
symbolTableStack = new Stack();
symbolTableStack.push(symbolTable);
usedSymbolIndices = new Hashtable();
}
public String getClassName()
{
return className;
}
public Vector getConstructorArguments()
{
return constructorArguments;
}
public StringBuffer getConstructorBuffer()
{
constructorPW.flush();
return constructorSW.getBuffer();
}
public Vector getConstructorExceptions()
{
return constructorExceptions;
}
public String getExtends()
{
return extendsName;
}
public StringBuffer getFieldBuffer()
{
fieldDeclPW.flush();
return fieldDeclSW.getBuffer();
}
public ObjInfo getFinalServiceMethodStatement()
{
return finalStatementInfo;
}
public Vector getImplements()
{
return implementsVector;
}
public Vector getImports()
{
return imports;
}
public StringBuffer getInitializerBuffer()
{
initializerPW.flush();
return initializerSW.getBuffer();
}
public StringBuffer getMethodBuffer()
{
methodDeclPW.flush();
return methodDeclSW.getBuffer();
}
public String getPackageName()
{
return packageName;
}
public StringBuffer getServiceMethodBuffer()
{
serviceMethodPW.flush();
return serviceMethodSW.getBuffer();
}
public Vector getServiceMethodExceptions()
{
return serviceMethodExceptions;
}
public String getServiceMethodName()
{
return serviceMethodName;
}
public Class getServiceMethodReturnType()
{
if (finalStatementInfo != null)
{
return finalStatementInfo.objClass;
}
else if (serviceMethodReturnType != null)
{
return serviceMethodReturnType;
}
else
{
return void.class;
}
}
public ObjInfo getSymbol(String symbol)
{
ObjInfo ret = (ObjInfo)symbolTable.get(symbol);
if (ret == null && parent != null)
ret = parent.getSymbol(symbol);
return ret;
}
Integer getSymbolIndex(String prefix)
{
if (parent != null)
{
return parent.getSymbolIndex(prefix);
}
else
{
return (Integer)usedSymbolIndices.get(prefix);
}
}
public Hashtable getSymbolTable()
{
return symbolTable;
}
public void merge(CodeBuffer otherCB)
{
Vector otherImports = otherCB.getImports();
for (int i = 0; i < otherImports.size(); i++)
{
addImport((String)otherImports.elementAt(i));
}
appendIfNecessary(fieldDeclPW, otherCB.getFieldBuffer());
appendIfNecessary(methodDeclPW, otherCB.getMethodBuffer());
appendIfNecessary(initializerPW, otherCB.getInitializerBuffer());
appendIfNecessary(constructorPW, otherCB.getConstructorBuffer());
appendIfNecessary(serviceMethodPW, otherCB.getServiceMethodBuffer());
ObjInfo oldRet = getFinalServiceMethodStatement();
if (oldRet != null && oldRet.isExecutable())
{
addServiceMethodStatement(oldRet.objName + ";");
}
setFinalServiceMethodStatement(otherCB.getFinalServiceMethodStatement());
}
public void popSymbolTable()
{
symbolTableStack.pop();
symbolTable = (Hashtable)symbolTableStack.peek();
}
public void print(PrintWriter out, boolean formatOutput)
{
if (formatOutput)
{
new CodeFormatter().formatCode(new StringReader(toString()), out);
}
else
{
out.print(toString());
}
out.flush();
}
public void pushSymbolTable()
{
symbolTable = (Hashtable)symbolTableStack.push(new ScriptSymbolTable(symbolTable));
}
public void putSymbol(String symbol, ObjInfo obj)
{
symbolTable.put(symbol, obj);
}
void putSymbolIndex(String prefix, Integer index)
{
if (parent != null)
{
parent.putSymbolIndex(prefix, index);
}
else
{
usedSymbolIndices.put(prefix, index);
}
}
public void setClassName(String className)
{
this.className = className;
}
public void setExtends(String extendsName)
{
this.extendsName = extendsName;
}
public void setFinalServiceMethodStatement(ObjInfo finalStatementInfo)
{
this.finalStatementInfo = finalStatementInfo;
}
public void setPackageName(String packageName)
{
this.packageName = packageName;
}
public void setServiceMethodName(String serviceMethodName)
{
this.serviceMethodName = serviceMethodName;
}
public void setServiceMethodReturnType(Class serviceMethodReturnType)
{
this.serviceMethodReturnType = serviceMethodReturnType;
}
public void setSymbolTable(Hashtable symbolTable)
{
this.symbolTable = symbolTable;
}
public boolean symbolTableIsStacked()
{
return (symbolTable instanceof ScriptSymbolTable);
}
public String toString()
{
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
ObjInfo ret = finalStatementInfo;
if (packageName != null && !packageName.equals(""))
{
pw.println("package " + packageName + ";");
pw.println();
}
if (imports.size() > 0)
{
for (int i = 0; i < imports.size(); i++)
{
pw.println("import " + imports.elementAt(i) + ";");
}
pw.println();
}
pw.println("public class " + className +
(extendsName != null && !extendsName.equals("")
? " extends " + extendsName
: "") +
(implementsVector.size() > 0
? " implements " +
StringUtils.getCommaListFromVector(implementsVector)
: "")
);
pw.println("{");
pw.print(getFieldBuffer().toString());
StringBuffer buf = getInitializerBuffer();
if (buf.length() > 0)
{
pw.println();
pw.println("{");
pw.print(buf.toString());
pw.println("}");
}
buf = getConstructorBuffer();
if (buf.length() > 0)
{
pw.println();
pw.println("public " + className + "(" +
(constructorArguments.size() > 0
? StringUtils.getCommaListFromVector(constructorArguments)
: ""
) + ")" +
(constructorExceptions.size() > 0
? " throws " +
StringUtils.getCommaListFromVector(constructorExceptions)
: ""
)
);
pw.println("{");
pw.print(buf.toString());
pw.println("}");
}
buf = getServiceMethodBuffer();
if (buf.length() > 0 || ret != null)
{
pw.println();
pw.println("public " +
StringUtils.getClassName(getServiceMethodReturnType()) + " " +
serviceMethodName + "()" +
(serviceMethodExceptions.size() > 0
? " throws " +
StringUtils.getCommaListFromVector(serviceMethodExceptions)
: ""
)
);
pw.println("{");
pw.print(buf.toString());
if (ret != null)
{
if (ret.isValueReturning())
{
pw.println();
pw.println("return " + ret.objName + ";");
}
else if (ret.isExecutable())
{
pw.println(ret.objName + ";");
}
}
pw.println("}");
}
pw.print(getMethodBuffer().toString());
pw.println("}");
pw.flush();
return sw.toString();
}
}

View File

@ -0,0 +1,379 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import com.volmit.iris.util.bsf.BSFEngine;
import com.volmit.iris.util.bsf.BSFException;
import com.volmit.iris.util.bsf.BSFManager;
/**
* This class contains utilities that language integrators can use
* when implementing the BSFEngine interface.
*
* @author Sanjiva Weerawarana
* @author Sam Ruby
* @author Rony G. Flatscher (added addEventListenerReturningEventInfos)
*/
public class EngineUtils {
// the BSF class loader that knows how to load from the a specific
// temp directory
static BSFClassLoader bsfCL;
// ---rgf, 2003-02-13, determine whether changing accessibility of Methods is possible
static boolean bMethodHasSetAccessible=false;
static {
Class mc=Method.class; // get the "Method" class object
Class arg[]={boolean.class}; // define an array with the primitive "boolean" pseudo class object
try {
mc.getMethod("setAccessible", arg ); // is this method available?
bMethodHasSetAccessible=true; // no exception, hence method exists
}
catch (Exception e)
{
bMethodHasSetAccessible=false;// exception occurred, hence method does not exist
}
}
/**
* Add a script as a listener to some event coming out of an object. The
* first two args identify the src of the event and the event set
* and the rest identify the script which should be run when the event
* fires.
*
* @param bean event source
* @param eventSetName name of event set from event src to bind to
* @param filter filter for events
* @param engine BSFEngine which can run this script
* @param manager BSFManager of the above engine
* @param source (context info) the source of this expression
* (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param script the script to execute when the event occurs
*
* @exception BSFException if anything goes wrong while running the script
*/
public static void addEventListener (Object bean, String eventSetName,
String filter, BSFEngine engine,
BSFManager manager, String source,
int lineNo, int columnNo,
Object script) throws BSFException {
BSFEventProcessor ep = new BSFEventProcessor (engine, manager, filter,
source, lineNo, columnNo,
script);
try {
ReflectionUtils.addEventListener (bean, eventSetName, ep);
} catch (Exception e) {
e.printStackTrace ();
throw new BSFException (BSFException.REASON_OTHER_ERROR,
"ouch while adding event listener: "
+ e, e);
}
}
/**
* Add a script as a listener to some event coming out of an object. The
* first two args identify the src of the event and the event set
* and the rest identify the script which should be run when the event
* fires. The processing will use the engine's apply() method.
*
* @param bean event source
* @param eventSetName name of event set from event src to bind to
* @param filter filter for events
* @param engine BSFEngine which can run this script
* @param manager BSFManager of the above engine
* @param source (context info) the source of this expression (e.g., filename)
* @param lineNo (context info) the line number in source for expr
* @param columnNo (context info) the column number in source for expr
* @param script the script to execute when the event occurs
* @param dataFromScriptingEngine
* this contains any object supplied by the scripting engine and gets sent
* back with the supplied script, if the event occurs.
* This could be used e.g. for indicating to the scripting engine which
* scripting engine object/routine/function/procedure
* should be ultimately informed of the event occurrence.
*
* @exception BSFException if anything goes wrong while running the script
*/
public static void addEventListenerReturningEventInfos ( Object bean,
String eventSetName,
String filter,
BSFEngine engine,
BSFManager manager,
String source,
int lineNo,
int columnNo,
Object script,
Object dataFromScriptingEngine
) throws BSFException
{
BSFEventProcessorReturningEventInfos ep =
new BSFEventProcessorReturningEventInfos (engine,
manager,
filter,
source,
lineNo,
columnNo,
script,
dataFromScriptingEngine
);
try {
ReflectionUtils.addEventListener (bean, eventSetName, ep);
} catch (Exception e) {
e.printStackTrace ();
throw new BSFException (BSFException.REASON_OTHER_ERROR,
"ouch while adding event listener: "
+ e, e);
}
}
/**
* Finds and invokes a method with the given signature on the given
* bean. The signature of the method that's invoked is first taken
* as the types of the args, but if that fails, this tries to convert
* any primitive wrapper type args to their primitive counterparts
* to see whether a method exists that way. If it does, done.
*
* @param bean the object on which to invoke the method
* @param methodName name of the method
* @param args arguments to be given to the method
*
* @return the result of invoking the method, if any
*
* @exception BSFException if something goes wrong
*/
public static Object callBeanMethod (Object bean, String methodName,
Object[] args) throws BSFException {
Class[] argTypes = null;
// determine arg types. note that a null argtype
// matches any object type
if (args != null) {
argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = (args[i] == null) ? null : args[i].getClass ();
}
}
// we want to allow a static call to occur on an object, similar
// to what Java allows. So isStaticOnly is set to false.
boolean isStaticOnly = false;
Class beanClass = (bean instanceof Class) ? (Class)bean :
bean.getClass ();
// now try to call method with the right signature
try {
Method m;
try {
m = MethodUtils.getMethod (beanClass, methodName, argTypes,
isStaticOnly);
} catch (NoSuchMethodException e) {
// ok, so that didn't work - now try converting any primitive
// wrapper types to their primitive counterparts
try {
// if args is null the NullPointerException will get caught
// below and the right thing'll happen .. ugly but works
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Number)
{
if (args[i] instanceof Byte) argTypes[i] = byte.class;
else if (args[i] instanceof Integer) argTypes[i] = int.class;
else if (args[i] instanceof Long) argTypes[i] = long.class;
else if (args[i] instanceof Float) argTypes[i] = float.class;
else if (args[i] instanceof Double ) argTypes[i] = double.class;
else if (args[i] instanceof Short ) argTypes[i] = short.class;
}
else if (args[i] instanceof Boolean) argTypes[i] = boolean.class;
else if (args[i] instanceof Character) argTypes[i] = char.class;
}
m = MethodUtils.getMethod (beanClass, methodName, argTypes,
isStaticOnly);
} catch (Exception e2) {
// throw the original
throw e;
}
}
// call it, and return the result
try {
return m.invoke (bean, args);
}
catch (Exception e) // 2003-02-23, --rgf, maybe an IllegalAccessException?
{
if (e instanceof IllegalAccessException &&
bMethodHasSetAccessible &&
Modifier.isPublic(m.getModifiers()) ) // if a public method allow access to it
{
m.setAccessible(true); // allow unconditional access to method
return m.invoke (bean, args);
}
// re-throw the exception
throw e;
}
} catch (Exception e) {
// something went wrong while invoking method
Throwable t = (e instanceof InvocationTargetException) ?
((InvocationTargetException)e).getTargetException () :
null;
throw new BSFException (BSFException.REASON_OTHER_ERROR,
"method invocation failed: " + e +
((t==null) ? "" :
(" target exception: " + t)), t);
}
}
/**
* Creates a new bean. The signature of the constructor that's invoked
* is first taken as the types of the args, but if that fails, this tries
* to convert any primitive wrapper type args to their primitive
* counterparts to see whether a method exists that way. If it does, done.
*
* @param className fully qualified name of class to instantiate
* @param args array of constructor args (or null if none)
*
* @return the created bean
*
* @exception BSFException if something goes wrong (@see
* org.apache.cs.util.MethodUtils for the real
* exceptions that can occur).
*/
public static Object createBean (String className, Object args[])
throws BSFException {
Bean obj;
Class[] argTypes = null;
if (args != null) {
argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = (args[i] != null) ? args[i].getClass () : null;
}
}
try {
try {
obj = ReflectionUtils.createBean (null, className,
argTypes, args);
return obj.value;
} catch (NoSuchMethodException me) {
// ok, so that didn't work - now try converting any primitive
// wrapper types to their primitive counterparts
try {
// if args is null the NullPointerException will get caught
// below and the right thing'll happen .. ugly but works
for (int i = 0; i < args.length; i++) {
if (args[i] instanceof Number)
argTypes[i] = byte.class;
else if (args[i] instanceof Boolean)
argTypes[i] = boolean.class;
else if (args[i] instanceof Character)
argTypes[i] = char.class;
}
obj = ReflectionUtils.createBean (null, className,
argTypes, args);
return obj.value;
} catch (Exception e) {
// throw the previous exception
throw me;
}
}
} catch (Exception e) {
throw new BSFException (BSFException.REASON_OTHER_ERROR,
e.getMessage (), e);
}
}
/**
* Given a class return the type signature string fragment for it.
* That is, return "I" for int, "J" for long, ... etc..
*
* @param cl class object for whom the signature fragment is needed.
*
* @return the string representing the type signature
*/
public static String getTypeSignatureString (Class cl) {
if (cl.isPrimitive ()) {
if (cl == boolean.class)
return "Z";
else if (cl == byte.class)
return "B";
else if (cl == char.class)
return "C";
else if (cl == short.class)
return "S";
else if (cl == int.class)
return "I";
else if (cl == long.class)
return "J";
else if (cl == float.class)
return "F";
else if (cl == double.class)
return "D";
else
return "V";
} else {
StringBuffer sb = new StringBuffer ("L");
sb.append (cl.getName ());
sb.append (";");
return sb.toString().replace ('.', '/');
}
}
/**
* Load a class using the class loader of given manager. If that fails
* try using a class loader that loads from the tempdir of the manager.
*
* @param mgr BSFManager who's classLoader and tempDir props are
* consulted
* @param name name of the class to load
*
* @return the loaded class
*
* @exception BSFException if something goes wrong.
*/
public static Class loadClass (BSFManager mgr, String name)
throws BSFException {
ClassLoader classLoader = mgr.getClassLoader ();
try {
return (classLoader == null) ?
// Class.forName (name)
Thread.currentThread().getContextClassLoader().loadClass (name)
: classLoader.loadClass (name);
} catch (ClassNotFoundException e) {
// try to load it from the temp dir using my own class loader
try {
if (bsfCL == null)
bsfCL = new BSFClassLoader ();
bsfCL.setTempDir (mgr.getTempDir ());
return bsfCL.loadClass (name);
} catch (ClassNotFoundException e2) {
throw new BSFException (BSFException.REASON_OTHER_ERROR,
"unable to load class '" + name + "':" + e, e);
}
}
}
}

View File

@ -0,0 +1,51 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.StringWriter;
/**
* This file is a collection of input/output utilities.
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
*/
public class IOUtils {
// debug flag - generates debug stuff if true
static boolean debug = false;
//////////////////////////////////////////////////////////////////////////
public static String getStringFromReader (Reader reader) throws IOException {
BufferedReader bufIn = new BufferedReader(reader);
StringWriter swOut = new StringWriter();
PrintWriter pwOut = new PrintWriter(swOut);
String tempLine;
while ((tempLine = bufIn.readLine()) != null) {
pwOut.println(tempLine);
}
pwOut.flush();
return swOut.toString();
}
}

View File

@ -0,0 +1,85 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Writer;
/**
* An <code>IndentWriter</code> object behaves the same as a
* <code>PrintWriter</code> object, with the additional capability
* of being able to print strings that are prepended with a specified
* amount of spaces.
*
* @author Matthew J. Duftler
*/
public class IndentWriter extends PrintWriter
{
/**
* Forwards its arguments to the <code>PrintWriter</code> constructor
* with the same signature.
*/
public IndentWriter(OutputStream out)
{
super(out);
}
/**
* Forwards its arguments to the <code>PrintWriter</code> constructor
* with the same signature.
*/
public IndentWriter(OutputStream out, boolean autoFlush)
{
super(out, autoFlush);
}
/**
* Forwards its arguments to the <code>PrintWriter</code> constructor
* with the same signature.
*/
public IndentWriter(Writer out)
{
super(out);
}
/**
* Forwards its arguments to the <code>PrintWriter</code> constructor
* with the same signature.
*/
public IndentWriter(Writer out, boolean autoFlush)
{
super(out, autoFlush);
}
/**
* Print the text (indented the specified amount) without inserting a linefeed.
*
* @param numberOfSpaces the number of spaces to indent the text.
* @param text the text to print.
*/
public void print(int numberOfSpaces, String text)
{
super.print(StringUtils.getChars(numberOfSpaces, ' ') + text);
}
/**
* Print the text (indented the specified amount) and insert a linefeed.
*
* @param numberOfSpaces the number of spaces to indent the text.
* @param text the text to print.
*/
public void println(int numberOfSpaces, String text)
{
super.println(StringUtils.getChars(numberOfSpaces, ' ') + text);
}
}

View File

@ -0,0 +1,228 @@
/*
* Copyright 2003,2004 The Apache Software Foundation.
*
* Licensed 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.
*/
#include <string.h>
#include <jni.h>
#include "JNIUtils.h"
/*****
*
* NOTE: Whereever I think an exception may occur, I need to check
* whether it did and recover appropriately .. otherwise the behavior
* of JNI is undefined!
*
*****/
/* throw a BSFException with the given code and message. */
void bsf_exception (JNIEnv *jenv, int code, char *msg) {
jclass bsfexceptclass =
(*jenv)->FindClass (jenv, "org/apache/bsf/BSFException");
(*jenv)->ThrowNew (jenv, bsfexceptclass, msg);
}
/* cvt a pointer to a Long object whose value is the pointer value */
jobject bsf_pointer2longobj (JNIEnv *jenv, void *ptr) {
return bsf_makeLong (jenv, (long) ptr);
}
/* cvt a Long object whose value is the pointer value to the pointer */
void *bsf_longobj2pointer (JNIEnv *jenv, jobject lobj) {
jclass longclass = (*jenv)->FindClass (jenv, "java/lang/Long");
jmethodID mi = (*jenv)->GetMethodID (jenv, longclass, "longValue", "()J");
void *ptr = (void *) (*jenv)->CallLongMethod (jenv, lobj, mi);
return ptr;
}
/* convert an object to a string obj */
jstring bsf_obj2jstring (JNIEnv *jenv, jobject obj) {
jclass objclass = (*jenv)->GetObjectClass (jenv, obj);
jmethodID tostr = (*jenv)->GetMethodID (jenv, objclass, "toString",
"()Ljava/lang/String;");
jstring strobj = (jstring) (*jenv)->CallObjectMethod (jenv, obj, tostr);
return strobj;
}
/* cvt an object to a c-string .. wastes memory, but useful for debug */
const char *bsf_obj2cstring (JNIEnv *jenv, jobject obj) {
return (*jenv)->GetStringUTFChars (jenv,
bsf_obj2jstring (jenv, obj),
0);
}
/* call the named method with the given args on the given bean */
jobject bsf_createbean (JNIEnv *jenv, char *classname, jobjectArray args) {
jclass cl;
jmethodID mid;
jobject result;
/* find the BSFUtils.createBean method ID if needed */
cl = (*jenv)->FindClass (jenv, "org/apache/bsf/util/EngineUtils");
mid = (*jenv)->GetStaticMethodID (jenv, cl, "createBean",
"(Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;");
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
return 0;
}
result = (*jenv)->CallStaticObjectMethod (jenv, cl, mid,
(*jenv)->NewStringUTF (jenv,
classname),
args);
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
/* I should really throw a BSF exception here and the caller should
check whether an exception was thrown and in that case return.
later. */
return 0;
} else {
return result;
}
}
/* call the named method with the given args on the given bean */
jobject bsf_callmethod (JNIEnv *jenv, jobject target,
char *methodname, jobjectArray args) {
jclass cl;
jmethodID mid;
jobject result;
/* find the BSFUtils.callBeanMethod method ID if needed */
cl = (*jenv)->FindClass (jenv, "org/apache/bsf/util/EngineUtils");
mid = (*jenv)->GetStaticMethodID (jenv, cl, "callBeanMethod",
"(Ljava/lang/Object;Ljava/lang/String;[Ljava/lang/Object;)Ljava/lang/Object;");
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
return 0;
}
result = (*jenv)->CallStaticObjectMethod (jenv, cl, mid, target,
(*jenv)->NewStringUTF (jenv,
methodname),
args);
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
/* I should really throw a BSF exception here and the caller should
check whether an exception was thrown and in that case return.
later. */
return 0;
} else {
return result;
}
}
/* return the named bean from the given mgr's bean registry */
jobject bsf_lookupbean (JNIEnv *jenv, jobject mgr, char *beanname) {
jmethodID lookupMethod;
jobject result;
jclass bsfmgrclass = (*jenv)->GetObjectClass (jenv, mgr);
lookupMethod =
(*jenv)->GetMethodID (jenv, bsfmgrclass, "lookupBean",
"(Ljava/lang/String;)Ljava/lang/Object;");
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
return 0;
}
result = (*jenv)->CallObjectMethod (jenv, mgr, lookupMethod,
(*jenv)->NewStringUTF (jenv, beanname));
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
/* I should really throw a BSF exception here and the caller should
check whether an exception was thrown and in that case return.
later. */
return 0;
} else {
return result;
}
}
/* return the type signature string component for the given type:
I for ints, J for long, ... */
char *bsf_getTypeSignatureString (JNIEnv *jenv, jclass objclass) {
jclass cl = 0;
jmethodID mid = 0;
jstring str;
cl = (*jenv)->FindClass (jenv, "org/apache/bsf/util/EngineUtils");
mid = (*jenv)->GetStaticMethodID (jenv, cl, "getTypeSignatureString",
"(Ljava/lang/Class;)Ljava/lang/String;");
if ((*jenv)->ExceptionOccurred (jenv)) {
(*jenv)->ExceptionDescribe (jenv);
(*jenv)->ExceptionClear (jenv);
return 0;
}
str = (jstring) (*jenv)->CallStaticObjectMethod (jenv, cl, mid, objclass);
return (char *) bsf_obj2cstring (jenv, str);
}
/* make objects from primitives */
jobject bsf_makeBoolean (JNIEnv *jenv, int val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Boolean");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(Z)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jboolean) val);
}
jobject bsf_makeByte (JNIEnv *jenv, int val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Byte");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(B)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jbyte) val);
}
jobject bsf_makeShort (JNIEnv *jenv, int val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Short");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(S)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jshort) val);
}
jobject bsf_makeInteger (JNIEnv *jenv, int val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Integer");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(I)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jint) val);
}
jobject bsf_makeLong (JNIEnv *jenv, long val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Long");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(J)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jlong) val);
}
jobject bsf_makeFloat (JNIEnv *jenv, float val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Float");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(F)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jfloat) val);
}
jobject bsf_makeDouble (JNIEnv *jenv, double val) {
jclass classobj = (*jenv)->FindClass (jenv, "java/lang/Double");
jmethodID constructor =
(*jenv)->GetMethodID (jenv, classobj, "<init>", "(D)V");
return (*jenv)->NewObject (jenv, classobj, constructor, (jdouble) val);
}

View File

@ -0,0 +1,62 @@
/*
* Copyright 2003,2004 The Apache Software Foundation.
*
* Licensed 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.
*/
#include <jni.h>
#if defined(__cplusplus)
extern "C" {
#endif
/* throw a BSFException with the given message */
extern void bsf_exception (JNIEnv *jenv, int code, char *msg);
/* cvt a pointer to a Long object whose value is the pointer value */
extern jobject bsf_pointer2longobj (JNIEnv *jenv, void *ptr);
/* cvt a Long object whose value is the pointer value to the pointer */
extern void *bsf_longobj2pointer (JNIEnv *jenv, jobject lobj);
/* convert an object to a string obj */
jstring bsf_obj2jstring (JNIEnv *jenv, jobject obj);
/* cvt an object to a c-string .. wastes memory, but useful for debug */
const char *bsf_obj2cstring (JNIEnv *jenv, jobject obj);
/* create an instance of the named class with the given args */
extern jobject bsf_createbean (JNIEnv *jenv, char *methodname,
jobjectArray args);
/* call the named method with the given args on the given bean */
extern jobject bsf_callmethod (JNIEnv *jenv, jobject target,
char *methodname, jobjectArray args);
/* return the named bean from the given mgr's bean registry */
extern jobject bsf_lookupbean (JNIEnv *jenv, jobject mgr, char *beanname);
/* return the type signature string component for the given type:
I for ints, J for long, ... */
extern char *bsf_getTypeSignatureString (JNIEnv *jenv, jclass objclass);
/* make objects from primitives */
extern jobject bsf_makeBoolean (JNIEnv *jenv, int val);
extern jobject bsf_makeByte (JNIEnv *jenv, int val);
extern jobject bsf_makeShort (JNIEnv *jenv, int val);
extern jobject bsf_makeInteger (JNIEnv *jenv, int val);
extern jobject bsf_makeLong (JNIEnv *jenv, long val);
extern jobject bsf_makeFloat (JNIEnv *jenv, float val);
extern jobject bsf_makeDouble (JNIEnv *jenv, double val);
#if defined(__cplusplus)
}
#endif

View File

@ -0,0 +1,55 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class JavaUtils {
// Temporarily copied from JavaEngine...
private static Log logger;
static {
logger = LogFactory.getLog((com.volmit.iris.util.bsf.util.JavaUtils.class)
.getName());
}
public static boolean JDKcompile(String fileName, String classPath) {
String option = (logger.isDebugEnabled()) ? "-g" : "-O";
String args[] = { "javac", option, "-classpath", classPath, fileName };
logger.debug("JavaEngine: Compiling " + fileName);
logger.debug("JavaEngine: Classpath is " + classPath);
try {
Process p = java.lang.Runtime.getRuntime().exec(args);
p.waitFor();
return (p.exitValue() != 0);
} catch (IOException e) {
logger.error("ERROR: IO exception during exec(javac).", e);
} catch (SecurityException e) {
logger.error("ERROR: Unable to create subprocess to exec(javac).",
e);
} catch (InterruptedException e) {
logger.error("ERROR: Wait for exec(javac) was interrupted.", e);
}
return false;
}
}

View File

@ -0,0 +1,517 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Enumeration;
import java.util.Vector;
/**
* This file is a collection of reflection utilities for dealing with
* methods and constructors.
*
* @author Sanjiva Weerawarana
* @author Joseph Kesselman
*/
public class MethodUtils {
/** Internal Class for getEntryPoint(). Implements 15.11.2.2 MORE
SPECIFIC rules.
Retains a list of methods (already known to match the
arguments). As each method is added, we check against past entries
to determine which if any is "more specific" -- defined as having
_all_ its arguments (not just a preponderance) be
method-convertable into those of another. If such a relationship
is found, the more-specific method is retained and the
less-specific method is discarded. At the end, if this has yielded
a single winner it is considered the Most Specific Method and
hence the one that should be invoked. Otherwise, a
NoSuchMethodException is thrown.
PERFORMANCE VERSUS ARCHITECTURE: Arguably, this should "have-a"
Vector. But the code is 6% smaller, and possibly faster, if we
code it as "is-a" Vector. Since it's an inner class, nobody's
likely to abuse the privilage.
Note: "Static" in the case of an inner class means "Does not
reference instance data in the outer class", and is required since
our caller is a static method. */
private static class MoreSpecific
extends Vector
{
/** Submit an entry-point to the list. May be discarded if a past
entry is more specific, or may cause others to be discarded it
if is more specific.
newEntry: Method or Constructor under consideration.
*/
void addItem (Object newEntry)
{
if(size()==0)
addElement(newEntry);
else
{
Class[] newargs=entryGetParameterTypes(newEntry);
boolean keep=true;
for (Enumeration e = elements();
keep & e.hasMoreElements() ;
)
{
Object oldEntry=e.nextElement();
// CAVEAT: Implicit references to enclosing class!
Class[] oldargs=entryGetParameterTypes(oldEntry);
if(areMethodConvertable(oldargs,newargs))
removeElement(oldEntry); // New more specific; discard old
else if(areMethodConvertable(newargs,oldargs))
keep=false; // Old more specific; discard new
// Else they're tied. Keep both and hope someone beats both.
}
if(keep)
addElement(newEntry);
}
}
/** Obtain the single Most Specific entry-point. If there is no clear
winner, or if the list is empty, throw NoSuchMethodException.
Arguments describe the call we were hoping to resolve. They are
used to throw a nice verbose exception if something goes wrong.
*/
Object getMostSpecific(Class targetClass,String methodName,
Class[] argTypes,boolean isStaticReference)
throws NoSuchMethodException
{
if(size()==1)
return firstElement();
if(size()>1)
{
StringBuffer buf=new StringBuffer();
Enumeration e=elements();
buf.append(e.nextElement());
while(e.hasMoreElements())
buf.append(" and ").append(e.nextElement());
throw new NoSuchMethodException (callToString(targetClass,
methodName,
argTypes,
isStaticReference)+
" is ambiguous. It matches "+
buf.toString());
}
return null;
}
}
/** Convenience method: Test an entire parameter-list/argument-list pair
for isMethodConvertable(), qv.
*/
static private boolean areMethodConvertable(Class[] parms,Class[] args)
{
if(parms.length!=args.length)
return false;
for(int i=0;i<parms.length;++i)
if(!isMethodConvertable(parms[i],args[i]))
return false;
return true;
}
/** Internal subroutine for getEntryPoint(): Format arguments as a
string describing the function being searched for. Used in
verbose exceptions. */
private static String callToString(Class targetClass,String methodName,
Class[] argTypes,boolean isStaticReference)
{
StringBuffer buf = new StringBuffer();
if(isStaticReference)
buf.append("static ");
buf.append(StringUtils.getClassName(targetClass));
if(methodName!=null)
buf.append(".").append(methodName);
buf.append("(");
if (argTypes != null && argTypes.length>0) {
if(false)
{
// ????? Sanjiva has an ArrayToString method. Using it would
// save a few bytes, at cost of giving up some reusability.
}
else
{
buf.append(StringUtils.getClassName(argTypes[0]));
for (int i = 1; i < argTypes.length; i++) {
buf.append(",").append(StringUtils.getClassName(argTypes[i]));
}
}
}
else
buf.append("[none]");
buf.append(")");
return buf.toString();
}
/** Utility function: obtain common data from either Method or
Constructor. (In lieu of an EntryPoint interface.) */
static int entryGetModifiers(Object entry)
{
return (entry instanceof Method)
? ((Method)entry).getModifiers()
: ((Constructor)entry).getModifiers();
}
// The common lookup code would be much easier if Method and
// Constructor shared an "EntryPoint" Interface. Unfortunately, even
// though their APIs are almost identical, they don't. These calls
// are a workaround... at the cost of additional runtime overhead
// and some extra bytecodes.
//
// (A JDK bug report has been submitted requesting that they add the
// Interface; it would be easy, harmless, and useful.)
/** Utility function: obtain common data from either Method or
Constructor. (In lieu of an EntryPoint interface.) */
static String entryGetName(Object entry)
{
return (entry instanceof Method)
? ((Method)entry).getName()
: ((Constructor)entry).getName();
}
/** Utility function: obtain common data from either Method or
Constructor. (In lieu of an EntryPoint interface.) */
static Class[] entryGetParameterTypes(Object entry)
{
return (entry instanceof Method)
? ((Method)entry).getParameterTypes()
: ((Constructor)entry).getParameterTypes();
}
/** Utility function: obtain common data from either Method or
Constructor. (In lieu of an EntryPoint interface.) */
static String entryToString(Object entry)
{
return (entry instanceof Method)
? ((Method)entry).toString()
: ((Constructor)entry).toString();
}
//////////////////////////////////////////////////////////////////////////
/** Class.getConstructor() finds only the entry point (if any)
_exactly_ matching the specified argument types. Our implmentation
can decide between several imperfect matches, using the same
search algorithm as the Java compiler.
Note that all constructors are static by definition, so
isStaticReference is true.
@exception NoSuchMethodException if constructor not found.
*/
static public Constructor getConstructor(Class targetClass, Class[] argTypes)
throws SecurityException, NoSuchMethodException
{
return (Constructor) getEntryPoint(targetClass,null,argTypes,true);
}
//////////////////////////////////////////////////////////////////////////
/**
* Search for entry point, per Java Language Spec 1.0
* as amended, verified by comparison against compiler behavior.
*
* @param targetClass Class object for the class to be queried.
* @param methodName Name of method to invoke, or null for constructor.
* Only Public methods will be accepted.
* @param argTypes Classes of intended arguments. Note that primitives
* must be specified via their TYPE equivalents,
* rather than as their wrapper classes -- Integer.TYPE
* rather than Integer. "null" may be passed in as an
* indication that you intend to invoke the method with
* a literal null argument and therefore can accept
* any object type in this position.
* @param isStaticReference If true, and if the target is a Class object,
* only static methods will be accepted as valid matches.
*
* @return a Method or Constructor of the appropriate signature
*
* @exception SecurityException if security violation
* @exception NoSuchMethodException if no such method
*/
static private Object getEntryPoint(Class targetClass,
String methodName,
Class[] argTypes,
boolean isStaticReference)
throws SecurityException, NoSuchMethodException
{
// 15.11.1: OBTAIN STARTING CLASS FOR SEARCH
Object m=null;
// 15.11.2 DETERMINE ARGUMENT SIGNATURE
// (Passed in as argTypes array.)
// Shortcut: If an exact match exists, return it.
try {
if(methodName!=null)
{
m=targetClass.getMethod (methodName, argTypes);
if(isStaticReference &&
!Modifier.isStatic(entryGetModifiers(m)) )
{
throw
new NoSuchMethodException (callToString (targetClass,
methodName,
argTypes,
isStaticReference)+
" resolved to instance " + m);
}
return m;
}
else
return targetClass.getConstructor (argTypes);
} catch (NoSuchMethodException e) {
// no-args has no alternatives!
if(argTypes==null || argTypes.length==0)
{
throw
new NoSuchMethodException (callToString (targetClass,
methodName,
argTypes,
isStaticReference)+
" not found.");
}
// Else fall through.
}
// Well, _that_ didn't work. Time to search for the Most Specific
// matching function. NOTE that conflicts are possible!
// 15.11.2.1 ACCESSIBLE: We apparently need to gather from two
// sources to be sure we have both instance and static methods.
Object[] methods;
if(methodName!=null)
{
methods=targetClass.getMethods();
}
else
{
methods=targetClass.getConstructors();
}
if(0==methods.length)
{
throw new NoSuchMethodException("No methods!");
}
MoreSpecific best=new MoreSpecific();
for(int i=0;i<methods.length;++i)
{
Object mi=methods[i];
if (
// 15.11.2.1 ACCESSIBLE: Method is public.
Modifier.isPublic(entryGetModifiers(mi))
&&
// 15.11.2.1 APPLICABLE: Right method name (or c'tor)
(methodName==null || entryGetName(mi).equals(methodName) )
&&
// 15.11.2.1 APPLICABLE: Parameters match arguments
areMethodConvertable(entryGetParameterTypes(mi),argTypes)
)
// 15.11.2.2 MORE SPECIFIC displace less specific.
best.addItem(mi);
}
// May throw NoSuchMethodException; we pass in info needed to
// create a useful exception
m=best.getMostSpecific(targetClass,methodName,argTypes,isStaticReference);
// 15.11.3 APPROPRIATE: Class invocation can call only static
// methods. Note that the defined order of evaluation permits a
// call to be resolved to an inappropriate method and then
// rejected, rather than finding the best of the appropriate
// methods.
//
// Constructors are never static, so we don't test them.
if(m==null)
{
throw new NoSuchMethodException (callToString(targetClass,
methodName,
argTypes,
isStaticReference)+
" -- no signature match");
}
if( methodName!=null &&
isStaticReference &&
!Modifier.isStatic(entryGetModifiers(m)) )
{
throw new NoSuchMethodException (callToString(targetClass,
methodName,
argTypes,
isStaticReference)+
" resolved to instance: "+m);
}
return m;
}
//////////////////////////////////////////////////////////////////////////
/* Class.getMethod() finds only the entry point (if any) _exactly_
matching the specified argument types. Our implmentation can
decide between several imperfect matches, using the same search
algorithm as the Java compiler.
This version more closely resembles Class.getMethod() -- we always
ask the Class for the method. It differs in testing for
appropriateness before returning the method; if the query is
being made via a static reference, only static methods will be
found and returned. */
static public Method getMethod(Class target,String methodName,
Class[] argTypes,boolean isStaticReference)
throws SecurityException, NoSuchMethodException
{
return (Method)getEntryPoint(target,methodName,argTypes,isStaticReference);
}
//////////////////////////////////////////////////////////////////////////
/**
* Class.getMethod() finds only the entry point (if any) _exactly_
* matching the specified argument types. Our implmentation can
* decide between several imperfect matches, using the same search
* algorithm as the Java compiler.
*
* This version emulates the compiler behavior by allowing lookup to
* be performed against either a class or an instance -- classname.foo()
* must be a static method call, instance.foo() can invoke either static
* or instance methods.
*
* @param target object on which call is to be made
* @param methodName name of method I'm lookin' for
* @param argTypes array of argument types of method
*
* @return the desired method
*
* @exception SecurityException if security violation
* @exception NoSuchMethodException if no such method
*/
static public Method getMethod(Object target,String methodName,
Class[] argTypes)
throws SecurityException, NoSuchMethodException
{
boolean staticRef=target instanceof Class;
return getMethod( staticRef ? (Class)target : target.getClass(),
methodName,argTypes,staticRef);
}
/** Determine whether a given type can accept assignments of another
type. Note that class.isAssignable() is _not_ a complete test!
(This method is not needed by getMethod() or getConstructor(), but
is provided as a convenience for other users.)
parm: The type given in the method's signature.
arg: The type we want to pass in.
Legal ASSIGNMENT CONVERSIONS (5.2) are METHOD CONVERSIONS (5.3)
plus implicit narrowing of int to byte, short or char. */
static private boolean isAssignmentConvertable(Class parm,Class arg)
{
return
(arg.equals(Integer.TYPE) &&
(parm.equals(Byte.TYPE) ||
parm.equals(Short.TYPE) ||
parm.equals(Character.TYPE)
)
) ||
isMethodConvertable(parm,arg);
}
/** Determine whether a given method parameter type can accept
arguments of another type.
parm: The type given in the method's signature.
arg: The type we want to pass in.
Legal METHOD CONVERSIONS (5.3) are Identity, Widening Primitive
Conversion, or Widening Reference Conversion. NOTE that this is a
subset of the legal ASSIGNMENT CONVERSIONS (5.2) -- in particular,
we can't implicitly narrow int to byte, short or char.
SPECIAL CASE: In order to permit invoking methods with literal
"null" values, setting the arg Class to null will be taken as a
request to match any Class type. POSSIBLE PROBLEM: This may match
a primitive type, which really should not accept a null value... but
I'm not sure how best to distinguish those, short of enumerating them
*/
static private boolean isMethodConvertable(Class parm, Class arg)
{
if (parm.equals(arg)) // If same class, short-circuit now!
return true;
// Accept any type EXCEPT primitives (which can't have null values).
if (arg == null)
{
return !parm.isPrimitive();
}
// Arrays are convertable if their elements are convertable
// ????? Does this have to be done before isAssignableFrom, or
// does it successfully handle arrays of primatives?
while(parm.isArray())
{
if(!arg.isArray())
return false; // Unequal array depth
else
{
parm=parm.getComponentType();
arg=arg.getComponentType();
}
}
if(arg.isArray())
return false; // Unequal array depth
// Despite its name, the 1.1.6 docs say that this function does
// NOT return true for all legal ASSIGNMENT CONVERSIONS
// (5.2):
// "Specifically, this method tests whether the type
// represented by the specified class can be converted
// to the type represented by this Class object via
// an identity conversion or via a widening reference
// conversion."
if(parm.isAssignableFrom(arg))
return true;
// That leaves us the Widening Primitives case. Four possibilities:
// void (can only convert to void), boolean (can only convert to boolean),
// numeric (which are sequenced) and char (which inserts itself into the
// numerics by promoting to int or larger)
if(parm.equals(Void.TYPE) || parm.equals(Boolean.TYPE) ||
arg.equals(Void.TYPE) || arg.equals(Boolean.TYPE))
return false;
Class[] primTypes={ Character.TYPE, Byte.TYPE, Short.TYPE, Integer.TYPE,
Long.TYPE, Float.TYPE, Double.TYPE };
int parmscore,argscore;
for(parmscore=0;parmscore<primTypes.length;++parmscore)
if (parm.equals(primTypes[parmscore]))
break;
if(parmscore>=primTypes.length)
return false; // Off the end
for(argscore=0;argscore<primTypes.length;++argscore)
if (arg.equals(primTypes[argscore]))
break;
if(argscore>=primTypes.length)
return false; // Off the end
// OK if ordered AND NOT char-to-smaller-than-int
return (argscore<parmscore && (argscore!=0 || parmscore>2) );
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
/**
* An <code>ObjInfo</code> object is used by a compiler to track the name and
* type of a bean.
*
* @author Matthew J. Duftler
*/
public class ObjInfo
{
static private String QUOTE_CHARS = "\'\"",
EXEC_CHARS = "(=";
public String objName;
public Class objClass;
public ObjInfo(Class objClass, String objName)
{
this.objClass = objClass;
this.objName = objName;
}
public boolean isExecutable()
{
char[] chars = objName.toCharArray();
char openingChar = ' ';
boolean inString = false,
inEscapeSequence = false;
for (int i = 0; i < chars.length; i++)
{
if (inEscapeSequence)
{
inEscapeSequence = false;
}
else if (QUOTE_CHARS.indexOf(chars[i]) != -1)
{
if (!inString)
{
openingChar = chars[i];
inString = true;
}
else
{
if (chars[i] == openingChar)
{
inString = false;
}
}
}
else if (EXEC_CHARS.indexOf(chars[i]) != -1)
{
if (!inString)
{
return true;
}
}
else if (inString && chars[i] == '\\')
{
inEscapeSequence = true;
}
}
return false;
}
public boolean isValueReturning()
{
return (objClass != void.class && objClass != Void.class);
}
public String toString()
{
return StringUtils.getClassName(objClass) + " " + objName;
}
}

View File

@ -0,0 +1,63 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.util.Hashtable;
/**
* The <em>ObjectRegistry</em> is used to do name-to-object reference lookups.
* If an <em>ObjectRegistry</em> is passed as a constructor argument, then this
* <em>ObjectRegistry</em> will be a cascading registry: when a lookup is
* invoked, it will first look in its own table for a name, and if it's not
* there, it will cascade to the parent <em>ObjectRegistry</em>.
* All registration is always local. [??]
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
*/
public class ObjectRegistry {
Hashtable reg = new Hashtable ();
ObjectRegistry parent = null;
public ObjectRegistry () {
}
public ObjectRegistry (ObjectRegistry parent) {
this.parent = parent;
}
// lookup an object: cascade up if needed
public Object lookup (String name) throws IllegalArgumentException {
Object obj = reg.get (name);
if (obj == null && parent != null) {
obj = parent.lookup (name);
}
if (obj == null) {
throw new IllegalArgumentException ("object '" + name + "' not in registry");
}
return obj;
}
// register an object
public void register (String name, Object obj) {
reg.put (name, obj);
}
// unregister an object (silent if unknown name)
public void unregister (String name) {
reg.remove (name);
}
}

View File

@ -0,0 +1,421 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.beans.BeanInfo;
import java.beans.Beans;
import java.beans.EventSetDescriptor;
import java.beans.FeatureDescriptor;
import java.beans.IndexedPropertyDescriptor;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import com.volmit.iris.util.bsf.util.event.EventAdapter;
import com.volmit.iris.util.bsf.util.event.EventAdapterRegistry;
import com.volmit.iris.util.bsf.util.event.EventProcessor;
import com.volmit.iris.util.bsf.util.type.TypeConvertor;
import com.volmit.iris.util.bsf.util.type.TypeConvertorRegistry;
/**
* This file is a collection of reflection utilities. There are utilities
* for creating beans, getting bean infos, setting/getting properties,
* and binding events.
*
* @author Sanjiva Weerawarana
* @author Joseph Kesselman
*/
public class ReflectionUtils {
//////////////////////////////////////////////////////////////////////////
/**
* Add an event processor as a listener to some event coming out of an
* object.
*
* @param source event source
* @param eventSetName name of event set from event src to bind to
* @param processor event processor the event should be delegated to
* when it occurs; either via processEvent or
* processExceptionableEvent.
*
* @exception IntrospectionException if unable to introspect
* @exception IllegalArgumentException if event set is unknown
* @exception IllegalAccessException if the event adapter class or
* initializer is not accessible.
* @exception InstantiationException if event adapter instantiation fails
* @exception InvocationTargetException if something goes wrong while
* running add event listener method
*/
public static void addEventListener (Object source, String eventSetName,
EventProcessor processor)
throws IntrospectionException, IllegalArgumentException,
IllegalAccessException, InstantiationException,
InvocationTargetException {
// find the event set descriptor for this event
BeanInfo bi = Introspector.getBeanInfo (source.getClass ());
EventSetDescriptor esd = (EventSetDescriptor)
findFeatureByName ("event", eventSetName, bi.getEventSetDescriptors ());
if (esd == null) // no events found, maybe a proxy from OpenOffice.org?
{
throw new IllegalArgumentException ("event set '" + eventSetName +
"' unknown for source type '" + source.getClass () + "'");
}
// get the class object for the event
Class listenerType=esd.getListenerType(); // get ListenerType class object from EventSetDescriptor
// find an event adapter class of the right type
Class adapterClass = EventAdapterRegistry.lookup (listenerType);
if (adapterClass == null) {
throw new IllegalArgumentException ("event adapter for listener type " +
"'" + listenerType + "' (eventset " +
"'" + eventSetName + "') unknown");
}
// create the event adapter and give it the event processor
EventAdapter adapter = (EventAdapter) adapterClass.newInstance ();
adapter.setEventProcessor (processor);
// bind the adapter to the source bean
Method addListenerMethod;
Object[] args;
if (eventSetName.equals ("propertyChange") ||
eventSetName.equals ("vetoableChange")) {
// In Java 1.2, beans may have direct listener adding methods
// for property and vetoable change events which take the
// property name as a filter to be applied at the event source.
// The filter property of the event processor should be used
// in this case to support the source-side filtering.
//
// ** TBD **: the following two lines need to change appropriately
addListenerMethod = esd.getAddListenerMethod ();
args = new Object[] {adapter};
}
else
{
addListenerMethod = esd.getAddListenerMethod ();
args = new Object[] {adapter};
}
addListenerMethod.invoke (source, args);
}
//////////////////////////////////////////////////////////////////////////
/**
* Create a bean using given class loader and using the appropriate
* constructor for the given args of the given arg types.
* @param cld the class loader to use. If null, Class.forName is used.
* @param className name of class to instantiate
* @param argTypes array of argument types
* @param args array of arguments
*
* @return the newly created bean
*
* @exception ClassNotFoundException if class is not loaded
* @exception NoSuchMethodException if constructor can't be found
* @exception InstantiationException if class can't be instantiated
* @exception IllegalAccessException if class is not accessible
* @exception IllegalArgumentException if argument problem
* @exception InvocationTargetException if constructor excepted
* @exception IOException if I/O error in beans.instantiate
*/
public static Bean createBean (ClassLoader cld, String className,
Class[] argTypes, Object[] args)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
IOException {
if (argTypes != null) {
// find the right constructor and use that to create bean
Class cl = (cld != null) ? cld.loadClass (className)
: Thread.currentThread().getContextClassLoader().loadClass (className); // rgf, 2006-01-05
// : Class.forName (className);
Constructor c = MethodUtils.getConstructor (cl, argTypes);
return new Bean (cl, c.newInstance (args));
} else {
// create the bean with no args constructor
Object obj = Beans.instantiate (cld, className);
return new Bean (obj.getClass (), obj);
}
}
//////////////////////////////////////////////////////////////////////////
/**
* Create a bean using given class loader and using the appropriate
* constructor for the given args. Figures out the arg types and
* calls above.
* @param cld the class loader to use. If null, Class.forName is used.
* @param className name of class to instantiate
* @param args array of arguments
*
* @return the newly created bean
*
* @exception ClassNotFoundException if class is not loaded
* @exception NoSuchMethodException if constructor can't be found
* @exception InstantiationException if class can't be instantiated
* @exception IllegalAccessException if class is not accessible
* @exception IllegalArgumentException if argument problem
* @exception InvocationTargetException if constructor excepted
* @exception IOException if I/O error in beans.instantiate
*/
public static Bean createBean (ClassLoader cld, String className,
Object[] args)
throws ClassNotFoundException, NoSuchMethodException,
InstantiationException, IllegalAccessException,
IllegalArgumentException, InvocationTargetException,
IOException {
Class[] argTypes = null;
if (args != null) {
argTypes = new Class[args.length];
for (int i = 0; i < args.length; i++) {
argTypes[i] = (args[i] != null) ? args[i].getClass () : null;
}
}
return createBean (cld, className, argTypes, args);
}
//////////////////////////////////////////////////////////////////////////
/**
* locate the item in the fds array whose name is as given. returns
* null if not found.
*/
private static
FeatureDescriptor findFeatureByName (String featureType, String name,
FeatureDescriptor[] fds) {
for (int i = 0; i < fds.length; i++) {
if (name.equals (fds[i].getName())) {
return fds[i];
}
}
return null;
}
public static Bean getField (Object target, String fieldName)
throws IllegalArgumentException, IllegalAccessException {
// This is to handle how we do static fields.
Class targetClass = (target instanceof Class)
? (Class) target
: target.getClass ();
try {
Field f = targetClass.getField (fieldName);
Class fieldType = f.getType ();
// Get the value and return it.
Object value = f.get (target);
return new Bean (fieldType, value);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException ("field '" + fieldName + "' is " +
"unknown for '" + target + "'");
}
}
//////////////////////////////////////////////////////////////////////////
/**
* Get a property of a bean.
*
* @param target the object whose prop is to be gotten
* @param propName name of the property to set
* @param index index to get (if property is indexed)
*
* @exception IntrospectionException if unable to introspect
* @exception IllegalArgumentException if problems with args: if the
* property is unknown, or if the property is given an index
* when its not, or if the property is not writeable, or if
* the given value cannot be assigned to the it (type mismatch).
* @exception IllegalAccessException if read method is not accessible
* @exception InvocationTargetException if read method excepts
*/
public static Bean getProperty (Object target, String propName,
Integer index)
throws IntrospectionException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
// find the property descriptor
BeanInfo bi = Introspector.getBeanInfo (target.getClass ());
PropertyDescriptor pd = (PropertyDescriptor)
findFeatureByName ("property", propName, bi.getPropertyDescriptors ());
if (pd == null) {
throw new IllegalArgumentException ("property '" + propName + "' is " +
"unknown for '" + target + "'");
}
// get read method and type of property
Method rm;
Class propType;
if (index != null) {
// if index != null, then property is indexed - pd better be so too
if (!(pd instanceof IndexedPropertyDescriptor)) {
throw new IllegalArgumentException ("attempt to get non-indexed " +
"property '" + propName +
"' as being indexed");
}
IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
rm = ipd.getIndexedReadMethod ();
propType = ipd.getIndexedPropertyType ();
} else {
rm = pd.getReadMethod ();
propType = pd.getPropertyType ();
}
if (rm == null) {
throw new IllegalArgumentException ("property '" + propName +
"' is not readable");
}
// now get the value
Object propVal = null;
if (index != null) {
propVal = rm.invoke (target, new Object[] {index});
} else {
propVal = rm.invoke (target, null);
}
return new Bean (propType, propVal);
}
public static void setField (Object target, String fieldName, Bean value,
TypeConvertorRegistry tcr)
throws IllegalArgumentException, IllegalAccessException {
// This is to handle how we do static fields.
Class targetClass = (target instanceof Class)
? (Class) target
: target.getClass ();
try {
Field f = targetClass.getField (fieldName);
Class fieldType = f.getType ();
// type convert the value if necessary
Object fieldVal = null;
boolean okeydokey = true;
if (fieldType.isAssignableFrom (value.type)) {
fieldVal = value.value;
} else if (tcr != null) {
TypeConvertor cvtor = tcr.lookup (value.type, fieldType);
if (cvtor != null) {
fieldVal = cvtor.convert (value.type, fieldType, value.value);
} else {
okeydokey = false;
}
} else {
okeydokey = false;
}
if (!okeydokey) {
throw new IllegalArgumentException ("unable to assign '" + value.value +
"' to field '" + fieldName + "'");
}
// now set the value
f.set (target, fieldVal);
} catch (NoSuchFieldException e) {
throw new IllegalArgumentException ("field '" + fieldName + "' is " +
"unknown for '" + target + "'");
}
}
//////////////////////////////////////////////////////////////////////////
/**
* Set a property of a bean to a given value.
*
* @param target the object whose prop is to be set
* @param propName name of the property to set
* @param index index to set (if property is indexed)
* @param value the property value
* @param valueType the type of the above (needed when its null)
* @param tcr type convertor registry to use to convert value type to
* property type if necessary
*
* @exception IntrospectionException if unable to introspect
* @exception IllegalArgumentException if problems with args: if the
* property is unknown, or if the property is given an index
* when its not, or if the property is not writeable, or if
* the given value cannot be assigned to the it (type mismatch).
* @exception IllegalAccessException if write method is not accessible
* @exception InvocationTargetException if write method excepts
*/
public static void setProperty (Object target, String propName,
Integer index, Object value,
Class valueType, TypeConvertorRegistry tcr)
throws IntrospectionException, IllegalArgumentException,
IllegalAccessException, InvocationTargetException {
// find the property descriptor
BeanInfo bi = Introspector.getBeanInfo (target.getClass ());
PropertyDescriptor pd = (PropertyDescriptor)
findFeatureByName ("property", propName, bi.getPropertyDescriptors ());
if (pd == null) {
throw new IllegalArgumentException ("property '" + propName + "' is " +
"unknown for '" + target + "'");
}
// get write method and type of property
Method wm;
Class propType;
if (index != null) {
// if index != null, then property is indexed - pd better be so too
if (!(pd instanceof IndexedPropertyDescriptor)) {
throw new IllegalArgumentException ("attempt to set non-indexed " +
"property '" + propName +
"' as being indexed");
}
IndexedPropertyDescriptor ipd = (IndexedPropertyDescriptor) pd;
wm = ipd.getIndexedWriteMethod ();
propType = ipd.getIndexedPropertyType ();
} else {
wm = pd.getWriteMethod ();
propType = pd.getPropertyType ();
}
if (wm == null) {
throw new IllegalArgumentException ("property '" + propName +
"' is not writeable");
}
// type convert the value if necessary
Object propVal = null;
boolean okeydokey = true;
if (propType.isAssignableFrom (valueType)) {
propVal = value;
} else if (tcr != null) {
TypeConvertor cvtor = tcr.lookup (valueType, propType);
if (cvtor != null) {
propVal = cvtor.convert (valueType, propType, value);
} else {
okeydokey = false;
}
} else {
okeydokey = false;
}
if (!okeydokey) {
throw new IllegalArgumentException ("unable to assign '" + value +
"' to property '" + propName + "'");
}
// now set the value
if (index != null) {
wm.invoke (target, new Object[] {index, propVal});
} else {
wm.invoke (target, new Object[] {propVal});
}
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.util.Hashtable;
/**
* An <code>ScriptSymbolTable</code> object is used by a <code>CodeBuffer</code>
* object to implement nested scopes.
*
* @author Matthew J. Duftler
*/
class ScriptSymbolTable extends Hashtable
{
private Hashtable parentTable;
ScriptSymbolTable(Hashtable parentTable)
{
this.parentTable = parentTable;
}
public synchronized Object get(Object key)
{
Object ret = super.get(key);
if (ret == null && parentTable != null)
ret = parentTable.get(key);
return ret;
}
}

View File

@ -0,0 +1,412 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util;
import java.beans.Introspector;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* Deals with strings (probably need to elaborate some more).
*
* @author Matthew J. Duftler
*/
public class StringUtils
{
public static final String lineSeparator =
System.getProperty("line.separator", "\n");
public static final String lineSeparatorStr = cleanString(lineSeparator);
public static String classNameToVarName(String className)
{
// Might represent an array.
int arrayDim = 0;
while (className.endsWith("[]"))
{
className = className.substring(0, className.length() - 2);
arrayDim++;
}
int iLastPeriod = className.lastIndexOf('.');
String varName = Introspector.decapitalize(
iLastPeriod != -1
? className.substring(iLastPeriod + 1)
: className);
if (arrayDim > 0)
{
varName += "_" + arrayDim + "D";
}
return getValidIdentifierName(varName);
}
// Ensure that escape sequences are passed through properly.
public static String cleanString(String str)
{
if (str == null)
return null;
else
{
char[] charArray = str.toCharArray();
StringBuffer sBuf = new StringBuffer();
for (int i = 0; i < charArray.length; i++)
switch (charArray[i])
{
case '\"' : sBuf.append("\\\"");
break;
case '\\' : sBuf.append("\\\\");
break;
case '\n' : sBuf.append("\\n");
break;
case '\r' : sBuf.append("\\r");
break;
default : sBuf.append(charArray[i]);
break;
}
return sBuf.toString();
}
}
/**
* Get a string consisting of <code>numberOfChars</code> theChars.
*
* @return a string consisting of <code>numberOfChars</code> theChars.
*/
public static String getChars(int numberOfChars, char theChar)
{
if (numberOfChars <= 0)
return "";
StringBuffer sRet = new StringBuffer(numberOfChars);
for (int i = 0; i < numberOfChars; i++)
sRet.append(theChar);
return sRet.toString();
}
/*
This method will return the correct name for a class object representing
a primitive, a single instance of a class, as well as n-dimensional arrays
of primitives or instances. This logic is needed to handle the string returned
from Class.getName(). If the class object represents a single instance (or
a primitive), Class.getName() returns the fully-qualified name of the class
and no further work is needed. However, if the class object represents an
array (of n dimensions), Class.getName() returns a Descriptor (the Descriptor
grammar is defined in section 4.3 of the Java VM Spec). This method will
parse the Descriptor if necessary.
*/
public static String getClassName(Class targetClass)
{
String className = targetClass.getName();
return targetClass.isArray() ? parseDescriptor(className) : className;
}
public static String getCommaListFromVector(Vector sourceVector)
{
StringBuffer strBuf = new StringBuffer();
for (int i = 0; i < sourceVector.size(); i++)
{
strBuf.append((i > 0 ? ", " : "") +
sourceVector.elementAt(i));
}
return strBuf.toString();
}
/*
Returns a Reader for reading from the specified resource, if the resource
points to a stream.
*/
public static Reader getContentAsReader(URL url) throws SecurityException,
IllegalArgumentException,
IOException
{
if (url == null)
{
throw new IllegalArgumentException("URL cannot be null.");
}
try
{
Object content = url.getContent();
if (content == null)
{
throw new IllegalArgumentException("No content.");
}
if (content instanceof InputStream)
{
Reader in = new InputStreamReader((InputStream)content);
if (in.ready())
{
return in;
}
else
{
throw new FileNotFoundException();
}
}
else
{
throw new IllegalArgumentException((content instanceof String)
? (String)content
: "This URL points to a: " +
StringUtils.getClassName(content.getClass()));
}
}
catch (SecurityException e)
{
throw new SecurityException("Your JVM's SecurityManager has disallowed this.");
}
catch (FileNotFoundException e)
{
throw new FileNotFoundException("This file was not found: " + url);
}
}
/*
Shorthand for: IOUtils.getStringFromReader(getContentAsReader(url)).
*/
public static String getContentAsString(URL url) throws SecurityException,
IllegalArgumentException,
IOException
{
return IOUtils.getStringFromReader(getContentAsReader(url));
}
// Handles multi-line strings.
public static String getSafeString(String scriptStr)
{
BufferedReader in = new BufferedReader(new StringReader(scriptStr));
StringBuffer strBuf = new StringBuffer();
String tempLine,
previousLine = null;
try
{
while ((tempLine = in.readLine()) != null)
{
if (previousLine != null)
{
strBuf.append("\"" + previousLine + lineSeparatorStr + "\" +" +
lineSeparator);
}
previousLine = cleanString(tempLine);
}
}
catch (IOException e)
{
}
strBuf.append("\"" + (previousLine != null ? previousLine : "") + "\"" +
lineSeparator);
return strBuf.toString();
}
/*
*/
public static URL getURL(URL contextURL, String spec) throws MalformedURLException
{
return getURL(contextURL, spec, 1);
}
/*
The recursiveDepth argument is used to insure that the algorithm gives up
after hunting 2 levels up in the contextURL's path.
*/
private static URL getURL(URL contextURL, String spec, int recursiveDepth)
throws MalformedURLException
{
URL url = null;
try
{
url = new URL(contextURL, spec);
try
{
url.openStream();
}
catch (IOException ioe1)
{
throw new MalformedURLException("This file was not found: " + url);
}
}
catch (MalformedURLException e1)
{
url = new URL("file", "", spec);
try
{
url.openStream();
}
catch (IOException ioe2)
{
if (contextURL != null)
{
String contextFileName = contextURL.getFile();
String parentName = new File(contextFileName).getParent();
if (parentName != null && recursiveDepth < 3)
{
return getURL(new URL("file", "", parentName + '/'),
spec,
recursiveDepth + 1);
}
}
throw new MalformedURLException("This file was not found: " + url);
}
}
return url;
}
public static String getValidIdentifierName(String identifierName)
{
if (identifierName == null || identifierName.length() == 0)
return null;
StringBuffer strBuf = new StringBuffer();
char[] chars = identifierName.toCharArray();
strBuf.append(Character.isJavaIdentifierStart(chars[0])
? chars[0]
: '_'
);
for (int i = 1; i < chars.length; i++)
{
strBuf.append(Character.isJavaIdentifierPart(chars[i])
? chars[i]
: '_'
);
}
return strBuf.toString();
}
public static boolean isValidIdentifierName(String identifierName)
{
if (identifierName == null || identifierName.length() == 0)
return false;
char[] chars = identifierName.toCharArray();
if (!Character.isJavaIdentifierStart(chars[0]))
return false;
for (int i = 1; i < chars.length; i++)
if (!Character.isJavaIdentifierPart(chars[i]))
return false;
return true;
}
public static boolean isValidPackageName(String packageName)
{
if (packageName == null)
return false;
else if (packageName.length() == 0)
// Empty is ok.
return true;
StringTokenizer strTok = new StringTokenizer(packageName, ".", true);
// Should have an odd number of tokens (including '.' delimiters).
if (strTok.countTokens() % 2 != 1)
return false;
// Must start with a valid identifier name.
if (!isValidIdentifierName(strTok.nextToken()))
return false;
// ... followed by 0 or more of ".ValidIdentifier".
while (strTok.hasMoreTokens())
{
// Must be a '.'.
if (!strTok.nextToken().equals("."))
return false;
// Must be a valid identifier name.
if (strTok.hasMoreTokens())
{
if (!isValidIdentifierName(strTok.nextToken()))
return false;
}
else
return false;
}
return true;
}
/*
See the comment above for getClassName(targetClass)...
*/
private static String parseDescriptor(String className)
{
char[] classNameChars = className.toCharArray();
int arrayDim = 0;
int i = 0;
while (classNameChars[i] == '[')
{
arrayDim++;
i++;
}
StringBuffer classNameBuf = new StringBuffer();
switch (classNameChars[i++])
{
case 'B' : classNameBuf.append("byte");
break;
case 'C' : classNameBuf.append("char");
break;
case 'D' : classNameBuf.append("double");
break;
case 'F' : classNameBuf.append("float");
break;
case 'I' : classNameBuf.append("int");
break;
case 'J' : classNameBuf.append("long");
break;
case 'S' : classNameBuf.append("short");
break;
case 'Z' : classNameBuf.append("boolean");
break;
case 'L' : classNameBuf.append(classNameChars,
i, classNameChars.length - i - 1);
break;
}
for (i = 0; i < arrayDim; i++)
classNameBuf.append("[]");
return classNameBuf.toString();
}
}

View File

@ -0,0 +1,196 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.cf;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.Writer;
/**
* This is an example of how a <code>CodeFormatter</code> bean can be used.
* <p>
* The CFDriver is a stand-alone tool that will instantiate a
* <code>CodeFormatter</code> bean, configure it according to your
* command-line arguments, and invoke the formatting. Since the
* default source of input is <code>stdin</code>, and the default
* target for output is <code>stdout</code>, a <code>CFDriver</code>
* can also be used as a filter.
*
* @see CodeFormatter
*
* @version 1.0
* @author Matthew J. Duftler
*/
public class CFDriver
{
/**
* Not used.
*/
public CFDriver()
{
}
/**
* A driver for <code>CodeFormatter</code>.
*<p>
* Usage:
*<code><pre>
* java org.apache.cf.CFDriver [args]
*<p>
* args:
*<p>
* [-in fileName] default: &lt;STDIN&gt;
* [-out fileName] default: &lt;STDOUT&gt;
* [-maxLine length] default: 74
* [-step size] default: 2
* [-delim group] default: (+
* [-sdelim group] default: ,
*</pre></code>
*/
public static void main(String[] argv)
{
if (argv.length % 2 == 0)
{
String inFile = null,
outFile = null,
maxLine = null,
indStep = null,
delim = null,
sDelim = null;
Reader in = null;
Writer out = null;
CodeFormatter cf = new CodeFormatter();
for (int i = 0; i < argv.length; i += 2)
{
if (argv[i].startsWith("-i"))
inFile = argv[i + 1];
else if (argv[i].startsWith("-o"))
outFile = argv[i + 1];
else if (argv[i].startsWith("-m"))
maxLine = argv[i + 1];
else if (argv[i].startsWith("-st"))
indStep = argv[i + 1];
else if (argv[i].startsWith("-d"))
delim = argv[i + 1];
else if (argv[i].startsWith("-sd"))
sDelim = argv[i + 1];
}
if (inFile != null)
{
try
{
in = new FileReader(inFile);
}
catch (FileNotFoundException e)
{
printError("Cannot open input file: " + inFile);
return;
}
}
else
{
in = new InputStreamReader(System.in);
}
if (outFile != null)
{
try
{
out = new FileWriter(outFile);
}
catch (IOException e)
{
printError("Cannot open output file: " + outFile);
return;
}
}
else
{
out = new OutputStreamWriter(System.out);
}
if (maxLine != null)
{
try
{
cf.setMaxLineLength(Integer.parseInt(maxLine));
}
catch (NumberFormatException nfe)
{
printError("Not a valid integer: " + maxLine);
return;
}
}
if (indStep != null)
{
try
{
cf.setIndentationStep(Integer.parseInt(indStep));
}
catch (NumberFormatException nfe)
{
printError("Not a valid integer: " + indStep);
return;
}
}
if (delim != null)
cf.setDelimiters(delim);
if (sDelim != null)
cf.setStickyDelimiters(sDelim);
cf.formatCode(in, out);
}
else
printHelp();
}
private static void printError(String errMsg)
{
System.err.println("ERROR: " + errMsg);
}
private static void printHelp()
{
System.out.println("Usage:");
System.out.println();
System.out.println(" java " + CFDriver.class.getName() + " [args]");
System.out.println();
System.out.println(" args:");
System.out.println();
System.out.println(" [-in fileName] default: <STDIN>");
System.out.println(" [-out fileName] default: <STDOUT>");
System.out.println(" [-maxLine length] default: " +
CodeFormatter.DEFAULT_MAX);
System.out.println(" [-step size] default: " +
CodeFormatter.DEFAULT_STEP);
System.out.println(" [-delim group] default: " +
CodeFormatter.DEFAULT_DELIM);
System.out.println(" [-sdelim group] default: " +
CodeFormatter.DEFAULT_S_DELIM);
}
}

View File

@ -0,0 +1,372 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.cf;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.Writer;
import com.volmit.iris.util.bsf.util.IndentWriter;
import com.volmit.iris.util.bsf.util.StringUtils;
/**
* A <code>CodeFormatter</code> bean is used to format raw Java code. It
* indents, word-wraps, and replaces tab characters with an amount of space
* characters equal to the size of the <code>indentationStep</code> property.
* To create and use a <code>CodeFormatter</code>, you simply instantiate a
* new <code>CodeFormatter</code> bean, and invoke
* <code>formatCode(Reader source, Writer target)</code> with appropriate
* arguments.
*
* @version 1.0
* @author Matthew J. Duftler
*/
public class CodeFormatter
{
/**
* The default maximum line length.
*/
public static final int DEFAULT_MAX = 74;
/**
* The default size of the indentation step.
*/
public static final int DEFAULT_STEP = 2;
/**
* The default set of delimiters.
*/
public static final String DEFAULT_DELIM = "(+";
/**
* The default set of sticky delimiters.
*/
public static final String DEFAULT_S_DELIM = ",";
// Configurable Parameters
private int maxLineLength = DEFAULT_MAX;
private int indentationStep = DEFAULT_STEP;
private String delimiters = DEFAULT_DELIM;
private String stickyDelimiters = DEFAULT_S_DELIM;
// Global Variables
private int indent;
private int hangingIndent;
private int origIndent;
private boolean inCPP_Comment;
private void addTok(StringBuffer targetBuf, StringBuffer tokBuf,
IndentWriter out)
{
int tokLength = tokBuf.length(),
targetLength = targetBuf.length();
if (indent + targetLength + tokLength > maxLineLength)
{
if (targetLength == 0)
{
out.println(indent, tokBuf.toString());
indent = hangingIndent;
targetBuf.setLength(0);
return;
}
else
{
out.println(indent, targetBuf.toString().trim());
indent = hangingIndent;
targetBuf.setLength(0);
}
}
targetBuf.append(tokBuf.toString());
return;
}
/**
* Formats the code read from <code>source</code>, and writes the formatted
* code to <code>target</code>.
*
* @param source where to read the unformatted code from.
* @param target where to write the formatted code to.
*/
public void formatCode(Reader source, Writer target)
{
String line;
BufferedReader in = new BufferedReader(source);
IndentWriter out = new IndentWriter(new BufferedWriter(target), true);
try
{
origIndent = 0;
inCPP_Comment = false;
while ((line = in.readLine()) != null)
{
line = line.trim();
if (line.length() > 0)
{
indent = origIndent;
hangingIndent = indent + indentationStep;
printLine(line, out);
}
else
out.println();
}
}
catch (IOException e)
{
e.printStackTrace();
}
}
/**
* Gets the set of delimiters.
*
* @return the set of delimiters.
* @see #setDelimiters
*/
public String getDelimiters()
{
return delimiters;
}
/**
* Gets the size of the indentation step.
*
* @return the size of the indentation step.
* @see #setIndentationStep
*/
public int getIndentationStep()
{
return indentationStep;
}
/**
* Gets the maximum line length.
*
* @return the maximum line length.
* @see #setMaxLineLength
*/
public int getMaxLineLength()
{
return maxLineLength;
}
/**
* Gets the set of sticky delimiters.
*
* @return the set of sticky delimiters.
* @see #setStickyDelimiters
*/
public String getStickyDelimiters()
{
return stickyDelimiters;
}
private void printLine(String line, IndentWriter out)
{
char[] source = line.toCharArray();
char ch;
char quoteChar = ' ';
boolean inEscapeSequence = false;
boolean inString = false;
StringBuffer tokBuf = new StringBuffer(),
targetBuf = new StringBuffer(hangingIndent + line.length());
for (int i = 0; i < source.length; i++)
{
ch = source[i];
if (inEscapeSequence)
{
tokBuf.append(ch);
inEscapeSequence = false;
}
else
{
if (inString)
{
switch (ch)
{
case '\\' :
tokBuf.append('\\');
inEscapeSequence = true;
break;
case '\'' :
case '\"' :
tokBuf.append(ch);
if (ch == quoteChar)
{
addTok(targetBuf, tokBuf, out);
tokBuf.setLength(0);
inString = false;
}
break;
case 9 : // pass thru tab characters...
tokBuf.append(ch);
break;
default :
if (ch > 31)
tokBuf.append(ch);
break;
}
}
else // !inString
{
if (inCPP_Comment)
{
tokBuf.append(ch);
if (ch == '/' && i > 0 && source[i - 1] == '*')
inCPP_Comment = false;
}
else
{
switch (ch)
{
case '/' :
tokBuf.append(ch);
if (i > 0 && source[i - 1] == '/')
{
String tokStr = tokBuf.append(source,
i + 1,
source.length - (i + 1)).toString();
out.println(indent, targetBuf.append(tokStr).toString());
return;
}
break;
case '*' :
tokBuf.append(ch);
if (i > 0 && source[i - 1] == '/')
inCPP_Comment = true;
break;
case '\'' :
case '\"' :
addTok(targetBuf, tokBuf, out);
tokBuf.setLength(0);
tokBuf.append(ch);
quoteChar = ch;
inString = true;
break;
case 9 : // replace tab characters...
tokBuf.append(StringUtils.getChars(indentationStep, ' '));
break;
case '{' :
tokBuf.append(ch);
origIndent += indentationStep;
break;
case '}' :
tokBuf.append(ch);
origIndent -= indentationStep;
if (i == 0)
indent = origIndent;
break;
default :
if (ch > 31)
{
if (delimiters.indexOf(ch) != -1)
{
addTok(targetBuf, tokBuf, out);
tokBuf.setLength(0);
tokBuf.append(ch);
}
else if (stickyDelimiters.indexOf(ch) != -1)
{
tokBuf.append(ch);
addTok(targetBuf, tokBuf, out);
tokBuf.setLength(0);
}
else
tokBuf.append(ch);
}
break;
}
}
}
}
}
if (tokBuf.length() > 0)
addTok(targetBuf, tokBuf, out);
String lastLine = targetBuf.toString().trim();
if (lastLine.length() > 0)
out.println(indent, lastLine);
}
/**
* Sets the set of delimiters; default set is <code>"(+"</code>.
* <p>
* Each character represents one delimiter. If a line is ready to be
* word-wrapped and a delimiter is encountered, the delimiter will
* appear as the <em>first character on the following line</em>.
* A quotation mark, <code>"</code> or <code>'</code>, opening a string
* is always a delimiter, whether you specify it or not.
*
* @param newDelimiters the new set of delimiters.
* @see #getDelimiters
*/
public void setDelimiters(String newDelimiters)
{
delimiters = newDelimiters;
}
/**
* Sets the size of the indentation step; default size is <code>2</code>.
* <p>
* This is the number of spaces that lines will be indented (when appropriate).
*
* @param newIndentationStep the new size of the indentation step.
* @see #getIndentationStep
*/
public void setIndentationStep(int newIndentationStep)
{
indentationStep = (newIndentationStep < 0 ? 0 : newIndentationStep);
}
/**
* Sets the (desired) maximum line length; default length is
* <code>74</code>.
* <p>
* If a token is longer than the requested maximum line length,
* then the line containing that token will obviously be longer
* than the desired maximum.
*
* @param newMaxLineLength the new maximum line length.
* @see #getMaxLineLength
*/
public void setMaxLineLength(int newMaxLineLength)
{
maxLineLength = (newMaxLineLength < 0 ? 0 : newMaxLineLength);
}
/**
* Sets the set of sticky delimiters; default set is <code>","</code>.
* <p>
* Each character represents one sticky delimiter. If a line is ready
* to be word-wrapped and a sticky delimiter is encountered, the sticky
* delimiter will appear as the <em>last character on the current line</em>.
* A quotation mark, <code>"</code> or <code>'</code>, closing a string
* is always a sticky delimiter, whether you specify it or not.
*
* @param newStickyDelimiters the new set of sticky delimiters.
* @see #getStickyDelimiters
*/
public void setStickyDelimiters(String newStickyDelimiters)
{
stickyDelimiters = newStickyDelimiters;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event;
/**
* <em>EventAdapter</em> is the interface that all event adapters must
* implement in order to work with the automatic event adapter generation
* model. This interface requires that the adapter implement a method
* that allows setting the event processor delegated to process the event
* after the adapter has received the event from the event source. The
* task of any event adapter is to receive the event and then delegate it
* to the event processor assigned to it, using either
* eventProcessor.processEvent or eventProcessor.processExceptionableEvent.
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @see EventProcessor
*/
public interface EventAdapter {
public void setEventProcessor (EventProcessor eventProcessor);
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event;
/**
* <em>EventAdapterImpl</em> is a default implementation of the EventAdapter
* interface that specific event adapters may choose to subclass from
* instead of implementing the interface themselves. Saves 5 lines of code
* mebbe.
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @see EventAdapter
*/
public class EventAdapterImpl implements EventAdapter {
protected EventProcessor eventProcessor;
public void setEventProcessor (EventProcessor eventProcessor) {
this.eventProcessor = eventProcessor;
}
}

View File

@ -0,0 +1,103 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event;
import java.util.Hashtable;
import com.volmit.iris.util.bsf.util.event.generator.EventAdapterGenerator;
/**
* The <em>EventAdapterRegistry</em> is the registry of event adapters.
* If a desired adapter is not found, the adapter will be dynamically
* generated when lookup is attempted. Set the <code>dynamic</code> property
* to <code>false</code> to disable this feature.
* <p>
* This implementation first looks for an adapter in its lookup table
* and if it doesn't find one looks for a standard implementation of
* that adapter in the com.volmit.iris.util.bsf.util.event.adapters package with a
* standard naming convention. The naming convention it assumes is the
* following: for event listener type <tt>a.b.c.FooListener</tt>,
* it loads an adapter of type
* <tt>com.volmit.iris.util.bsf.util.event.adapters.a_b_c_FooAdapter</tt>.
* If both the loading and the dynamic generation fail, then a
* <code>null</code> is returned.
* <p>
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @see EventAdapter
*/
public class EventAdapterRegistry {
private static Hashtable reg = new Hashtable ();
private static ClassLoader cl = null;
private static String adapterPackage = "com.volmit.iris.util.bsf.util.event.adapters";
private static String adapterSuffix = "Adapter";
private static boolean dynamic = true;
public static Class lookup (Class listenerType) {
String key = listenerType.getName().replace ('.', '_');
Class adapterClass = (Class) reg.get (key);
if (adapterClass == null) {
String en = key.substring (0, key.lastIndexOf ("Listener"));
String cn = adapterPackage + "." + en + adapterSuffix;
try {
// Try to resolve one.
// adapterClass = (cl != null) ? cl.loadClass (cn) : Class.forName (cn);
adapterClass = (cl != null) ? cl.loadClass (cn)
: Thread.currentThread().getContextClassLoader().loadClass (cn); // rgf, 2006-01-05
} catch (ClassNotFoundException e) {
if (dynamic) {
// Unable to resolve one, try to generate one.
adapterClass = // if second argument is set to 'true', then the class file will be stored in the filesystem
EventAdapterGenerator.makeEventAdapterClass (listenerType, false);
}
}
if (adapterClass != null) {
reg.put (key, adapterClass);
}
}
return adapterClass;
}
public static void register (Class listenerType, Class eventAdapterClass) {
String key = listenerType.getName().replace('.', '_');
reg.put (key, eventAdapterClass);
}
/**
* Class loader to use to load event adapter classes.
*/
public static void setClassLoader (ClassLoader cloader) {
cl = cloader;
}
/**
* Indicates whether or not to dynamically generate adapters; default is
* <code>true</code>.
* <p>
* If the <code>dynamic</code> property is set to true, and the
* <code>ClassLoader</code> is unable to resolve an adapter, one will be
* dynamically generated.
*
* @param dynamic whether or not to dynamically generate adapters.
*/
public static void setDynamic (boolean dynamic) {
EventAdapterRegistry.dynamic = dynamic;
}
}

View File

@ -0,0 +1,35 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event;
/**
* <em>EventProcessor</em> is the interface that event adapters use to
* delegate events they received to be delivered to the appropriate target.
* They can simply deliver the event using processEvent or, if the event
* can be excepted to, via processExceptionableEvent (in which case the
* adapter is expected to forward on an exception to the source bean).
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @see EventAdapter
*/
public interface EventProcessor {
public void processEvent (String filter, Object[] eventInfo);
public void processExceptionableEvent (String filter, Object[] eventInfo)
throws Exception;
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_ActionAdapter extends EventAdapterImpl
implements ActionListener {
public void actionPerformed (ActionEvent e) {
eventProcessor.processEvent ("actionPerformed", new Object[]{e});
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.AdjustmentEvent;
import java.awt.event.AdjustmentListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_AdjustmentAdapter extends EventAdapterImpl
implements AdjustmentListener {
public void adjustmentValueChanged (AdjustmentEvent e) {
eventProcessor.processEvent ("adjustmentValueChanged", new Object[]{e});
}
}

View File

@ -0,0 +1,39 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.ComponentEvent;
import java.awt.event.ComponentListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_ComponentAdapter extends EventAdapterImpl
implements ComponentListener {
public void componentHidden (ComponentEvent e) {
eventProcessor.processEvent ("componentHidden", new Object[]{e});
}
public void componentMoved (ComponentEvent e) {
eventProcessor.processEvent ("componentMoved", new Object[]{e});
}
public void componentResized (ComponentEvent e) {
eventProcessor.processEvent ("componentResized", new Object[]{e});
}
public void componentShown (ComponentEvent e) {
eventProcessor.processEvent ("componentShown", new Object[]{e});
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.ContainerEvent;
import java.awt.event.ContainerListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_ContainerAdapter extends EventAdapterImpl
implements ContainerListener {
public void componentAdded (ContainerEvent e) {
eventProcessor.processEvent ("componentAdded", new Object[]{e});
}
public void componentRemoved (ContainerEvent e) {
eventProcessor.processEvent ("componentRemoved", new Object[]{e});
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.FocusEvent;
import java.awt.event.FocusListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_FocusAdapter extends EventAdapterImpl
implements FocusListener {
public void focusGained (FocusEvent e) {
eventProcessor.processEvent ("focusGained", new Object[]{e});
}
public void focusLost (FocusEvent e) {
eventProcessor.processEvent ("focusLost", new Object[]{e});
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_ItemAdapter extends EventAdapterImpl
implements ItemListener {
public void itemStateChanged (ItemEvent e) {
eventProcessor.processEvent ("itemStateChanged", new Object[]{e});
}
}

View File

@ -0,0 +1,36 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_KeyAdapter extends EventAdapterImpl
implements KeyListener {
public void keyPressed (KeyEvent e) {
eventProcessor.processEvent ("keyPressed", new Object[]{e});
}
public void keyReleased (KeyEvent e) {
eventProcessor.processEvent ("keyReleased", new Object[]{e});
}
public void keyTyped (KeyEvent e) {
eventProcessor.processEvent ("keyTyped", new Object[]{e});
}
}

View File

@ -0,0 +1,42 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_MouseAdapter extends EventAdapterImpl
implements MouseListener {
public void mouseClicked (MouseEvent e) {
eventProcessor.processEvent ("mouseClicked", new Object[]{e});
}
public void mouseEntered (MouseEvent e) {
eventProcessor.processEvent ("mouseEntered", new Object[]{e});
}
public void mouseExited (MouseEvent e) {
eventProcessor.processEvent ("mouseExited", new Object[]{e});
}
public void mousePressed (MouseEvent e) {
eventProcessor.processEvent ("mousePressed", new Object[]{e});
}
public void mouseReleased (MouseEvent e) {
eventProcessor.processEvent ("mouseReleased", new Object[]{e});
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_MouseMotionAdapter extends EventAdapterImpl
implements MouseMotionListener {
public void mouseDragged(MouseEvent e) {
eventProcessor.processEvent ("mouseDragged", new Object[]{e});
}
public void mouseMoved(MouseEvent e) {
eventProcessor.processEvent ("mouseMoved", new Object[]{e});
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.TextEvent;
import java.awt.event.TextListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_TextAdapter extends EventAdapterImpl
implements TextListener {
public void textValueChanged (TextEvent e) {
eventProcessor.processEvent ("textValueChanged", new Object[]{e});
}
}

View File

@ -0,0 +1,48 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_awt_event_WindowAdapter extends EventAdapterImpl
implements WindowListener {
public void windowActivated (WindowEvent e) {
eventProcessor.processEvent ("windowActivated", new Object[]{e});
}
public void windowClosed (WindowEvent e) {
eventProcessor.processEvent ("windowClosed", new Object[]{e});
}
public void windowClosing (WindowEvent e) {
eventProcessor.processEvent ("windowClosing", new Object[]{e});
}
public void windowDeactivated (WindowEvent e) {
eventProcessor.processEvent ("windowDeactivated", new Object[]{e});
}
public void windowDeiconified (WindowEvent e) {
eventProcessor.processEvent ("windowDeiconified", new Object[]{e});
}
public void windowIconified (WindowEvent e) {
eventProcessor.processEvent ("windowIconified", new Object[]{e});
}
public void windowOpened (WindowEvent e) {
eventProcessor.processEvent ("windowOpened", new Object[]{e});
}
}

View File

@ -0,0 +1,30 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_beans_PropertyChangeAdapter extends EventAdapterImpl
implements PropertyChangeListener {
public void propertyChange(PropertyChangeEvent e) {
eventProcessor.processEvent (e.getPropertyName(), new Object[]{e});
}
}

View File

@ -0,0 +1,41 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.adapters;
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import com.volmit.iris.util.bsf.util.event.EventAdapterImpl;
public class java_beans_VetoableChangeAdapter extends EventAdapterImpl
implements VetoableChangeListener {
public void vetoableChange (PropertyChangeEvent e) throws PropertyVetoException {
try
{
eventProcessor.processExceptionableEvent (e.getPropertyName(), new Object[]{e});
}
catch (PropertyVetoException ex)
{
throw ex;
}
catch (Exception ex)
{
}
}
}

View File

@ -0,0 +1,102 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.generator;
import java.util.Hashtable;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class AdapterClassLoader extends ClassLoader
{
private static Hashtable classCache = new Hashtable();
private Class c;
private Log logger = LogFactory.getLog(this.getClass().getName());
public AdapterClassLoader()
{
super();
}
public synchronized Class defineClass(String name, byte[] b)
{
if ((c = getLoadedClass(name)) == null)
{
c = defineClass(name.replace('/','.'), b, 0, b.length); // rgf, 2006-02-03
put(name, c);
}
else
{
logger.error("AdapterClassLoader: " + c +
" previously loaded. Can not redefine class.");
}
return c;
}
final protected Class findClass(String name)
{
return get(name);
}
final protected Class get(String name)
{
return (Class)classCache.get(name);
}
public synchronized Class getLoadedClass(String name)
{
Class c = findLoadedClass(name);
if (c == null)
{
try
{
c = findSystemClass(name);
}
catch (ClassNotFoundException e)
{
}
}
if (c == null)
{
c = findClass(name);
}
return c;
}
protected synchronized Class loadClass(String name, boolean resolve)
throws ClassNotFoundException
{
Class c = getLoadedClass(name);
if (c != null && resolve)
{
resolveClass(c);
}
return c;
}
// Not in JDK 1.1, only in JDK 1.2.
// public AdapterClassLoader(ClassLoader loader)
// {
// super(loader);
// }
final protected void put(String name, Class c)
{
classCache.put(name, c);
}
}

View File

@ -0,0 +1,331 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.generator;
/**
* Byte handling utilities
*
* 5 April 1999 - functions to append standard types to byte arrays
* functions to produce standard types from byte arrays
*
* @author Richard F. Boehme
*
*/
public class ByteUtility
{
public static byte[] addBytes(byte[] array,byte[] value)
{
if( null != array )
{
byte newarray[] = new byte[array.length + value.length];
System.arraycopy(array,0,newarray,0,array.length);
System.arraycopy(value,0,newarray,array.length,value.length);
array = newarray;
}
else
{
array = value;
}
return array;
}
public static byte[] addBytes(byte[] array, byte value)
{
if( null != array )
{
byte newarray[] = new byte[array.length + 1];
System.arraycopy(array,0,newarray,0,array.length);
newarray[newarray.length-1] = value;
array = newarray;
}
else
{
array = new byte[1];
array[0] = value;
}
return array;
}
public static byte[] addBytes(byte[] array, int value)
{
if( null != array )
{
byte newarray[] = new byte[array.length + 3];
System.arraycopy(array,0,newarray,0,array.length);
newarray[newarray.length-3] = (byte) (( value >> 16 ) & 0xFF);
newarray[newarray.length-2] = (byte) (( value >> 8 ) & 0xFF);
newarray[newarray.length-1] = (byte) ( value & 0xFF);
array = newarray;
}
else
{
array = new byte[3];
array[0] = (byte) (( value >> 16 ) & 0xFF);
array[1] = (byte) (( value >> 8 ) & 0xFF);
array[2] = (byte) ( value & 0xFF);
}
return array;
}
public static byte[] addBytes(byte[] array, long value)
{
if( null != array )
{
byte newarray[] = new byte[array.length + 4];
System.arraycopy(array,0,newarray,0,array.length);
newarray[newarray.length-4] = (byte) (( value >> 24 ) & 0xFF);
newarray[newarray.length-3] = (byte) (( value >> 16 ) & 0xFF);
newarray[newarray.length-2] = (byte) (( value >> 8 ) & 0xFF);
newarray[newarray.length-1] = (byte) ( value & 0xFF);
array = newarray;
}
else
{
array = new byte[4];
array[0] = (byte) (( value >> 24 ) & 0xFF);
array[1] = (byte) (( value >> 16 ) & 0xFF);
array[2] = (byte) (( value >> 8 ) & 0xFF);
array[3] = (byte) (value & 0xFF);
}
return array;
}
public static byte[] addBytes(byte[] array,String value)
{
if( null != value )
{
if( null != array)
{
byte newarray[] = new byte[array.length + value.length()];
System.arraycopy(array,0,newarray,0,array.length);
System.arraycopy(value.getBytes(),0,newarray,array.length,value.length());
array = newarray;
}
else
{
array = value.getBytes();
}
}
return array;
}
public static byte[] addBytes(byte[] array, short value)
{
if( null != array)
{
byte newarray[] = new byte[array.length + 2];
System.arraycopy(array,0,newarray,0,array.length);
newarray[newarray.length-2] = (byte) (( value >> 8 ) & 0xFF);
newarray[newarray.length-1] = (byte) ( value & 0xFF);
array = newarray;
}
else
{
array = new byte[2];
array[0] = (byte) (( value >> 8 ) & 0xFF);
array[1] = (byte) ( value & 0xFF);
}
return array;
}
public static double byteArrayToDouble(byte high[], byte low[])
{
double temp = 0;
// high bytes
temp += (((long)high[0]) & 0xFF) << 56;
temp += (((long)high[1]) & 0xFF) << 48;
temp += (((long)high[2]) & 0xFF) << 40;
temp += (((long)high[3]) & 0xFF) << 32;
// low bytes
temp += (((long)low[0]) & 0xFF) << 24;
temp += (((long)low[1]) & 0xFF) << 16;
temp += (((long)low[2]) & 0xFF) << 8;
temp += (((long)low[3]) & 0xFF);
return temp;
}
public static double byteArrayToDouble(byte value[])
{
byte high[] = new byte[4];
byte low[] = new byte[4];
high[0] = value[0];
high[1] = value[1];
high[2] = value[2];
high[3] = value[3];
low[0] = value[4];
low[1] = value[5];
low[2] = value[6];
low[3] = value[7];
return byteArrayToDouble(high,low);
}
public static float byteArrayToFloat(byte value[])
{
float temp = 0;
temp += (((int)value[0]) & 0xFF) << 24;
temp += (((int)value[1]) & 0xFF) << 16;
temp += (((int)value[2]) & 0xFF) << 8;
temp += (((int)value[3]) & 0xFF);
return temp;
}
public static int byteArrayToInt(byte value[])
{
int temp = 0;
temp += (((int)value[0]) & 0xFF) << 24;
temp += (((int)value[1]) & 0xFF) << 16;
temp += (((int)value[2]) & 0xFF) << 8;
temp += (((int)value[3]) & 0xFF);
return temp;
}
public static long byteArrayToLong(byte value[])
{
byte high[] = new byte[4];
byte low[] = new byte[4];
high[0] = value[0];
high[1] = value[1];
high[2] = value[2];
high[3] = value[3];
low[0] = value[4];
low[1] = value[5];
low[2] = value[6];
low[3] = value[7];
return byteArrayToLong(high,low);
}
public static long byteArrayToLong(byte high[], byte low[])
{
long temp = 0;
// high bytes
temp += (((long)high[0]) & 0xFF) << 56;
temp += (((long)high[1]) & 0xFF) << 48;
temp += (((long)high[2]) & 0xFF) << 40;
temp += (((long)high[3]) & 0xFF) << 32;
// low bytes
temp += (((long)low[0]) & 0xFF) << 24;
temp += (((long)low[1]) & 0xFF) << 16;
temp += (((long)low[2]) & 0xFF) << 8;
temp += (((long)low[3]) & 0xFF);
return temp;
}
// make the following loops with check on array length *****************
public static short byteArrayToShort(byte value[])
{
short temp = 0;
temp += (((int)value[0]) & 0xFF) << 8;
temp += (((int)value[1]) & 0xFF);
return temp;
}
public static String byteToHexString(byte value)
{
String temp = null;
switch( (value & 0xF0) >> 4 )
{
case 0:
temp = "0";
break;
case 1:
temp = "1";
break;
case 2:
temp = "2";
break;
case 3:
temp = "3";
break;
case 4:
temp = "4";
break;
case 5:
temp = "5";
break;
case 6:
temp = "6";
break;
case 7:
temp = "7";
break;
case 8:
temp = "8";
break;
case 9:
temp = "9";
break;
case 10:
temp = "A";
break;
case 11:
temp = "B";
break;
case 12:
temp = "C";
break;
case 13:
temp = "D";
break;
case 14:
temp = "E";
break;
case 15:
temp = "F";
break;
}
switch( (value & 0x0F) )
{
case 0:
temp += "0";
break;
case 1:
temp += "1";
break;
case 2:
temp += "2";
break;
case 3:
temp += "3";
break;
case 4:
temp += "4";
break;
case 5:
temp += "5";
break;
case 6:
temp += "6";
break;
case 7:
temp += "7";
break;
case 8:
temp += "8";
break;
case 9:
temp += "9";
break;
case 10:
temp += "A";
break;
case 11:
temp += "B";
break;
case 12:
temp += "C";
break;
case 13:
temp += "D";
break;
case 14:
temp += "E";
break;
case 15:
temp += "F";
break;
}
return temp;
}
}

View File

@ -0,0 +1,105 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.generator;
/**
* Bytecode handling utilities
*
* Handle standard byte arrays as defined in Java VM and Class File
*
* 5 April 1999 - functions to append Class File byte subarrays
* into a Class File byte array
*
* @author Richard F. Boehme
*
*/
public class Bytecode
{
// Constant Pool Item Codes
public static final byte C_Utf8 = 0x01; // 1
public static final byte C_Integer = 0x03; // 3
public static final byte C_Float = 0x04; // 4
public static final byte C_Long = 0x05; // 5
public static final byte C_Double = 0x06; // 6
public static final byte C_Class = 0x07; // 7
public static final byte C_String = 0x08; // 8
public static final byte C_FieldRef = 0x09; // 9
public static final byte C_MethodRef = 0x0A; // 10
public static final byte C_InterfaceMethodRef = 0x0B; // 11
public static final byte C_NameAndType = 0x0C; // 12
//public static byte[] addDouble(byte[] array,double value)
//{
// array = ByteUtility.addBytes(array,C_Double);
// array = ByteUtility.addBytes(array,value);
// return array;
//}
public static byte[] addClass(byte[] array,short value)
{ return addRef(C_Class,array,value); }
public static byte[] addFieldRef(byte[] array,short value1,short value2)
{ return addRef(C_FieldRef,array,value1,value2); }
public static byte[] addInteger(byte[] array,int value)
{
array = ByteUtility.addBytes(array,C_Integer);
array = ByteUtility.addBytes(array,value);
return array;
}
public static byte[] addInterfaceMethodRef(byte[] array,short value1,short value2)
{ return addRef(C_InterfaceMethodRef,array,value1,value2); }
//public static byte[] addFloat(byte[] array,float value)
//{
// array = ByteUtility.addBytes(array,C_Float);
// array = ByteUtility.addBytes(array,value);
// return array;
//}
public static byte[] addLong(byte[] array,long value)
{
array = ByteUtility.addBytes(array,C_Long);
array = ByteUtility.addBytes(array,value);
return array;
}
public static byte[] addMethodRef(byte[] array,short value1,short value2)
{ return addRef(C_MethodRef,array,value1,value2); }
public static byte[] addNameAndType(byte[] array,short value1,short value2)
{ return addRef(C_NameAndType,array,value1,value2); }
public static byte[] addRef(byte refType,byte[] array,short value)
{
array = ByteUtility.addBytes(array,refType);
array = ByteUtility.addBytes(array,value);
return array;
}
// Generic Bytecode Methods
public static byte[] addRef(byte refType,byte[] array,short value1,short value2)
{
array = ByteUtility.addBytes(array,refType);
array = ByteUtility.addBytes(array,value1);
array = ByteUtility.addBytes(array,value2);
return array;
}
public static byte[] addString(byte[] array,short value)
{ return addRef(C_String,array,value); }
// Constant Pool Item Methods
public static byte[] addUtf8(byte[] array,String value)
{
array = ByteUtility.addBytes(array,C_Utf8);
array = ByteUtility.addBytes(array,(short)value.length());
array = ByteUtility.addBytes(array,value);
return array;
}
}

View File

@ -0,0 +1,568 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.event.generator;
import java.io.FileOutputStream;
import java.io.IOException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/** EventAdapterGenerator
*
* Generate an "Event Adapter" dynamically during program execution
*
**/
public class EventAdapterGenerator
{
public static AdapterClassLoader ldr = new AdapterClassLoader();
static Class EVENTLISTENER = null;
static String CLASSPACKAGE = "org/apache/bsf/util/event/adapters/";
static String WRITEDIRECTORY = null;
// starting 8 bytes of all Java Class files
static byte CLASSHEADER[];
// constant pool items found in all event adapters
static short BASECPCOUNT; // number of cp items + 1 ( cp item # 0 reserved for JVM )
static byte BASECP[]; //
// some bytes in the middle of the class file (see below)
static byte FIXEDCLASSBYTES[];
// the initialization method, noargs constructor
static byte INITMETHOD[];
private static Log logger;
/* The static initializer */
static
{
logger = LogFactory.getLog(
(com.volmit.iris.util.bsf.util.event.generator.EventAdapterGenerator.class).getName());
String USERCLASSPACKAGE = System.getProperty("DynamicEventClassPackage",
"");
if (!USERCLASSPACKAGE.equals(""))
{
CLASSPACKAGE = USERCLASSPACKAGE;
}
if(CLASSPACKAGE.length() > 0 )
{
CLASSPACKAGE = CLASSPACKAGE.replace('\\','/');
if(!CLASSPACKAGE.endsWith("/"))
{ CLASSPACKAGE = CLASSPACKAGE+"/"; }
}
WRITEDIRECTORY = System.getProperty("DynamicEventClassWriteDirectory",CLASSPACKAGE);
if(WRITEDIRECTORY.length() > 0 )
{
WRITEDIRECTORY = WRITEDIRECTORY.replace('\\','/');
if(!WRITEDIRECTORY.endsWith("/"))
{ WRITEDIRECTORY = WRITEDIRECTORY+"/"; }
}
try
// { EVENTLISTENER = Class.forName("java.util.EventListener"); }
{ EVENTLISTENER = Thread.currentThread().getContextClassLoader().loadClass ("java.util.EventListener"); } // rgf, 2006-01-05
catch(ClassNotFoundException ex)
{
System.err.println(ex.getMessage());
ex.printStackTrace();
}
// start of the Java Class File
CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xCA); // magic
CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xFE); // magic
CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xBA); // magic
CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(byte)0xBE); // magic
CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(short)3); // minor version
CLASSHEADER = ByteUtility.addBytes(CLASSHEADER,(short)45); // major version
// Start the constant pool for base items in all event adapter classes
BASECPCOUNT = 17; // number of cp items + 1 ( cp item # 0 reserved for JVM )
// cp item 01
BASECP = Bytecode.addUtf8(BASECP,"()V");
// cp item 02
BASECP = Bytecode.addUtf8(BASECP,"<init>");
// cp item 03
BASECP = Bytecode.addUtf8(BASECP,"Code");
// cp item 04
BASECP = Bytecode.addUtf8(BASECP,"eventProcessor");
// cp item 05
BASECP = Bytecode.addUtf8(BASECP,"java/lang/Object");
// cp item 06
BASECP = Bytecode.addUtf8(BASECP,"org/apache/bsf/util/event/EventAdapterImpl");
// cp item 07
BASECP = Bytecode.addUtf8(BASECP,"org/apache/bsf/util/event/EventProcessor");
// cp item 08
BASECP = Bytecode.addUtf8(BASECP,"(Ljava/lang/String;[Ljava/lang/Object;)V");
// cp item 09
BASECP = Bytecode.addUtf8(BASECP,"Lorg/apache/bsf/util/event/EventProcessor;");
// cp item 10
BASECP = Bytecode.addClass(BASECP,(short)5); // Class "java/lang/Object"
// cp item 11
BASECP = Bytecode.addClass(BASECP,(short)6); // Class "org/apache/bsf/util/event/EventAdapterImpl"
// cp item 12
BASECP = Bytecode.addClass(BASECP,(short)7); // Class "org/apache/bsf/util/event/EventProcessor"
// cp item 13
BASECP = Bytecode.addNameAndType(BASECP,(short)2,(short)1); // "<init>" "()V"
// cp item 14
BASECP = Bytecode.addNameAndType(BASECP,(short)4,(short)9); // "eventProcessor" "Lorg/apache/bsf/util/event/EventProcessor;"
// cp item 15
BASECP = Bytecode.addFieldRef(BASECP,(short)11,(short)14);
// cp item 16
BASECP = Bytecode.addMethodRef(BASECP,(short)11,(short)13);
// fixed bytes in middle of class file
FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)0x21); // access_flags (fixed)
FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)20); // this_class (fixed)
FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)11); // super_class (fixed)
FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)1); // interface_count (fixed)
FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)19); // interfaces (fixed)
FIXEDCLASSBYTES = ByteUtility.addBytes(FIXEDCLASSBYTES,(short)0); // field_count (fixed)
// initialization method, constructor
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); // access_flags
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)2); // name_index "<init>"
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); // descriptor_index "()V"
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); // attribute_count
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)3); // attribute_name_index "Code"
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(long)17); // attribute_length
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); // max_stack
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)1); // max_locals
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(long)5); // code_length
//code
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(byte)0x2A); // aload_0
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(byte)0xB7); // invokespecial
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)16); // method_ref index
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(byte)0xB1); // return
// exception table
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)0); // exception_table_length
INITMETHOD = ByteUtility.addBytes(INITMETHOD,(short)0); // attributes_count
}
/* methods that take an EventListener Class Type to create an EventAdapterClass */
public static Class makeEventAdapterClass(Class listenerType,boolean writeClassFile)
{
logger.info("EventAdapterGenerator");
if( EVENTLISTENER.isAssignableFrom(listenerType) )
{
boolean exceptionable = false;
boolean nonExceptionable = false;
byte constantPool[] = null;
short cpBaseIndex;
short cpCount = 0;
short cpExceptionBaseIndex;
short exceptionableCount;
short nonExceptionableCount;
/* Derive Names */
String listenerTypeName = listenerType.getName();
logger.info("ListenerTypeName: "+listenerTypeName);
String adapterClassName =
CLASSPACKAGE+
(listenerTypeName.endsWith("Listener")
? listenerTypeName.substring(0, listenerTypeName.length() - 8)
: listenerTypeName).replace('.', '_') +
"Adapter";
String finalAdapterClassName = adapterClassName;
Class cached = null;
int suffixIndex = 0;
do
{
if (null != (cached = ldr.getLoadedClass(finalAdapterClassName)))
{
logger.info("cached: "+cached);
try
{
if (!listenerType.isAssignableFrom(cached))
finalAdapterClassName = adapterClassName + "_" + suffixIndex++;
else
return cached;
}
catch(VerifyError ex)
{
System.err.println(ex.getMessage());
ex.printStackTrace();
return cached;
}
}
}
while (cached != null);
String eventListenerName = listenerTypeName.replace('.', '/');
/* method stuff */
java.lang.reflect.Method lms[] = listenerType.getMethods();
/* ****************************************************************************************** */
// Listener interface
// Class name
cpCount += 4;
// cp item 17
constantPool = Bytecode.addUtf8(constantPool,eventListenerName);
// cp item 18
constantPool = Bytecode.addUtf8(constantPool,finalAdapterClassName);
// cp item 19
constantPool = Bytecode.addClass(constantPool,(short)17);
// cp item 20
constantPool = Bytecode.addClass(constantPool,(short)18);
// do we have nonExceptionalble event, exceptionable or both
for (int i = 0 ; i < lms.length ; ++i)
{
Class exceptionTypes[] = lms[i].getExceptionTypes();
if( 0 < exceptionTypes.length)
{ exceptionable = true; }
else
{ nonExceptionable = true; }
}/* End for*/
/* ****************************************************************************************** */
// optional inclusion of nonexceptional events affects exceptional events indices
nonExceptionableCount = 0;
if(nonExceptionable)
{
nonExceptionableCount = 3;
cpCount += nonExceptionableCount;
// cp item 21
constantPool = Bytecode.addUtf8(constantPool,"processEvent");
// cp item 22
constantPool = Bytecode.addNameAndType(constantPool,(short)21,(short)8);
// cp item 23
constantPool = Bytecode.addInterfaceMethodRef(constantPool,(short)12,(short)22);
}
/* ****************************************************************************************** */
// optional inclusion of exceptional events affects CP Items which follow for specific methods
exceptionableCount = 0;
if(exceptionable)
{
int classIndex = BASECPCOUNT + cpCount + 1;
int nameIndex = BASECPCOUNT + cpCount + 0;
int natIndex = BASECPCOUNT + cpCount + 3;
exceptionableCount = 5;
cpCount += exceptionableCount;
// cp item 24 or 21
constantPool = Bytecode.addUtf8(constantPool,"processExceptionableEvent");
// cp item 25 or 22
constantPool = Bytecode.addUtf8(constantPool,"java/lang/Exception");
// cp item 26 or 23
constantPool = Bytecode.addClass(constantPool,(short)classIndex);
// cp item 27 or 24
constantPool = Bytecode.addNameAndType(constantPool,(short)nameIndex,(short)8);
// cp item 28 or 25
constantPool = Bytecode.addInterfaceMethodRef(constantPool,(short)12,(short)natIndex);
}
// base index for method cp references
cpBaseIndex = (short)(BASECPCOUNT + cpCount);
logger.debug("cpBaseIndex: " + cpBaseIndex);
for (int i = 0 ; i < lms.length ; ++i)
{
String eventMethodName = lms[i].getName();
String eventName = lms[i].getParameterTypes()[0].getName().replace('.','/');
cpCount += 3;
// cp items for event methods
constantPool = Bytecode.addUtf8(constantPool,eventMethodName);
constantPool = Bytecode.addUtf8(constantPool,("(L" + eventName + ";)V"));
constantPool = Bytecode.addString(constantPool,(short)(BASECPCOUNT+cpCount-3));
}/* End for*/
boolean propertyChangeFlag[] = new boolean[lms.length];
int cpIndexPCE = 0;
for (int i = 0 ; i < lms.length ; ++i)
{
String eventName = lms[i].getParameterTypes()[0].getName().replace('.','/');
// cp items for PropertyChangeEvent special handling
if(eventName.equalsIgnoreCase("java/beans/PropertyChangeEvent"))
{
propertyChangeFlag[i] = true;
if( 0 == cpIndexPCE )
{
constantPool = Bytecode.addUtf8(constantPool,eventName);
constantPool = Bytecode.addUtf8(constantPool,"getPropertyName");
constantPool = Bytecode.addUtf8(constantPool,"()Ljava/lang/String;");
constantPool = Bytecode.addClass(constantPool,(short)(BASECPCOUNT + cpCount));
constantPool = Bytecode.addNameAndType(constantPool,
(short)(BASECPCOUNT + cpCount + 1),
(short)(BASECPCOUNT + cpCount + 2));
constantPool = Bytecode.addMethodRef(constantPool,
(short)(BASECPCOUNT + cpCount + 3),
(short)(BASECPCOUNT + cpCount + 4));
cpCount += 6;
cpIndexPCE = BASECPCOUNT + cpCount - 1;
}
}
else
{ propertyChangeFlag[i] = false; }
}/* End for*/
cpExceptionBaseIndex = (short)(BASECPCOUNT + cpCount);
logger.debug("cpExceptionBaseIndex: " + cpExceptionBaseIndex);
int excpIndex[][] = new int[lms.length][];
for (int i = 0 ; i < lms.length ; ++i)
{
Class exceptionTypes[] = lms[i].getExceptionTypes();
excpIndex[i] = new int[exceptionTypes.length];
for ( int j = 0 ; j < exceptionTypes.length ; j++)
{
constantPool = Bytecode.addUtf8(constantPool,exceptionTypes[j].getName().replace('.', '/'));
constantPool = Bytecode.addClass(constantPool,(short)(BASECPCOUNT+cpCount));
excpIndex[i][j] = BASECPCOUNT + cpCount + 1;
cpCount += 2;
}
}/* End for*/
/* end constant pool */
/* ************************************************************************************************ */
// put the Class byte array together
/* start */
byte newClass[] = CLASSHEADER; // magic, version (fixed)
short count = (short)(BASECPCOUNT + cpCount);
newClass = ByteUtility.addBytes(newClass,count); // constant_pool_count (variable)
newClass = ByteUtility.addBytes(newClass,BASECP); // constant_pool (fixed)
newClass = ByteUtility.addBytes(newClass,constantPool); // constant_pool (variable)
newClass = ByteUtility.addBytes(newClass,FIXEDCLASSBYTES); // see FIXEDCLASSBYTES (fixed)
newClass = ByteUtility.addBytes(newClass,(short)(lms.length+1)); // method_count (variable)
newClass = ByteUtility.addBytes(newClass,INITMETHOD); // constructor <init> (fixed)
// methods
/* ****************************************************************************************** */
/* loop over listener methods from listenerType */
for (int i = 0 ; i < lms.length ; ++i)
{
newClass = ByteUtility.addBytes(newClass,(short)1); // access_flags (fixed)
newClass = ByteUtility.addBytes(newClass,(short)(cpBaseIndex+3*i+0)); // name_index (variable)
newClass = ByteUtility.addBytes(newClass,(short)(cpBaseIndex+3*i+1)); // descriptor_index (variable)
newClass = ByteUtility.addBytes(newClass,(short)1); // attribute_count (fixed)
newClass = ByteUtility.addBytes(newClass,(short)3); // attribute_name_index code(fixed)
// Code Attribute Length
int length = 32;
if( 0 < excpIndex[i].length )
{ length += 5 + 8 * ( 1 + excpIndex[i].length ); }
if(propertyChangeFlag[i])
{ length += 2; }
newClass = ByteUtility.addBytes(newClass,(long)length); // attribute_length (variable)
// start code attribute
newClass = ByteUtility.addBytes(newClass,(short)6); // max_stack (fixed)
newClass = ByteUtility.addBytes(newClass,(short)3); // max_locals (fixed)
// Code Length
length = 20;
if(exceptionable && 0 < excpIndex[i].length)
{ length += 5; }
if(propertyChangeFlag[i])
{ length += 2; }
newClass = ByteUtility.addBytes(newClass,(long)length); // code_length (variable)
// start code
newClass = ByteUtility.addBytes(newClass,(byte)0x2A); // aload_0 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xB4); // getfield (fixed)
newClass = ByteUtility.addBytes(newClass,(short)15); // index (fixed)
if(propertyChangeFlag[i])
{ // the propertyName is passed as the first parameter
newClass = ByteUtility.addBytes(newClass,(byte)0x2B); // aload_1 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xB6); // invokevirtual (fixed)
newClass = ByteUtility.addBytes(newClass,(short)cpIndexPCE); // methodref (variable)
}
else
{ // the eventMethodName is passed as the first parameter
// Target for method invocation.
newClass = ByteUtility.addBytes(newClass,(byte)0x12); // ldc (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)(cpBaseIndex+3*i+2)); // index (byte) (variable)
}
newClass = ByteUtility.addBytes(newClass,(byte)0x04); // iconst_1 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xBD); // anewarray (fixed)
newClass = ByteUtility.addBytes(newClass,(short)10); // Class java/lang/Object (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x59); // dup (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x03); // iconst_0 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x2B); // aload_1 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x53); // aastore (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xB9); // invokeinterface (fixed)
// index to processEvent or processExceptionableEvent method
length = 23; // actually an index into cp
if(exceptionable && nonExceptionable)
{ // interface method index
if( 0 < lms[i].getExceptionTypes().length )
{ length += 5; }
}
else if(exceptionable)
{ length += 2; }
newClass = ByteUtility.addBytes(newClass,(short)length); // index (process??????...) (variable)
newClass = ByteUtility.addBytes(newClass,(byte)0x03); // iconst_0 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x00); // noop (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xB1); // return (fixed)
if(exceptionable && 0 < excpIndex[i].length)
{ // exception code
newClass = ByteUtility.addBytes(newClass,(byte)0x4D); // astore_2 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x2C); // aload_2 (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xBF); // athrow (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0x57); // pop (fixed)
newClass = ByteUtility.addBytes(newClass,(byte)0xB1); // return (fixed)
// end code
// exception table
length = excpIndex[i].length;
newClass = ByteUtility.addBytes(newClass,(short)(1+length)); // exception_table_length (variable)
for( int j = 0 ; j < length ; j++ )
{ // catch exception types and rethrow
newClass = ByteUtility.addBytes(newClass,(short)0); // start_pc (fixed)
if(propertyChangeFlag[i])
{
newClass = ByteUtility.addBytes(newClass,(short)21); // end_pc (fixed)
newClass = ByteUtility.addBytes(newClass,(short)22); // handler_pc (fixed)
}
else
{
newClass = ByteUtility.addBytes(newClass,(short)19); // end_pc (fixed)
newClass = ByteUtility.addBytes(newClass,(short)20); // handler_pc (fixed)
}
newClass = ByteUtility.addBytes(newClass,(short)excpIndex[i][j]); // catch_type (variable)
}
// catch "exception" and trap it
newClass = ByteUtility.addBytes(newClass,(short)0); // start_pc (fixed)
if(propertyChangeFlag[i])
{
newClass = ByteUtility.addBytes(newClass,(short)21); // end_pc (fixed)
newClass = ByteUtility.addBytes(newClass,(short)25); // handler_pc (fixed)
}
else
{
newClass = ByteUtility.addBytes(newClass,(short)19); // end_pc (fixed)
newClass = ByteUtility.addBytes(newClass,(short)23); // handler_pc (fixed)
}
if(nonExceptionable)
{ newClass = ByteUtility.addBytes(newClass,(short)26); } // catch_type (fixed)
else // or
{ newClass = ByteUtility.addBytes(newClass,(short)23); } // catch_type (fixed)
}
else
{ newClass = ByteUtility.addBytes(newClass,(short)0); } // exception_table_length (fixed)
// attributes on the code attribute (none)
newClass = ByteUtility.addBytes(newClass,(short)0); // attribute_count (fixed)
// end code attribute
}/* End for*/
// Class Attributes (none for this)
newClass = ByteUtility.addBytes(newClass,(short)0); // attribute_count (fixed)
/* done */
logger.debug("adapterName: " + finalAdapterClassName);
logger.debug("cpCount: " + count + " = " + BASECPCOUNT + " + " + cpCount);
logger.debug("methodCount: " + (lms.length+1));
// output to disk class file
/* ****************************************************************************************** */
// now create the class and load it
// return the Class.
if (writeClassFile)
{
try
{
// removed "WRITEDIRECTORY+", as this path is already part of 'finalAdapterClassName'
FileOutputStream fos = new FileOutputStream(finalAdapterClassName+".class");
fos.write(newClass);
fos.close();
}
catch(IOException ex)
{
System.err.println(ex.getMessage());
ex.printStackTrace();
}
try
{
Class ret = ldr.loadClass(finalAdapterClassName);
logger.debug("EventAdapterGenerator: " +
ret.getName() +
" dynamically generated");
return ret;
}
catch (ClassNotFoundException ex)
{
System.err.println(ex.getMessage());
ex.printStackTrace();
}
}
try
{
Class ret = ldr.defineClass(finalAdapterClassName,newClass);
logger.debug("EventAdapterGenerator: " +
ret.getName() +
" dynamically generated");
return ret;
}
catch(Exception ex)
{
System.err.println(ex.getMessage());
ex.printStackTrace();
}
}
return null;
}
}

View File

@ -0,0 +1,31 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.type;
/**
* A <em>TypeConvertor</em> is used to convert an object of one type to
* one of another type. The convertor is invoked with the class of the
* from object, the desired class, and the from object itself. The
* convertor must return a new object of the desired class.
*
* @author Sanjiva Weerawarana
* @see TypeConvertorRegistry
*/
public interface TypeConvertor {
public Object convert (Class from, Class to, Object obj);
public String getCodeGenString ();
}

View File

@ -0,0 +1,206 @@
/*
* Copyright 2004,2004 The Apache Software Foundation.
*
* Licensed 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 com.volmit.iris.util.bsf.util.type;
import java.awt.Color;
import java.awt.Font;
import java.util.Hashtable;
/**
* The <em>TypeConvertorRegistry</em> is the registry of type convertors.
* It has lookup and register capabilities based on the types to be
* converted as well as by some object key.
*
* @author Sanjiva Weerawarana
* @author Matthew J. Duftler
* @see TypeConvertorRegistry
*/
public class TypeConvertorRegistry {
Hashtable reg = new Hashtable ();
Hashtable keyedReg = new Hashtable ();
// register some standard convertors at construction time
public TypeConvertorRegistry () {
// no-op convertors: cvt from primitive wrappers to the object wrapper
TypeConvertor tc = new TypeConvertor () {
public Object convert (Class from, Class to, Object obj) {
return obj;
}
public String getCodeGenString() {
return "(Class from, Class to, Object obj) {\n" +
"return obj;\n" +
"}";
}
};
register (Boolean.class, boolean.class, tc);
register (boolean.class, Boolean.class, tc);
register (Byte.class, byte.class, tc);
register (byte.class, Byte.class, tc);
register (Character.class, char.class, tc);
register (char.class, Character.class, tc);
register (Short.class, short.class, tc);
register (short.class, Short.class, tc);
register (Integer.class, int.class, tc);
register (int.class, Integer.class, tc);
register (Long.class, long.class, tc);
register (long.class, Long.class, tc);
register (Float.class, float.class, tc);
register (float.class, Float.class, tc);
register (Double.class, double.class, tc);
register (double.class, Double.class, tc);
// object to string: the registry special cases this one as the backup
// if the target is string and there is no special convertor available
// otherwise
tc = new TypeConvertor () {
public Object convert (Class from, Class to, Object obj) {
return (obj == null) ? "(null)" : obj.toString ();
}
public String getCodeGenString() {
return "(Class from, Class to, Object obj) {\n" +
"return (obj == null) ? \"(null)\" : obj.toString ();\n" +
"}";
}
};
register (Object.class, String.class, tc);
// convert strings to various primitives (both their object versions
// and wrappers for primitive versions)
tc = new TypeConvertor () {
public Object convert (Class from, Class to, Object obj) {
String str = (String) obj;
if (to == Boolean.class || to == boolean.class) {
return Boolean.valueOf (str);
} else if (to == Byte.class || to == byte.class) {
return Byte.valueOf (str);
} else if (to == Character.class || to == char.class) {
return new Character (str.charAt (0));
} else if (to == Short.class || to == short.class) {
return Short.valueOf (str);
} else if (to == Integer.class || to == int.class) {
return Integer.valueOf (str);
} else if (to == Long.class || to == long.class) {
return Long.valueOf (str);
} else if (to == Float.class || to == float.class) {
return Float.valueOf (str);
} else if (to == Double.class || to == double.class) {
return Double.valueOf (str);
} else {
return null;
}
}
public String getCodeGenString() {
return "(Class from, Class to, Object obj) {\n" +
"String str = (String) obj;\n" +
"if (to == Boolean.class || to == boolean.class) {\n" +
"return Boolean.valueOf (str);\n" +
"} else if (to == Byte.class || to == byte.class) {\n" +
"return Byte.valueOf (str);\n" +
"} else if (to == Character.class || to == char.class) {\n" +
"return new Character (str.charAt (0));\n" +
"} else if (to == Short.class || to == short.class) {\n" +
"return Short.valueOf (str);\n" +
"} else if (to == Integer.class || to == int.class) {\n" +
"return Integer.valueOf (str);\n" +
"} else if (to == Long.class || to == long.class) {\n" +
"return Long.valueOf (str);\n" +
"} else if (to == Float.class || to == float.class) {\n" +
"return Float.valueOf (str);\n" +
"} else if (to == Double.class || to == double.class) {\n" +
"return Double.valueOf (str);\n" +
"} else {\n" +
"return null;\n" +
"}\n" +
"}";
}
};
register (String.class, boolean.class, tc);
register (String.class, Boolean.class, tc);
register (String.class, byte.class, tc);
register (String.class, Byte.class, tc);
register (String.class, char.class, tc);
register (String.class, Character.class, tc);
register (String.class, short.class, tc);
register (String.class, Short.class, tc);
register (String.class, int.class, tc);
register (String.class, Integer.class, tc);
register (String.class, long.class, tc);
register (String.class, Long.class, tc);
register (String.class, float.class, tc);
register (String.class, Float.class, tc);
register (String.class, double.class, tc);
register (String.class, Double.class, tc);
// strings to fonts
tc = new TypeConvertor () {
public Object convert (Class from, Class to, Object obj) {
return Font.decode ((String) obj);
}
public String getCodeGenString() {
return "(Class from, Class to, Object obj) {\n" +
"return Font.decode ((String) obj);\n" +
"}";
}
};
register (String.class, Font.class, tc);
// strings to colors
tc = new TypeConvertor () {
public Object convert (Class from, Class to, Object obj) {
return Color.decode ((String) obj);
}
public String getCodeGenString() {
return "(Class from, Class to, Object obj) {\n" +
"return Color.decode ((String) obj);\n" +
"}";
}
};
register (String.class, Color.class, tc);
}
// lookup a convertor
public TypeConvertor lookup (Class from, Class to) {
String key = from.getName () + " -> " + to.getName ();
TypeConvertor tc = (TypeConvertor) reg.get (key);
if (tc == null) {
if (from != void.class
&& from != Void.class
&& to == String.class) {
// find the object -> string convertor
return lookup (Object.class, String.class);
}
}
return tc;
}
// lookup a convertor by key
public TypeConvertor lookupByKey (Object key) {
return (TypeConvertor) keyedReg.get (key);
}
// register a convertor
public void register (Class from, Class to, TypeConvertor convertor) {
String key = from.getName () + " -> " + to.getName ();
reg.put (key, convertor);
}
// register a convertor by key
public void registerByKey (Object key, TypeConvertor convertor) {
keyedReg.put (key, convertor);
}
}