1 /*
2 * The Apache Software License, Version 1.1
3 *
4 * Copyright (c) 1999, 2000 The Apache Software Foundation. All rights
5 * reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 *
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 *
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in
16 * the documentation and/or other materials provided with the
17 * distribution.
18 *
19 * 3. The end-user documentation included with the redistribution, if
20 * any, must include the following acknowlegement:
21 * "This product includes software developed by the
22 * Apache Software Foundation (http://www.apache.org/)."
23 * Alternately, this acknowlegement may appear in the software itself,
24 * if and wherever such third-party acknowlegements normally appear.
25 *
26 * 4. The names "The Jakarta Project", "Ant", and "Apache Software
27 * Foundation" must not be used to endorse or promote products derived
28 * from this software without prior written permission. For written
29 * permission, please contact apache@apache.org.
30 *
31 * 5. Products derived from this software may not be called "Apache"
32 * nor may "Apache" appear in their names without prior written
33 * permission of the Apache Group.
34 *
35 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
36 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
37 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
38 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
39 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
40 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
41 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
42 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
44 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
45 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
46 * SUCH DAMAGE.
47 * ====================================================================
48 *
49 * This software consists of voluntary contributions made by many
50 * individuals on behalf of the Apache Software Foundation. For more
51 * information on the Apache Software Foundation, please see
52 * <http://www.apache.org/>.
53 */
54 package tweed.system.bus;
55 import java.awt.EventQueue;
56 import java.util.EventObject;
57 import java.util.Iterator;
58 import java.util.LinkedList;
59 import java.util.List;
60 import org.apache.avalon.framework.logger.Logger;
61 import tweed.context.Context;
62
63
64 /***
65 * An event "bus" providing a centralized place for posting
66 * and recieving generic application events. To receive events a class must
67 * implement the "BusMember" interface. When registering as a member, an
68 * "interrupt level" is provided, which specifies a relative ordering level
69 * that the member wishes to receive events for. By convention, a member
70 * can be registered at the MONITORING, VETOING, or RESPONDING levels, which
71 * correspond to recieving events first to receiving events last. If a member
72 * receives an event, the event is of type AntEvent, and the member calls the
73 * AntEvent.cancel() method, the event is not then delivered
74 * to subsequent members. Members also indicate interest in an event
75 * by providing an instance of the BusFilter interface.<BR>
76 *
77 * NB: This class is overly simple right now, but will eventually
78 * be expanded to do better event filtering, interrupt levels, etc.
79 * <br>
80 * TODO: use weak references as pointers to bus members.
81 *
82 * @author Simeon Fitch (source taken out from Ant Antidote)
83 * @author Laurent Caillette (changed a few things)
84 * @version $Revision: 1.2 $ $Date: 2002/03/22 08:41:28 $
85 */
86 public class EventBus {
87
88 public final static String CHILDLOGGER_NAME = "bus" ;
89
90 // private final Context context ;
91 private final Logger logger ;
92
93 public EventBus( Context context ) {
94 if( context == null ) {
95 throw new IllegalArgumentException( "context == null" ) ;
96 }
97 // this.context = context ;
98 logger = context.getLogger().getChildLogger( CHILDLOGGER_NAME ) ;
99 }
100
101
102
103 /*** The default "vetoing" interrupt level, used by bus members
104 * whose role is to veto request events or otherwise handle an
105 * event before it is processed by the default handler.
106 */
107 public static final int VETOING = 1 ;
108
109 /*** The default "monitoring" interrupt level, used by members who
110 * are only listeners/monitors of events.
111 */
112 public static final int MONITORING = 5 ;
113
114 /*** The default "responding" interrupt level, for members who service
115 * events in a default manner.
116 */
117 public static final int RESPONDING = 10 ;
118
119 /*** The maximum valid interrupt value.
120 */
121 public static final int MAX_INTERRUPT = 15 ;
122
123 /*** Set of bus members, with a list for each interrupt level. */
124 private List[] memberSet = new List[ MAX_INTERRUPT ] ;
125
126
127 /***
128 * Add a member to the bus.
129 *
130 * @param intLevel Interrupt level.
131 * @param member Member to add.
132 */
133 public void addMember( int intLevel , BusMember member ) {
134 if( intLevel < 1 || intLevel > MAX_INTERRUPT ) {
135 throw new IllegalArgumentException(
136 "Invalid interrupt level: " + intLevel ) ;
137 }
138 synchronized( memberSet ) {
139 List list = memberSet[intLevel - 1] ;
140 if( list == null ) {
141 list = new LinkedList() ;
142 memberSet[intLevel - 1] = list ;
143 }
144 list.add( member ) ;
145 }
146 }
147
148
149 /***
150 * Remove a member from the bus.
151 *
152 * @param member Member to remove.
153 */
154 public void removeMember( BusMember member ) {
155 synchronized( memberSet ) {
156 // XXX lets hope we don't do too much removing. Yuck...
157 for( int i = 0 ; i < memberSet.length ; i++ ) {
158 if( memberSet[ i ] == null ) continue ;
159 memberSet[ i ].remove( member ) ;
160 }
161 }
162 }
163
164 /***
165 * Method used for sending an event to the bus.
166 *
167 * @param event Event to post.
168 */
169 public void postEvent( EventObject event ) {
170
171 logger.debug( "EventBus received : " + event.toString() ) ;
172
173 EventDispatcher disp = new EventDispatcher( event ) ;
174
175 // Events need to be dispatched on the AWTEvent thread, as the UI
176 // components assume that.
177 if( EventQueue.isDispatchThread() ) {
178 disp.run() ;
179 } else {
180 EventQueue.invokeLater( disp ) ;
181 }
182 }
183
184 /*** Class that performs the duty of dispatching events to the members. */
185 private class EventDispatcher implements Runnable {
186
187 /*** Event to dispatch. */
188 private EventObject event = null ;
189
190 /***
191 * Standard constructor.
192 *
193 * @param event Event to dispatch.
194 */
195 public EventDispatcher( EventObject event ) {
196 this.event = event ;
197 }
198
199
200 /***
201 * Perform dispatching.
202 *
203 */
204 public void run() {
205 synchronized( memberSet ) {
206 outerLoop :
207 for( int i = 0 ; i < memberSet.length ; i++ ) {
208 if( memberSet[ i ] == null ) continue ;
209
210 Iterator it = memberSet[ i ].iterator() ;
211 while( it.hasNext() ) {
212 BusMember next = ( BusMember ) it.next() ;
213 BusFilter filter = next.getBusFilter() ;
214 if( filter == null || filter.accept( event ) ) {
215 if( logger.isDebugEnabled() ) {
216 StringBuffer buf = new StringBuffer() ;
217 buf.append ( "EventBus posting " ) ;
218 buf.append ( event.toString() ) ;
219 buf.append ( " to " ) ;
220 buf.append ( next.toString() ) ;
221 boolean response = next.eventPosted( event ) ;
222 buf.append( " : " ) ;
223 buf.append( response ) ;
224
225 if( ! response ) {
226 break outerLoop ;
227 }
228 logger.debug( buf.toString() ) ;
229
230 } else {
231 // If false then callee canceled the event
232 // propogation.
233 if( ! next.eventPosted( event ) ) {
234 break outerLoop ;
235 }
236 }
237
238 }
239 }
240 }
241 }
242 }
243 }
244 }
This page was automatically generated by Maven