mirror of
https://github.com/VolmitSoftware/Iris.git
synced 2026-06-17 14:21:33 +00:00
Scripting engine
This commit is contained in:
+2
-2
@@ -145,6 +145,6 @@ dependencies {
|
|||||||
implementation 'com.google.code.gson:gson:2.8.7'
|
implementation 'com.google.code.gson:gson:2.8.7'
|
||||||
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'
|
||||||
|
implementation 'bsf:bsf:2.4.0'
|
||||||
|
implementation 'rhino:js:1.7R2'
|
||||||
}
|
}
|
||||||
@@ -29,6 +29,9 @@ public class CommandIrisStudio extends MortarCommand {
|
|||||||
@Command
|
@Command
|
||||||
private CommandIrisStudioCreate create;
|
private CommandIrisStudioCreate create;
|
||||||
|
|
||||||
|
@Command
|
||||||
|
private CommandIrisStudioExecute execute;
|
||||||
|
|
||||||
@Command
|
@Command
|
||||||
private CommandIrisStudioOpen open;
|
private CommandIrisStudioOpen open;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.command.studio;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.core.IrisSettings;
|
||||||
|
import com.volmit.iris.core.project.loader.IrisData;
|
||||||
|
import com.volmit.iris.core.tools.IrisToolbelt;
|
||||||
|
import com.volmit.iris.core.tools.IrisWorlds;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.framework.IrisAccess;
|
||||||
|
import com.volmit.iris.engine.object.common.IrisScript;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.plugin.MortarCommand;
|
||||||
|
import com.volmit.iris.util.plugin.VolmitSender;
|
||||||
|
|
||||||
|
public class CommandIrisStudioExecute extends MortarCommand {
|
||||||
|
public CommandIrisStudioExecute() {
|
||||||
|
super("execute", "ex");
|
||||||
|
requiresPermission(Iris.perm.studio);
|
||||||
|
setDescription("Execute a script");
|
||||||
|
setCategory("Studio");
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addTabOptions(VolmitSender sender, String[] args, KList<String> list) {
|
||||||
|
if ((args.length == 0 || args.length == 1) && sender.isPlayer() && IrisWorlds.isIrisWorld(sender.player().getWorld())) {
|
||||||
|
IrisData data = IrisWorlds.access(sender.player().getWorld()).getData();
|
||||||
|
if (data == null) {
|
||||||
|
sender.sendMessage("Tab complete options only work for summons while in an Iris world.");
|
||||||
|
} else if (args.length == 0) {
|
||||||
|
list.add(data.getScriptLoader().getPossibleKeys());
|
||||||
|
} else if (args.length == 1) {
|
||||||
|
list.add(data.getScriptLoader().getPossibleKeys(args[0]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean handle(VolmitSender sender, String[] args) {
|
||||||
|
if (!IrisSettings.get().isStudio()) {
|
||||||
|
sender.sendMessage("To use Iris Studio, please enable studio in Iris/settings.json");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
IrisAccess a = IrisToolbelt.access(sender.player().getWorld());
|
||||||
|
|
||||||
|
if(a != null)
|
||||||
|
{
|
||||||
|
((Engine)a.getEngineAccess(0)).getExecution().execute(args[0]);
|
||||||
|
Iris.info("Executed. See script output in console.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected String getArgsUsage() {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -22,6 +22,7 @@ import com.volmit.iris.Iris;
|
|||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.object.biome.IrisBiome;
|
import com.volmit.iris.engine.object.biome.IrisBiome;
|
||||||
import com.volmit.iris.engine.object.block.IrisBlockData;
|
import com.volmit.iris.engine.object.block.IrisBlockData;
|
||||||
|
import com.volmit.iris.engine.object.common.IrisScript;
|
||||||
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
||||||
import com.volmit.iris.engine.object.entity.IrisEntity;
|
import com.volmit.iris.engine.object.entity.IrisEntity;
|
||||||
import com.volmit.iris.engine.object.jigsaw.IrisJigsawPiece;
|
import com.volmit.iris.engine.object.jigsaw.IrisJigsawPiece;
|
||||||
@@ -58,6 +59,7 @@ public class IrisData {
|
|||||||
private ResourceLoader<IrisBlockData> blockLoader;
|
private ResourceLoader<IrisBlockData> blockLoader;
|
||||||
private ResourceLoader<IrisExpression> expressionLoader;
|
private ResourceLoader<IrisExpression> expressionLoader;
|
||||||
private ResourceLoader<IrisObject> objectLoader;
|
private ResourceLoader<IrisObject> objectLoader;
|
||||||
|
private ResourceLoader<IrisScript> scriptLoader;
|
||||||
private KMap<Class<? extends IrisRegistrant>, ResourceLoader<? extends IrisRegistrant>> loaders = new KMap<>();
|
private KMap<Class<? extends IrisRegistrant>, ResourceLoader<? extends IrisRegistrant>> loaders = new KMap<>();
|
||||||
private boolean closed;
|
private boolean closed;
|
||||||
private final File dataFolder;
|
private final File dataFolder;
|
||||||
@@ -96,7 +98,11 @@ public class IrisData {
|
|||||||
ResourceLoader<T> r = null;
|
ResourceLoader<T> r = null;
|
||||||
if (registrant.equals(IrisObject.class)) {
|
if (registrant.equals(IrisObject.class)) {
|
||||||
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
r = (ResourceLoader<T>) new ObjectResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
||||||
} else {
|
}
|
||||||
|
else if (registrant.equals(IrisScript.class)) {
|
||||||
|
r = (ResourceLoader<T>) new ScriptResourceLoader(dataFolder, this, rr.getFolderName(), rr.getTypeName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
r = new ResourceLoader<T>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
r = new ResourceLoader<T>(dataFolder, this, rr.getFolderName(), rr.getTypeName(), registrant);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,6 +139,7 @@ public class IrisData {
|
|||||||
this.blockLoader = registerLoader(IrisBlockData.class);
|
this.blockLoader = registerLoader(IrisBlockData.class);
|
||||||
this.expressionLoader = registerLoader(IrisExpression.class);
|
this.expressionLoader = registerLoader(IrisExpression.class);
|
||||||
this.objectLoader = registerLoader(IrisObject.class);
|
this.objectLoader = registerLoader(IrisObject.class);
|
||||||
|
this.scriptLoader = registerLoader(IrisScript.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void dump() {
|
public void dump() {
|
||||||
@@ -195,6 +202,10 @@ public class IrisData {
|
|||||||
return loadAny(key, (dm) -> dm.getSpawnerLoader().load(key, false));
|
return loadAny(key, (dm) -> dm.getSpawnerLoader().load(key, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static IrisScript loadAnyScript(String key) {
|
||||||
|
return loadAny(key, (dm) -> dm.getScriptLoader().load(key, false));
|
||||||
|
}
|
||||||
|
|
||||||
public static IrisRegion loadAnyRegion(String key) {
|
public static IrisRegion loadAnyRegion(String key) {
|
||||||
return loadAny(key, (dm) -> dm.getRegionLoader().load(key, false));
|
return loadAny(key, (dm) -> dm.getRegionLoader().load(key, false));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
* 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.core.project.loader;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
|
import com.volmit.iris.engine.object.common.IrisScript;
|
||||||
|
import com.volmit.iris.engine.object.objects.IrisObject;
|
||||||
|
import com.volmit.iris.util.collection.KList;
|
||||||
|
import com.volmit.iris.util.collection.KMap;
|
||||||
|
import com.volmit.iris.util.collection.KSet;
|
||||||
|
import com.volmit.iris.util.format.C;
|
||||||
|
import com.volmit.iris.util.format.Form;
|
||||||
|
import com.volmit.iris.util.io.IO;
|
||||||
|
import com.volmit.iris.util.math.M;
|
||||||
|
import com.volmit.iris.util.scheduling.ChronoLatch;
|
||||||
|
import com.volmit.iris.util.scheduling.J;
|
||||||
|
import com.volmit.iris.util.scheduling.PrecisionStopwatch;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
|
||||||
|
public class ScriptResourceLoader extends ResourceLoader<IrisScript> {
|
||||||
|
|
||||||
|
public ScriptResourceLoader(File root, IrisData idm, String folderName, String resourceTypeName) {
|
||||||
|
super(root, idm, folderName, resourceTypeName, IrisScript.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean supportsSchemas() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return loadCache.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisScript loadFile(File j, String key, String name) {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
PrecisionStopwatch p = PrecisionStopwatch.start();
|
||||||
|
IrisScript t = new IrisScript(IO.readAll(j));
|
||||||
|
loadCache.put(key, t);
|
||||||
|
t.setLoadKey(name);
|
||||||
|
t.setLoader(manager);
|
||||||
|
t.setLoadFile(j);
|
||||||
|
logLoad(j, t);
|
||||||
|
lock.unlock();
|
||||||
|
tlt.addAndGet(p.getMilliseconds());
|
||||||
|
return t;
|
||||||
|
} catch (Throwable e) {
|
||||||
|
Iris.reportError(e);
|
||||||
|
lock.unlock();
|
||||||
|
Iris.warn("Couldn't read " + resourceTypeName + " file: " + j.getPath() + ": " + e.getMessage());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String[] getPossibleKeys() {
|
||||||
|
if (possibleKeys != null) {
|
||||||
|
return possibleKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
Iris.debug("Building " + resourceTypeName + " Possibility Lists");
|
||||||
|
KSet<String> m = new KSet<>();
|
||||||
|
|
||||||
|
for (File i : getFolders()) {
|
||||||
|
for (File j : i.listFiles()) {
|
||||||
|
if (j.isFile() && j.getName().endsWith(".js")) {
|
||||||
|
m.add(j.getName().replaceAll("\\Q.iob\\E", ""));
|
||||||
|
} else if (j.isDirectory()) {
|
||||||
|
for (File k : j.listFiles()) {
|
||||||
|
if (k.isFile() && k.getName().endsWith(".js")) {
|
||||||
|
m.add(j.getName() + "/" + k.getName().replaceAll("\\Q.iob\\E", ""));
|
||||||
|
} else if (k.isDirectory()) {
|
||||||
|
for (File l : k.listFiles()) {
|
||||||
|
if (l.isFile() && l.getName().endsWith(".js")) {
|
||||||
|
m.add(j.getName() + "/" + k.getName() + "/" + l.getName().replaceAll("\\Q.iob\\E", ""));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
KList<String> v = new KList<>(m);
|
||||||
|
possibleKeys = v.toArray(new String[0]);
|
||||||
|
return possibleKeys;
|
||||||
|
}
|
||||||
|
|
||||||
|
public File findFile(String name) {
|
||||||
|
lock.lock();
|
||||||
|
for (File i : getFolders(name)) {
|
||||||
|
for (File j : i.listFiles()) {
|
||||||
|
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
|
lock.unlock();
|
||||||
|
return j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(i, name + ".js");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
lock.unlock();
|
||||||
|
return file;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisScript load(String name, boolean warn) {
|
||||||
|
String key = name + "-" + objectClass.getCanonicalName();
|
||||||
|
|
||||||
|
if (loadCache.containsKey(key)) {
|
||||||
|
IrisScript t = loadCache.get(key);
|
||||||
|
return t;
|
||||||
|
}
|
||||||
|
|
||||||
|
lock.lock();
|
||||||
|
for (File i : getFolders(name)) {
|
||||||
|
for (File j : i.listFiles()) {
|
||||||
|
if (j.isFile() && j.getName().endsWith(".js") && j.getName().split("\\Q.\\E")[0].equals(name)) {
|
||||||
|
lock.unlock();
|
||||||
|
return loadFile(j, key, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
File file = new File(i, name + ".js");
|
||||||
|
|
||||||
|
if (file.exists()) {
|
||||||
|
lock.unlock();
|
||||||
|
return loadFile(file, key, name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Iris.warn("Couldn't find " + resourceTypeName + ": " + name);
|
||||||
|
|
||||||
|
lock.unlock();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import com.volmit.iris.engine.object.biome.IrisBiomePaletteLayer;
|
|||||||
import com.volmit.iris.engine.object.decoration.IrisDecorator;
|
import com.volmit.iris.engine.object.decoration.IrisDecorator;
|
||||||
import com.volmit.iris.engine.object.engine.IrisEngineData;
|
import com.volmit.iris.engine.object.engine.IrisEngineData;
|
||||||
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
|
import com.volmit.iris.engine.object.objects.IrisObjectPlacement;
|
||||||
|
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
||||||
import com.volmit.iris.util.context.IrisContext;
|
import com.volmit.iris.util.context.IrisContext;
|
||||||
import com.volmit.iris.util.documentation.BlockCoordinates;
|
import com.volmit.iris.util.documentation.BlockCoordinates;
|
||||||
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
import com.volmit.iris.util.documentation.ChunkCoordinates;
|
||||||
@@ -64,6 +65,9 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
|||||||
@Getter
|
@Getter
|
||||||
private final EngineEffects effects;
|
private final EngineEffects effects;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
private final EngineExecutionEnvironment execution;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final EngineWorldManager worldManager;
|
private final EngineWorldManager worldManager;
|
||||||
|
|
||||||
@@ -116,10 +120,13 @@ public class IrisEngine extends BlockPopulator implements Engine {
|
|||||||
Iris.callEvent(new IrisEngineHotloadEvent(this));
|
Iris.callEvent(new IrisEngineHotloadEvent(this));
|
||||||
context = new IrisContext(this);
|
context = new IrisContext(this);
|
||||||
context.touch();
|
context.touch();
|
||||||
|
execution = new IrisExecutionEnvironment(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public IrisEngineData getEngineData() {
|
public IrisEngineData getEngineData() {
|
||||||
|
World w = null;
|
||||||
|
|
||||||
return engineData.aquire(() -> {
|
return engineData.aquire(() -> {
|
||||||
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + "-" + getIndex() + ".json");
|
File f = new File(getWorld().worldFolder(), "iris/engine-data/" + getDimension().getLoadKey() + "-" + getIndex() + ".json");
|
||||||
|
|
||||||
|
|||||||
@@ -18,16 +18,70 @@
|
|||||||
|
|
||||||
package com.volmit.iris.engine;
|
package com.volmit.iris.engine;
|
||||||
|
|
||||||
|
import com.volmit.iris.Iris;
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
||||||
|
import com.volmit.iris.engine.scripting.IrisScriptingAPI;
|
||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
|
import org.apache.bsf.BSFEngine;
|
||||||
|
import org.apache.bsf.BSFException;
|
||||||
|
import org.apache.bsf.BSFManager;
|
||||||
|
import org.apache.bsf.engines.javascript.JavaScriptEngine;
|
||||||
|
|
||||||
@Data
|
@Data
|
||||||
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
|
public class IrisExecutionEnvironment implements EngineExecutionEnvironment {
|
||||||
|
private final BSFManager manager;
|
||||||
private final Engine engine;
|
private final Engine engine;
|
||||||
|
private final IrisScriptingAPI api;
|
||||||
|
private JavaScriptEngine javaScriptEngine;
|
||||||
|
|
||||||
IrisExecutionEnvironment(Engine engine)
|
public IrisExecutionEnvironment(Engine engine)
|
||||||
{
|
{
|
||||||
this.engine = engine;
|
this.engine = engine;
|
||||||
|
this.api = new IrisScriptingAPI(engine);
|
||||||
|
this.manager = new BSFManager();
|
||||||
|
this.manager.setClassLoader(Iris.class.getClassLoader());
|
||||||
|
try {
|
||||||
|
this.manager.declareBean("Iris", api, api.getClass());
|
||||||
|
this.javaScriptEngine = (JavaScriptEngine) this.manager.loadScriptingEngine("javascript");
|
||||||
|
} catch (Throwable e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void execute(String script)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
javaScriptEngine.exec("", 0, 0, getEngine().getData().getScriptLoader().load(script));
|
||||||
|
} catch (BSFException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object evaluate(String script)
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
return javaScriptEngine.eval("", 0, 0, getEngine().getData().getScriptLoader().load(script));
|
||||||
|
} catch (BSFException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(String script, double x, double y, double z) {
|
||||||
|
api.setX(x);
|
||||||
|
api.setY(y);
|
||||||
|
api.setZ(z);
|
||||||
|
execute(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object evaluate(String script, double x, double y, double z) {
|
||||||
|
api.setX(x);
|
||||||
|
api.setY(y);
|
||||||
|
api.setZ(z);
|
||||||
|
return evaluate(script);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.volmit.iris.engine.object.loot.IrisLootTable;
|
|||||||
import com.volmit.iris.engine.object.meta.InventorySlotType;
|
import com.volmit.iris.engine.object.meta.InventorySlotType;
|
||||||
import com.volmit.iris.engine.object.regional.IrisRegion;
|
import com.volmit.iris.engine.object.regional.IrisRegion;
|
||||||
import com.volmit.iris.engine.parallax.ParallaxAccess;
|
import com.volmit.iris.engine.parallax.ParallaxAccess;
|
||||||
|
import com.volmit.iris.engine.scripting.EngineExecutionEnvironment;
|
||||||
import com.volmit.iris.util.collection.KList;
|
import com.volmit.iris.util.collection.KList;
|
||||||
import com.volmit.iris.util.context.IrisContext;
|
import com.volmit.iris.util.context.IrisContext;
|
||||||
import com.volmit.iris.util.data.B;
|
import com.volmit.iris.util.data.B;
|
||||||
@@ -65,6 +66,8 @@ public interface Engine extends DataProvider, Fallible, GeneratorAccess, LootPro
|
|||||||
|
|
||||||
IrisContext getContext();
|
IrisContext getContext();
|
||||||
|
|
||||||
|
EngineExecutionEnvironment getExecution();
|
||||||
|
|
||||||
double getMaxBiomeObjectDensity();
|
double getMaxBiomeObjectDensity();
|
||||||
|
|
||||||
double getMaxBiomeDecoratorDensity();
|
double getMaxBiomeDecoratorDensity();
|
||||||
|
|||||||
+34
-18
@@ -16,24 +16,40 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.volmit.iris.util.bsf;
|
package com.volmit.iris.engine.object.common;
|
||||||
|
|
||||||
/**
|
import com.volmit.iris.core.project.loader.IrisRegistrant;
|
||||||
* BSFDeclaredBeans are used internally by BSF to encapsulate information being
|
import lombok.Data;
|
||||||
* passed between a BSFManager and its various BSFEngines. Note that the
|
import lombok.EqualsAndHashCode;
|
||||||
* constructor is not public because this is not a public class.
|
import org.bukkit.Bukkit;
|
||||||
*
|
|
||||||
* @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) {
|
@EqualsAndHashCode(callSuper = true)
|
||||||
this.name = name;
|
@Data
|
||||||
this.bean = bean;
|
public class IrisScript extends IrisRegistrant {
|
||||||
this.type = type;
|
private final String source;
|
||||||
}
|
|
||||||
|
public IrisScript()
|
||||||
|
{
|
||||||
|
this("");
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisScript(String source)
|
||||||
|
{
|
||||||
|
this.source = source;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getFolderName() {
|
||||||
|
return "scripts";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getTypeName() {
|
||||||
|
return "Script";
|
||||||
|
}
|
||||||
|
|
||||||
|
public String toString()
|
||||||
|
{
|
||||||
|
return source;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -19,11 +19,22 @@
|
|||||||
package com.volmit.iris.engine.scripting;
|
package com.volmit.iris.engine.scripting;
|
||||||
|
|
||||||
import com.volmit.iris.engine.framework.Engine;
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import org.apache.bsf.BSFManager;
|
||||||
|
|
||||||
public interface EngineExecutionEnvironment
|
public interface EngineExecutionEnvironment
|
||||||
{
|
{
|
||||||
Engine getEngine();
|
Engine getEngine();
|
||||||
|
|
||||||
|
BSFManager getManager();
|
||||||
|
|
||||||
|
void execute(String script);
|
||||||
|
|
||||||
|
Object evaluate(String script);
|
||||||
|
|
||||||
|
void execute(String script, double x, double y, double z);
|
||||||
|
|
||||||
|
Object evaluate(String script, double x, double y, double z);
|
||||||
|
|
||||||
default void close()
|
default void close()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
* 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.Iris;
|
||||||
|
import com.volmit.iris.core.project.loader.IrisData;
|
||||||
|
import com.volmit.iris.engine.IrisComplex;
|
||||||
|
import com.volmit.iris.engine.framework.Engine;
|
||||||
|
import com.volmit.iris.engine.framework.EngineFramework;
|
||||||
|
import com.volmit.iris.engine.object.biome.IrisBiome;
|
||||||
|
import com.volmit.iris.engine.object.dimensional.IrisDimension;
|
||||||
|
import com.volmit.iris.engine.object.noise.IrisExpression;
|
||||||
|
import lombok.Data;
|
||||||
|
|
||||||
|
@Data
|
||||||
|
public class IrisScriptingAPI {
|
||||||
|
private final Engine engine;
|
||||||
|
private double x = 0;
|
||||||
|
private double y = 0;
|
||||||
|
private double z = 0;
|
||||||
|
|
||||||
|
public IrisScriptingAPI(Engine engine)
|
||||||
|
{
|
||||||
|
this.engine = engine;
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisData getData()
|
||||||
|
{
|
||||||
|
return getEngine().getData();
|
||||||
|
}
|
||||||
|
|
||||||
|
public EngineFramework getFramework()
|
||||||
|
{
|
||||||
|
return getEngine().getFramework();
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisComplex getComplex()
|
||||||
|
{
|
||||||
|
return getFramework().getComplex();
|
||||||
|
}
|
||||||
|
|
||||||
|
public long getSeed()
|
||||||
|
{
|
||||||
|
return getEngine().getTarget().getWorld().seed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public double expression(String expressionName, double x, double y, double z)
|
||||||
|
{
|
||||||
|
IrisExpression expression = getData().getExpressionLoader().load(expressionName);
|
||||||
|
return expression.evaluate(getComplex().getRng(), x, y, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public double expression(String expressionName, double x, double z)
|
||||||
|
{
|
||||||
|
IrisExpression expression = getData().getExpressionLoader().load(expressionName);
|
||||||
|
return expression.evaluate(getComplex().getRng(), x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisBiome getBiomeAt(int x, int z)
|
||||||
|
{
|
||||||
|
return getEngine().getSurfaceBiome(x, z);
|
||||||
|
}
|
||||||
|
|
||||||
|
public IrisDimension getDimension()
|
||||||
|
{
|
||||||
|
return getEngine().getDimension();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void info(String log)
|
||||||
|
{
|
||||||
|
Iris.info(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void debug(String log)
|
||||||
|
{
|
||||||
|
Iris.debug(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void warn(String log)
|
||||||
|
{
|
||||||
|
Iris.warn(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void error(String log)
|
||||||
|
{
|
||||||
|
Iris.error(log);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,253 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
@@ -1,71 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 ();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,913 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 "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.
|
|
||||||
*
|
|
||||||
<br>Example: "<code>240.20061006</code>"
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#
|
|
||||||
# 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
|
|
||||||
@@ -1,190 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,107 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,136 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 + " \"\"");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,352 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,244 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,497 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 {}
|
|
||||||
}
|
|
||||||
@@ -1,193 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,203 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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(...).");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-164
@@ -1,164 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,38 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,479 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,379 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,517 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,421 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,412 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,196 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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: <STDIN>
|
|
||||||
* [-out fileName] default: <STDOUT>
|
|
||||||
* [-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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,372 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,103 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-39
@@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-36
@@ -1,36 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-42
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-33
@@ -1,33 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-48
@@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-30
@@ -1,30 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-41
@@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,102 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,331 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,105 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
-568
@@ -1,568 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 ();
|
|
||||||
}
|
|
||||||
@@ -1,206 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,6 +12,8 @@ libraries:
|
|||||||
- com.google.code.gson:gson:2.8.7
|
- com.google.code.gson:gson:2.8.7
|
||||||
- it.unimi.dsi:fastutil:8.5.4
|
- it.unimi.dsi:fastutil:8.5.4
|
||||||
- com.google.guava:guava:30.1.1-jre
|
- com.google.guava:guava:30.1.1-jre
|
||||||
|
- bsf:bsf:2.4.0
|
||||||
|
- rhino:js:1.7R2
|
||||||
commands:
|
commands:
|
||||||
iris:
|
iris:
|
||||||
aliases: [ ir, irs ]
|
aliases: [ ir, irs ]
|
||||||
|
|||||||
Reference in New Issue
Block a user