KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > armedbear > lisp > JProxy


1 /*
2  * JProxy.java
3  *
4  * Copyright (C) 2002-2004 Peter Graves
5  * $Id: JProxy.java,v 1.4 2004/02/23 00:05:35 piso Exp $
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
20  */

21
22 package org.armedbear.lisp;
23
24 import java.lang.reflect.InvocationHandler JavaDoc;
25 import java.lang.reflect.Method JavaDoc;
26 import java.lang.reflect.Proxy JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Map JavaDoc;
29 import java.util.WeakHashMap JavaDoc;
30
31 public final class JProxy extends Lisp
32 {
33     private static final Map JavaDoc table = new WeakHashMap JavaDoc();
34
35     // ### %jnew-proxy
36
// %jnew-proxy interface &rest method-names-and-defs
37
private static final Primitive _JNEW_PROXY =
38         new Primitive("%jnew-proxy", PACKAGE_JAVA, false, "interface &rest method-names-and-defs")
39     {
40         public LispObject execute(LispObject[] args) throws ConditionThrowable
41         {
42             int length = args.length;
43             if (length < 3 || length % 2 != 1)
44                 return signal(new WrongNumberOfArgumentsException(this));
45             Map JavaDoc lispDefinedMethods = new HashMap JavaDoc();
46             for (int i = 1; i < length; i = i+2)
47                 lispDefinedMethods.put(args[i].getStringValue(),(Function)args[i+1]);
48             Class JavaDoc iface = (Class JavaDoc) args[0].javaInstance();
49             Object JavaDoc proxy =
50                 Proxy.newProxyInstance(iface.getClassLoader(), new Class JavaDoc[] { iface }, new LispHandler(table));
51             table.put(proxy, new Entry(iface, lispDefinedMethods));
52             return new JavaObject(proxy);
53         }
54     };
55
56     private static class LispHandler implements InvocationHandler JavaDoc
57     {
58         Map JavaDoc table;
59
60         LispHandler (Map JavaDoc table)
61         {
62             this.table = table;
63         }
64
65         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args)
66         {
67             String JavaDoc methodName = method.getName();
68
69             if (methodName.equals("hashCode")) {
70                 return new Integer JavaDoc(System.identityHashCode(proxy));
71             } else if (methodName.equals("equals")) {
72                 return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
73             } else if (methodName.equals("toString")) {
74                 return proxy.getClass().getName() + '@' + Integer.toHexString(proxy.hashCode());
75             }
76
77             if (table.containsKey(proxy)) {
78                 Entry entry = (Entry)table.get(proxy);
79                 Function f = entry.getLispMethod(methodName);
80                 if (f != null) {
81                     if (args == null) // method needs no argument
82
args = new Object JavaDoc[0];
83                     LispObject[] lispArgs = new LispObject[args.length];
84                     for (int i = 0 ; i< args.length; i++)
85                         lispArgs[i] = new JavaObject(args[i]);
86                     try {
87                         LispObject result = f.execute(lispArgs);
88                         return (method.getReturnType() == void.class ? null : result.javaInstance());
89                     }
90                     catch (ConditionThrowable t) {
91                         t.printStackTrace();
92                     }
93                 }
94             }
95             return null;
96         }
97     }
98
99     private static class Entry
100     {
101         Class JavaDoc iface;
102         Map JavaDoc lispDefinedMethods;
103
104         public Entry (Class JavaDoc iface, Map JavaDoc lispDefinedMethods)
105         {
106             this.iface = iface;
107             this.lispDefinedMethods = lispDefinedMethods;
108         }
109
110         public Function getLispMethod(String JavaDoc methodName)
111         {
112             if (lispDefinedMethods.containsKey(methodName))
113                 return (Function)lispDefinedMethods.get(methodName);
114             return null;
115         }
116     }
117 }
118
Popular Tags