View Javadoc

1   // 
2   //Copyright (c) 2003, Caltha - Gajda, Krzewski, Mach, Potempski Sp.J. 
3   //All rights reserved. 
4   //   
5   //Redistribution and use in source and binary forms, with or without modification,  
6   //are permitted provided that the following conditions are met: 
7   //   
8   //* Redistributions of source code must retain the above copyright notice,  
9   //this list of conditions and the following disclaimer. 
10  //* Redistributions in binary form must reproduce the above copyright notice,  
11  //this list of conditions and the following disclaimer in the documentation  
12  //and/or other materials provided with the distribution. 
13  //* Neither the name of the Caltha - Gajda, Krzewski, Mach, Potempski Sp.J.  
14  //nor the names of its contributors may be used to endorse or promote products  
15  //derived from this software without specific prior written permission. 
16  // 
17  //THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"  
18  //AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED  
19  //WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 
20  //IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,  
21  //INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,  
22  //BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, 
23  //OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,  
24  //WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)  
25  //ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE  
26  //POSSIBILITY OF SUCH DAMAGE. 
27  //
28  
29  package org.objectledge.event;
30  
31  import java.lang.reflect.InvocationHandler;
32  import java.lang.reflect.InvocationTargetException;
33  import java.lang.reflect.Method;
34  import java.lang.reflect.Proxy;
35  import java.rmi.Remote;
36  import java.util.HashMap;
37  import java.util.HashSet;
38  import java.util.Iterator;
39  import java.util.Map;
40  import java.util.Set;
41  import java.util.WeakHashMap;
42  
43  import org.jcontainer.dna.Logger;
44  
45  /**
46   * Default event forwarder implementation.
47   *
48   * @author <a href="mailto:rafal@caltha.pl">Rafal Krzewski</a>
49   * @version $Id: DefaultEventWhiteboard.java,v 1.7 2006/02/08 18:22:08 zwierzem Exp $
50   */
51  public class DefaultEventWhiteboard implements EventWhiteboard
52  {
53      /*** The logger. */
54      private Logger logger;
55  
56      /***
57       * The Map Listener interface -> ( Map trigger object -> Set of Listeners ) 
58       */
59      private Map<Class,Map<Object,Map>> interfaceMap = new HashMap<Class,Map<Object,Map>>();
60  
61      /*** Created proxies for <code>Remote</code> objects. */
62      private Map<Remote,Map<Class,Object>> proxies = new WeakHashMap<Remote,Map<Class,Object>>();
63  
64      /*** The EventWhiteboardFactory */
65      private EventWhiteboardFactory eventSystem;
66  
67      // Initailization ////////////////////////////////////////////////////////
68  
69      /***
70       * Crates an EventWhiteboard instance.
71       * 
72       * @param eventSystem the event system component.
73       * @param logger the logger.
74       */
75      public DefaultEventWhiteboard(EventWhiteboardFactory eventSystem, Logger logger)
76      {
77          this.logger = logger;
78          this.eventSystem = eventSystem;
79      }
80  
81      /***
82       * {@inheritDoc}
83       */
84      public synchronized void addListener(Class iface, Object listener, Object object)
85          throws IllegalArgumentException
86      {
87          if (!iface.isInterface())
88          {
89              throw new IllegalArgumentException(iface.getName() + " is not an interface type");
90          }
91          if (!iface.isInstance(listener))
92          {
93              throw new IllegalArgumentException("Handler class " + listener.getClass().getName() + 
94                                                  " does not implement " + iface.getName());
95          }
96          Map<Object,Map> triggerMap = interfaceMap.get(iface);
97          if (triggerMap == null)
98          {
99              triggerMap = new WeakHashMap<Object,Map>();
100             interfaceMap.put(iface, triggerMap);
101         }
102         Map handlers = triggerMap.get(object);
103         if (handlers == null)
104         {
105             handlers = new WeakHashMap();
106             triggerMap.put(object, handlers);
107         }
108         handlers.put(listener, null);
109     }
110 
111     /***
112      * {@inheritDoc}
113      */
114     public synchronized void removeListener(Class iface, Object listener, Object object)
115     {
116         Map triggerMap = (Map)interfaceMap.get(iface);
117         if (triggerMap != null)
118         {
119             Map handlers = (Map)triggerMap.get(object);
120             if (handlers != null)
121             {
122                 handlers.remove(listener);
123             }
124         }
125     }
126 
127     /***
128      * {@inheritDoc}
129      */
130     public synchronized void addRemoteListener(Class iface, Remote listener, Object object)
131         throws IllegalArgumentException
132     {
133         InvocationHandler handler = new RemoteInvocationHandler(iface, listener);
134         Object proxy = Proxy.newProxyInstance(this.getClass().getClassLoader(),
135                                               new Class[] { iface }, handler);
136         Map<Class,Object> ifMap = proxies.get(listener);
137         if(ifMap == null)
138         {
139             ifMap = new HashMap<Class,Object>();
140             proxies.put(listener, ifMap);
141         }
142         ifMap.put(iface, proxy);
143         addListener(iface, proxy, object); 
144     }
145 
146     /***
147      * {@inheritDoc}
148      */
149     public synchronized void removeRemoteListener(Class iface, Remote listener, Object object)
150     {
151         Map ifMap = (Map)proxies.get(listener);
152         if(ifMap != null)
153         {
154             Object proxy = ifMap.get(iface);
155             if(proxy != null)
156             {
157                 removeListener(iface, proxy, object);
158             }
159         }
160     }
161 
162     /***
163      * {@inheritDoc}
164      */
165     public void fireEvent(Method method, Object[] args, Object object)
166     {
167         if(eventSystem.isAsynchronous())
168         {
169             eventSystem.enqueueEvent(this, method, args, object);
170         }
171         else
172         {
173             dispatchEvent(method, args, object);
174         }
175     }
176 
177     void dispatchEvent(Method method, Object[] args, Object object)
178     {
179         Class iface = method.getDeclaringClass();
180         Set currentHandlers = null;
181         synchronized(this)
182         {
183             Map<Object,Map> triggerMap = interfaceMap.get(iface);
184             if(triggerMap != null)
185             {
186                 Map handlers = triggerMap.get(object);
187                 if(handlers != null)
188                 {
189                     currentHandlers = new HashSet(handlers.keySet());
190                 }
191             }
192         }
193         if(currentHandlers != null)
194         {
195             Iterator i = currentHandlers.iterator();
196             while(i.hasNext())
197             {
198                 Object handler = i.next();
199                 try
200                 {
201                     method.invoke(handler, args);
202                 }
203                 catch(ThreadDeath t)
204                 {
205                     throw t;
206                 }
207                 catch(VirtualMachineError t)
208                 {
209                     throw t;
210                 }
211                 catch(InvocationTargetException e)
212                 {
213                     logger.error("Failed to invoke handler", e.getTargetException());
214                 }
215                 catch(Throwable t)
216                 {
217                     logger.error("Failed to invoke handler", t);
218                 }
219             }
220         }
221     }
222 }