001: /*
002: * @(#)bind.java 1.4 05/01/27
003: *
004: * Copyright (c) 2002-2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package org.pnuts.beans;
010:
011: import pnuts.lang.*;
012: import java.util.*;
013: import java.io.*;
014: import java.beans.*;
015: import java.lang.reflect.Method;
016: import java.lang.reflect.Constructor;
017: import java.lang.reflect.InvocationTargetException;
018:
019: /*
020: * function bind(bean, action, func)
021: */
022: public class bind extends PnutsFunction {
023:
024: /*
025: * bean => adapter
026: */
027: static Hashtable eventAdapterTable = new Hashtable();
028:
029: /*
030: * listenerType + action => adapter class
031: */
032: static Hashtable adapters = new Hashtable();
033:
034: public bind() {
035: super ("bind");
036: }
037:
038: public boolean defined(int nargs) {
039: return nargs == 3;
040: }
041:
042: protected Object exec(Object[] args, Context context) {
043: int nargs = args.length;
044: if (nargs != 3) {
045: undefined(args, context);
046: return null;
047: }
048: Object bean = args[0];
049: final PnutsFunction func = (PnutsFunction) args[2];
050: if (!func.defined(1)) {
051: throw new PnutsException("function must take one argument",
052: context);
053: }
054: String action = (String) args[1];
055: int idx = action.lastIndexOf('.');
056: String listenerType;
057: if (idx > 0) {
058: listenerType = action.substring(0, idx - 1);
059: action = action.substring(idx + 1);
060: } else {
061: listenerType = null;
062: }
063: Method method = null;
064: Method addMethod = null;
065: try {
066: EventSetDescriptor[] eventset = Introspector.getBeanInfo(
067: bean.getClass()).getEventSetDescriptors();
068: for (int i = 0; i < eventset.length; i++) {
069: EventSetDescriptor event = eventset[i];
070: if (listenerType != null
071: && listenerType != event.getListenerType()
072: .getName()) {
073: continue;
074: }
075: Method[] methods = event.getListenerMethods();
076: Method add = event.getAddListenerMethod();
077: for (int j = 0; j < methods.length; j++) {
078: Method m = methods[j];
079: if (m.getName().equals(action)) {
080: method = m;
081: addMethod = add;
082: break;
083: }
084: }
085: }
086: if (addMethod == null) {
087: for (int i = 0; i < eventset.length; i++) {
088: EventSetDescriptor event = eventset[i];
089: Class t = event.getListenerType();
090: Method[] methods = t.getMethods();
091: for (int j = 0; j < methods.length; j++) {
092: Method mj = methods[j];
093: if (mj.getName().equals(action)) {
094: method = mj;
095: addMethod = event.getAddListenerMethod();
096: break;
097: }
098: }
099: if (addMethod != null) {
100: break;
101: }
102: }
103: if (addMethod == null) {
104: throw new PnutsException(
105: "cannot find add-method for: " + action,
106: context);
107: }
108: }
109: Class listenerClass = method.getDeclaringClass();
110:
111: String key = listenerClass + ":" + action;
112: Class adapter = (Class) adapters.get(key);
113: if (adapter == null) {
114: adapters.put(key, adapter = EventAdapter
115: .generateEventAdapter(listenerClass, action));
116: }
117: Constructor cons = adapter.getConstructor(new Class[] {
118: PnutsFunction.class, Context.class });
119: Object listener = cons.newInstance(new Object[] {
120: new PnutsFunction() {
121: protected Object exec(Object[] args,
122: Context context) {
123: func
124: .call(new Object[] { args[0] },
125: context);
126: PrintWriter w = context.getWriter();
127: if (w != null) {
128: w.flush();
129: }
130: return null;
131: }
132: }, (Context) context.clone() });
133: addMethod.invoke(bean, new Object[] { listener });
134: register(context, bean, action, func, listener);
135: } catch (IntrospectionException e1) {
136: throw new PnutsException(e1, context);
137: } catch (IllegalAccessException e2) {
138: throw new PnutsException(e2, context);
139: } catch (InvocationTargetException e3) {
140: throw new PnutsException(e3, context);
141: } catch (NoSuchMethodException e4) {
142: } catch (InstantiationException e5) {
143: throw new PnutsException(e5, context);
144: }
145: return null;
146: }
147:
148: static void register(Context context, Object bean, String action,
149: PnutsFunction func, Object adapter) {
150: Hashtable ht = (Hashtable) eventAdapterTable.get(bean);
151: if (ht == null) {
152: eventAdapterTable.put(bean, ht = new Hashtable());
153: Hashtable u = new Hashtable();
154: ht.put(action, u);
155: u.put(func, adapter);
156: } else {
157: Hashtable u = (Hashtable) ht.get(action);
158: if (u == null) {
159: ht.put(action, u = new Hashtable());
160: }
161: u.put(func, adapter);
162: }
163: }
164:
165: public String toString() {
166: return "function bind(bean, action, func)";
167: }
168: }
|