Berin,
this is what I want:
import java.lang.reflect.*;
import java.util.*;
/**
* Interface for events. See the Button class below for example of use.
*/
interface Event {
public void register (Object o);
public void deregister (Object o);
}
/**
* Creates events (multicast delegates)
*/
class EventFactory {
static class EventHandler implements InvocationHandler {
private ArrayList handlers = new ArrayList ();
private Method registerMethod;
private Method deregisterMethod;
public EventHandler () {
try {
registerMethod = Event.class.getDeclaredMethod
("register", new Class[] { Object.class });
deregisterMethod = Event.class.getDeclaredMethod
("deregister", new Class[] { Object.class });
} catch (Exception e) {
// If this happens we've had a severe error somewhere.
throw new Error (e.toString ());
}
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
System.out.println ("EventHandler invocation: " +
method.getName ());
if (method.equals (registerMethod)) {
handlers.add (args[0]);
return null;
} else if (method.equals (deregisterMethod)) {
handlers.remove (args[0]);
return null;
} else {
Iterator iter = handlers.iterator ();
while (iter.hasNext ()) {
method.invoke (iter.next (), args);
}
// As events are multicast, the only allowed return
value is void.
return null;
}
}
}
public static Event newEvent (Class delegateInterface) {
return (Event) Proxy.newProxyInstance
(delegateInterface.getClassLoader (),
new Class[]{ Event.class, delegateInterface }, new
EventHandler () );
}
}
/**
* Creates delegates.
*/
class DelegateFactory {
static class DelegateHandler implements InvocationHandler {
private final Object instance;
private final Method delegateMethod;
public DelegateHandler (Object instance, String methodName) {
this.instance = instance;
// Right now we only test on method name.
// This could be extended to test on delegate
// method signature.
Class instanceClass = instance.getClass ();
Method[] methods = instanceClass.getDeclaredMethods ();
Method method = null;
for (int i = 0; i < methods.length; i++) {
if (methods[i].getName ().equals (methodName)) {
method = methods[i];
}
}
this.delegateMethod = method;
}
public Object invoke(Object proxy, Method m, Object[] args)
throws Throwable {
return delegateMethod.invoke (instance, args);
}
}
public static Object newDelegate (Object instance, String
methodName, Class delegateInterface) {
return Proxy.newProxyInstance (delegateInterface.getClassLoader
(),
new Class[]{ delegateInterface }, new DelegateHandler
(instance, methodName) );
}
}
// -------------------- Test Code
class Button {
interface Delegate {
public String action ();
}
public Event multicast = EventFactory.newEvent (Delegate.class);
public Delegate unicast = null;
public void fireMulticast () {
((Delegate) multicast).action ();
}
public void fireUnicast () {
String result = ((Delegate) unicast).action ();
System.out.println ("Result from unicast is " + result);
}
}
public class Hack {
public String myFirstEventHandler () {
System.out.println ("In myFirstEventHandler.");
return "myFirstEventHandler";
}
public String mySecondEventHandler () {
System.out.println ("In mySecondEventHandler.");
return "mySecondEventHandler";
}
public String myDelegate () {
System.out.println ("In myDelegate.");
return "delegate";
}
public void run () {
Button button = new Button ();
button.multicast.register (DelegateFactory.newDelegate (this,
"myFirstEventHandler", Button.Delegate.class));
button.multicast.register (DelegateFactory.newDelegate (this,
"mySecondEventHandler", Button.Delegate.class));
button.unicast = (Button.Delegate) DelegateFactory.newDelegate
(this, "myDelegate", Button.Delegate.class);
button.fireMulticast ();
button.fireUnicast ();
}
public static void main (String[] args) {
new Hack ().run ();
}
}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>