[armedbear-cvs] r11369 - in branches/scripting/j/src/org/armedbear/lisp: . scripting
Alessio Stalla
astalla at common-lisp.net
Thu Oct 30 06:30:26 UTC 2008
Author: astalla
Date: Thu Oct 30 06:30:25 2008
New Revision: 11369
Log:
Introduced jmake-invocation-handler and jmake-proxy.
Modified:
branches/scripting/j/src/org/armedbear/lisp/Autoload.java
branches/scripting/j/src/org/armedbear/lisp/JProxy.java
branches/scripting/j/src/org/armedbear/lisp/autoloads.lisp
branches/scripting/j/src/org/armedbear/lisp/java.lisp
branches/scripting/j/src/org/armedbear/lisp/scripting/AbclScriptEngine.java
Modified: branches/scripting/j/src/org/armedbear/lisp/Autoload.java
==============================================================================
--- branches/scripting/j/src/org/armedbear/lisp/Autoload.java (original)
+++ branches/scripting/j/src/org/armedbear/lisp/Autoload.java Thu Oct 30 06:30:25 2008
@@ -489,6 +489,8 @@
autoload(PACKAGE_EXT, "thread-unlock", "ThreadLock", true);
autoload(PACKAGE_JAVA, "%jnew-proxy", "JProxy");
autoload(PACKAGE_JAVA, "%jimplement-interface", "JProxy");
+ autoload(PACKAGE_JAVA, "%jmake-invocation-handler", "JProxy");
+ autoload(PACKAGE_JAVA, "%jmake-proxy", "JProxy");
autoload(PACKAGE_JAVA, "%jnew-runtime-class", "RuntimeClass");
autoload(PACKAGE_JAVA, "%jredefine-method", "RuntimeClass");
autoload(PACKAGE_JAVA, "%jregister-handler", "JHandler");
Modified: branches/scripting/j/src/org/armedbear/lisp/JProxy.java
==============================================================================
--- branches/scripting/j/src/org/armedbear/lisp/JProxy.java (original)
+++ branches/scripting/j/src/org/armedbear/lisp/JProxy.java Thu Oct 30 06:30:25 2008
@@ -122,10 +122,104 @@
}
}
- //NEW IMPLEMENTATION by Alessio Stalla
+ //NEW IMPLEMENTATION by Alessio Stalla
-
+ public static class LispInvocationHandler implements InvocationHandler {
+
+ private Function function;
+ private static Method hashCodeMethod;
+ private static Method equalsMethod;
+ private static Method toStringMethod;
+
+ static {
+ try {
+ hashCodeMethod = Object.class.getMethod("hashCode", new Class[] {});
+ equalsMethod = Object.class.getMethod("equals", new Class[] { Object.class });
+ toStringMethod = Object.class.getMethod("toString", new Class[] {});
+ } catch (Exception e) {
+ throw new Error("Something got horribly wrong - can't get a method from Object.class", e);
+ }
+ }
+
+ public LispInvocationHandler(Function function) {
+ this.function = function;
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if(hashCodeMethod.equals(method)) {
+ return proxy.hashCode();
+ }
+ if(equalsMethod.equals(method)) {
+ return proxy.equals(args[0]);
+ }
+ if(toStringMethod.equals(method)) {
+ return proxy.toString();
+ }
+
+ LispObject[] lispArgs = new LispObject[args.length + 2];
+ lispArgs[0] = toLispObject(proxy);
+ lispArgs[1] = new JavaObject(method);
+ for(int i = 0; i < args.length; i++) {
+ lispArgs[i + 2] = toLispObject(args[i]);
+ }
+ Object retVal = (function.execute(lispArgs)).javaInstance();
+ /* DOES NOT WORK due to autoboxing!
+ if(retVal != null && !method.getReturnType().isAssignableFrom(retVal.getClass())) {
+ return error(new TypeError(new JavaObject(retVal), new JavaObject(method.getReturnType())));
+ }*/
+ return retVal;
+ }
+ }
+ private static final Primitive _JMAKE_INVOCATION_HANDLER =
+ new Primitive("%jmake-invocation-handler", PACKAGE_JAVA, false,
+ "function") {
+
+ public LispObject execute(LispObject[] args) throws ConditionThrowable {
+ int length = args.length;
+ if (length != 1) {
+ return error(new WrongNumberOfArgumentsException(this));
+ }
+ if(!(args[0] instanceof Function)) {
+ return error(new TypeError(args[0], Symbol.FUNCTION));
+ }
+
+ return new JavaObject(new LispInvocationHandler((Function) args[0]));
+ }
+ };
+
+ private static final Primitive _JMAKE_PROXY =
+ new Primitive("%jmake-proxy", PACKAGE_JAVA, false,
+ "interface invocation-handler") {
+
+ public LispObject execute(final LispObject[] args) throws ConditionThrowable {
+ int length = args.length;
+ if (length != 2) {
+ return error(new WrongNumberOfArgumentsException(this));
+ }
+ if(!(args[0] instanceof JavaObject) ||
+ !(((JavaObject) args[0]).javaInstance() instanceof Class)) {
+ return error(new TypeError(args[0], new SimpleString(Class.class.getName())));
+ }
+ if(!(args[1] instanceof JavaObject) ||
+ !(((JavaObject) args[1]).javaInstance() instanceof InvocationHandler)) {
+ return error(new TypeError(args[1], new SimpleString(InvocationHandler.class.getName())));
+ }
+ Class<?> iface = (Class<?>) ((JavaObject) args[0]).javaInstance();
+ InvocationHandler invocationHandler = (InvocationHandler) ((JavaObject) args[1]).javaInstance();
+ Object proxy = Proxy.newProxyInstance(
+ iface.getClassLoader(),
+ new Class[] { iface },
+ invocationHandler);
+ return new JavaObject(proxy);
+ }
+ };
+
+ private static LispObject toLispObject(Object obj) {
+ return (obj instanceof LispObject) ? (LispObject) obj : new JavaObject(obj);
+ }
+
private static final Primitive _JIMPLEMENT_INTERFACE =
new Primitive("%jimplement-interface", PACKAGE_JAVA, false,
"interface &rest method-names-and-defs") {
Modified: branches/scripting/j/src/org/armedbear/lisp/autoloads.lisp
==============================================================================
--- branches/scripting/j/src/org/armedbear/lisp/autoloads.lisp (original)
+++ branches/scripting/j/src/org/armedbear/lisp/autoloads.lisp Thu Oct 30 06:30:25 2008
@@ -189,6 +189,10 @@
(autoload 'jinterface-implementation "java")
(export 'jimplement-interface "JAVA")
(autoload 'jimplement-interface "java")
+(export 'jmake-invocation-handler "JAVA")
+(autoload 'jmake-invocation-handler "java")
+(export 'jmake-proxy "JAVA")
+(autoload 'jmake-proxy "java")
(export 'jobject-class "JAVA")
(autoload 'jobject-class "java")
(export 'jclass-superclass "JAVA")
Modified: branches/scripting/j/src/org/armedbear/lisp/java.lisp
==============================================================================
--- branches/scripting/j/src/org/armedbear/lisp/java.lisp (original)
+++ branches/scripting/j/src/org/armedbear/lisp/java.lisp Thu Oct 30 06:30:25 2008
@@ -102,6 +102,15 @@
(push method-name method-names-and-defs)))
(apply #'%jimplement-interface interface method-names-and-defs)))
+(defun jmake-invocation-handler (function)
+ (%jmake-invocation-handler function))
+
+(defun jmake-proxy (interface invocation-handler)
+ (let ((handler (if (functionp invocation-handler)
+ (jmake-invocation-handler invocation-handler)
+ invocation-handler)))
+ (%jmake-proxy (jclass interface) handler)))
+
(defun jobject-class (obj)
"Returns the Java class that OBJ belongs to"
(jcall (jmethod "java.lang.Object" "getClass") obj))
Modified: branches/scripting/j/src/org/armedbear/lisp/scripting/AbclScriptEngine.java
==============================================================================
--- branches/scripting/j/src/org/armedbear/lisp/scripting/AbclScriptEngine.java (original)
+++ branches/scripting/j/src/org/armedbear/lisp/scripting/AbclScriptEngine.java Thu Oct 30 06:30:25 2008
@@ -277,11 +277,16 @@
try {
in = new ReaderInputStream(ctx.getReader());
out = new WriterOutputStream(ctx.getWriter());
+ Stream outStream = new Stream(out, Symbol.CHARACTER);
retVal = evalScript.execute(makeBindings(ctx.getBindings(ScriptContext.GLOBAL_SCOPE)),
makeBindings(ctx.getBindings(ScriptContext.ENGINE_SCOPE)),
new Stream(in, Symbol.CHARACTER),
- new Stream(out, Symbol.CHARACTER),
+ outStream,
new SimpleString(code), new JavaObject(ctx));
+ outStream._finishOutput();
+ out.flush();
+ in.close();
+ out.close();
return toJava(retVal);
} catch (ConditionThrowable e) {
throw new ScriptException(new Exception(e));
More information about the armedbear-cvs
mailing list