View Javadoc

1   package org.lsst.ccs.utilities.dispatch;
2   
3   
4   import java.lang.reflect.InvocationHandler;
5   import java.lang.reflect.Method;
6   import java.lang.reflect.Proxy;
7   import java.util.concurrent.CopyOnWriteArrayList;
8   import java.util.logging.Level;
9   
10  /**
11   * Instances of this class creates a dynamic proxy that dispatches method call
12   * to registered agents implementing an interface type.
13   * <P>
14   *  <B>beware</B> : if the implemented interface is itself a parameterized type
15   *  no type control is exercised on these type parameters.
16   *
17   * @author Bernard AMADE
18   */
19  public class SynchronousDispatchProxy <I> {
20      protected CopyOnWriteArrayList<Object> list = new CopyOnWriteArrayList<Object>() ;
21      class Invoker implements InvocationHandler {
22          @Override
23          public Object invoke(Object o, Method method, Object[] parms){
24              for(Object goal : list) {
25                  try {
26                  method.invoke(goal, parms);
27                  } catch (Exception exc) {
28                      PackCst.CURLOG.log(Level.SEVERE, "dispatching to " + goal, exc);
29                  }
30              }
31              return null;
32          }
33      }
34  
35      protected I proxy ;
36  
37      /**
38       *  prepares a generator able to deliver a Proxy object able to dispatch method calls to registered agents.
39       *   The methods of the interface will necessarily be of procedural nature (the return values will be dumped)
40       * @param interfaceType
41       */
42      public SynchronousDispatchProxy(Class<I> interfaceType) {
43          // not necessarily a good idea ;
44          proxy = (I) Proxy.newProxyInstance(this.getClass().getClassLoader(), new Class[] {interfaceType}, new Invoker()) ;
45  
46      }
47  
48      /**
49       * Same as previous but with a specified ClassLoader
50       * @param interfaceType
51       * @param loader
52       */
53      public SynchronousDispatchProxy(Class<I> interfaceType, ClassLoader loader) {
54          proxy = (I) Proxy.newProxyInstance(loader, new Class[] {interfaceType}, new Invoker()) ;
55      }
56  
57       /**
58       * Registers a code ready to receive "synchronous" commands
59       * @param executant (should implement the interface)
60       */
61      public  <T extends I> void addExecutant(T executant) {
62          list.add(executant) ;
63      }
64  
65      /**
66       * Remove the code from the listeners list
67       *
68       * @param executant
69       */
70      public <T extends I> void removeExecutant(T executant){
71          list.remove(executant) ;
72      }
73  
74      /**
75       * to be called once to get a dynamically generated proxy that will forward calls to registered agents.
76       *
77       * @return
78       */
79      public I getProxy() {
80          return proxy ;
81      }
82  }