[armedbear-cvs] r12774 - trunk/abcl/src/org/armedbear/lisp
Alessio Stalla
astalla at common-lisp.net
Thu Jul 1 21:02:46 UTC 2010
Author: astalla
Date: Thu Jul 1 17:02:45 2010
New Revision: 12774
Log:
Added support for implementing multiple interfaces using jmake-proxy
Modified:
trunk/abcl/src/org/armedbear/lisp/JProxy.java
trunk/abcl/src/org/armedbear/lisp/java.lisp
Modified: trunk/abcl/src/org/armedbear/lisp/JProxy.java
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/JProxy.java (original)
+++ trunk/abcl/src/org/armedbear/lisp/JProxy.java Thu Jul 1 17:02:45 2010
@@ -210,26 +210,26 @@
private static final Primitive _JMAKE_PROXY =
new Primitive("%jmake-proxy", PACKAGE_JAVA, false,
- "interface invocation-handler") {
+ "interfaces invocation-handler") {
public LispObject execute(final LispObject[] args) {
int length = args.length;
if (length != 3) {
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[0] instanceof Cons)) {
+ return error(new TypeError(args[0], new SimpleString("CONS")));
}
- 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();
+ Class[] ifaces = new Class[args[0].length()];
+ LispObject ifList = args[0];
+ for(int i = 0; i < ifaces.length; i++) {
+ ifaces[i] = ifList.car().javaInstance(Class.class);
+ ifList = ifList.cdr();
+ }
+ InvocationHandler invocationHandler = ((JavaObject) args[1]).javaInstance(InvocationHandler.class);
Object proxy = Proxy.newProxyInstance(
- iface.getClassLoader(),
- new Class[] { iface },
+ JavaClassLoader.getCurrentClassLoader(),
+ ifaces,
invocationHandler);
synchronized(proxyMap) {
proxyMap.put(proxy, args[2]);
Modified: trunk/abcl/src/org/armedbear/lisp/java.lisp
==============================================================================
--- trunk/abcl/src/org/armedbear/lisp/java.lisp (original)
+++ trunk/abcl/src/org/armedbear/lisp/java.lisp Thu Jul 1 17:02:45 2010
@@ -92,15 +92,21 @@
(fmakunbound 'jmake-proxy))
(defgeneric jmake-proxy (interface implementation &optional lisp-this)
- (:documentation "Returns a proxy Java object implementing the provided interface using methods implemented in Lisp - typically closures, but implementations are free to provide other mechanisms. You can pass an optional 'lisp-this' object that will be passed to the implementing methods as their first argument. If you don't provide this object, NIL will be used. The second argument of the Lisp methods is the name of the Java method being implemented. This has the implication that overloaded methods are merged, so you have to manually discriminate them if you want to. The remaining arguments are java-objects wrapping the method's parameters."))
+ (:documentation "Returns a proxy Java object implementing the provided interface(s) using methods implemented in Lisp - typically closures, but implementations are free to provide other mechanisms. You can pass an optional 'lisp-this' object that will be passed to the implementing methods as their first argument. If you don't provide this object, NIL will be used. The second argument of the Lisp methods is the name of the Java method being implemented. This has the implication that overloaded methods are merged, so you have to manually discriminate them if you want to. The remaining arguments are java-objects wrapping the method's parameters."))
+
+(defun canonicalize-jproxy-interfaces (ifaces)
+ (if (listp ifaces)
+ (mapcar #'jclass ifaces)
+ (list (jclass ifaces))))
+
(defmethod jmake-proxy (interface invocation-handler &optional lisp-this)
"Basic implementation that directly uses an invocation handler."
- (%jmake-proxy (jclass interface) invocation-handler lisp-this))
+ (%jmake-proxy (canonicalize-jproxy-interfaces interface) invocation-handler lisp-this))
(defmethod jmake-proxy (interface (implementation function) &optional lisp-this)
"Implements a Java interface forwarding method calls to a Lisp function."
- (%jmake-proxy (jclass interface) (jmake-invocation-handler implementation) lisp-this))
+ (%jmake-proxy (canonicalize-jproxy-interfaces interface) (jmake-invocation-handler implementation) lisp-this))
(defmethod jmake-proxy (interface (implementation package) &optional lisp-this)
"Implements a Java interface mapping Java method names to symbols in a given package. javaMethodName is mapped to a JAVA-METHOD-NAME symbol. An error is signaled if no such symbol exists in the package, or if the symbol exists but does not name a function."
@@ -114,7 +120,7 @@
(setf last-lower-p (not upper-p))
(princ (char-upcase char) str)))
name)))))
- (%jmake-proxy (jclass interface)
+ (%jmake-proxy (canonicalize-jproxy-interfaces interface)
(jmake-invocation-handler
(lambda (obj method &rest args)
(let ((sym (find-symbol
@@ -133,7 +139,7 @@
(defmethod jmake-proxy (interface (implementation hash-table) &optional lisp-this)
"Implements a Java interface using closures in an hash-table keyed by Java method name."
- (%jmake-proxy (jclass interface)
+ (%jmake-proxy (canonicalize-jproxy-interfaces interface)
(jmake-invocation-handler
(lambda (obj method &rest args)
(let ((fn (gethash method implementation)))
More information about the armedbear-cvs
mailing list