KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cocoon > portal > event > impl > DefaultEventManager


1 /*
2  * Copyright 1999-2002,2004-2005 The Apache Software Foundation.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16 package org.apache.cocoon.portal.event.impl;
17
18 import java.lang.reflect.Method JavaDoc;
19 import java.util.ArrayList JavaDoc;
20 import java.util.HashMap JavaDoc;
21 import java.util.Iterator JavaDoc;
22 import java.util.List JavaDoc;
23 import java.util.Map JavaDoc;
24
25 import org.apache.avalon.framework.activity.Disposable;
26 import org.apache.avalon.framework.activity.Initializable;
27 import org.apache.avalon.framework.configuration.Configurable;
28 import org.apache.avalon.framework.configuration.Configuration;
29 import org.apache.avalon.framework.configuration.ConfigurationException;
30 import org.apache.avalon.framework.container.ContainerUtil;
31 import org.apache.avalon.framework.context.Context;
32 import org.apache.avalon.framework.context.ContextException;
33 import org.apache.avalon.framework.context.Contextualizable;
34 import org.apache.avalon.framework.logger.AbstractLogEnabled;
35 import org.apache.avalon.framework.service.ServiceException;
36 import org.apache.avalon.framework.service.ServiceManager;
37 import org.apache.avalon.framework.service.ServiceSelector;
38 import org.apache.avalon.framework.service.Serviceable;
39 import org.apache.avalon.framework.thread.ThreadSafe;
40 import org.apache.cocoon.ProcessingException;
41 import org.apache.cocoon.components.ContextHelper;
42 import org.apache.cocoon.portal.PortalService;
43 import org.apache.cocoon.portal.event.Event;
44 import org.apache.cocoon.portal.event.EventConverter;
45 import org.apache.cocoon.portal.event.EventManager;
46 import org.apache.cocoon.portal.event.Publisher;
47 import org.apache.cocoon.portal.event.Receiver;
48 import org.apache.cocoon.portal.event.Register;
49 import org.apache.cocoon.portal.event.Subscriber;
50 import org.apache.cocoon.portal.event.aspect.EventAspect;
51 import org.apache.cocoon.util.ClassUtils;
52 import org.apache.cocoon.util.Deprecation;
53
54 /**
55  * This is the default implementation of the event manager.
56  *
57  * @author <a HREF="mailto:cziegeler@s-und-n.de">Carsten Ziegeler</a>
58  * @author <a HREF="mailto:volker.schmitt@basf-it-services.com">Volker Schmitt</a>
59  *
60  * @version CVS $Id: DefaultEventManager.java 219049 2005-07-14 15:11:52Z cziegeler $
61  */

62 public class DefaultEventManager
63     extends AbstractLogEnabled
64     implements EventManager,
65                 Serviceable,
66                 Initializable,
67                 ThreadSafe,
68                 Configurable,
69                 Disposable,
70                 Contextualizable,
71                 Publisher, Register {
72                     
73     private final String JavaDoc rootEventType = Event.class.getName();
74     private Class JavaDoc eventClass;
75     /** The list of all subscribers. */
76     private List JavaDoc subscribers = new ArrayList JavaDoc();
77     /** The list of all receivers */
78     private Map JavaDoc receivers = new HashMap JavaDoc();
79
80     private ServiceManager manager;
81     private Configuration configuration;
82     
83     protected EventAspectChain chain;
84     
85     protected ServiceSelector aspectSelector;
86
87     protected Context context;
88
89     /** The portal service */
90     protected PortalService service;
91
92     /** Introspected receiver classes */
93     protected Map JavaDoc receiverClasses = new HashMap JavaDoc();
94
95     /**
96      * @see org.apache.avalon.framework.service.Serviceable#service(org.apache.avalon.framework.service.ServiceManager)
97      */

98     public void service(ServiceManager manager) throws ServiceException {
99         this.manager = manager;
100         this.service = (PortalService)manager.lookup(PortalService.ROLE);
101     }
102
103     /* (non-Javadoc)
104      * @see org.apache.cocoon.portal.event.EventManager#getPublisher()
105      */

106     public Publisher getPublisher() {
107         return this;
108     }
109     
110     /* (non-Javadoc)
111      * @see org.apache.cocoon.portal.event.EventManager#getRegister()
112      */

113     public Register getRegister() {
114         return this;
115     }
116     
117     /**
118      * Helper method to get the current object model
119      */

120     protected Map JavaDoc getObjectModel() {
121         return ContextHelper.getObjectModel( this.context );
122     }
123
124     /* (non-Javadoc)
125      * @see org.apache.avalon.framework.configuration.Configurable#configure(org.apache.avalon.framework.configuration.Configuration)
126      */

127     public void configure(Configuration conf)
128     throws ConfigurationException {
129         this.configuration = conf;
130     }
131
132     /* (non-Javadoc)
133      * @see org.apache.avalon.framework.activity.Disposable#dispose()
134      */

135     public void dispose() {
136         if (this.manager != null) {
137             if ( this.chain != null) {
138                 this.chain.dispose( this.aspectSelector );
139             }
140             this.manager.release( this.aspectSelector );
141             this.aspectSelector = null;
142             this.manager.release(this.service);
143             this.service = null;
144             this.manager = null;
145         }
146     }
147
148     /* (non-Javadoc)
149      * @see org.apache.avalon.framework.activity.Initializable#initialize()
150      */

151     public void initialize()
152     throws Exception JavaDoc {
153         this.eventClass = Class.forName( rootEventType );
154         if ( this.getLogger().isDebugEnabled() ) {
155             this.getLogger().debug("Initialising eventClass " + eventClass);
156         }
157
158         // FIXME - the following configuration is not portal specific, it's global!
159
// subscribe all configured roles
160
Configuration roles = this.configuration.getChild("subscriber-roles", false);
161         if ( roles != null ) {
162             Configuration[] rolesConf = roles.getChildren("role");
163             for(int i=0; i<rolesConf.length;i++) {
164                 final Configuration current = rolesConf[i];
165                 final String JavaDoc name = current.getAttribute("name");
166                 
167                 Subscriber subscriber = null;
168                 try {
169                     subscriber = (Subscriber) this.manager.lookup(name);
170                     Deprecation.logger.warn("Subscriber is deprecated. Please convert the following component to a Receiver: " + subscriber.getClass().getName());
171                     this.subscribe(subscriber);
172                 } finally {
173                     this.manager.release(subscriber);
174                 }
175             }
176         }
177         // subscribe all configured classes
178
Configuration classes = this.configuration.getChild("subscriber-classes", false);
179         if ( classes != null ) {
180             Configuration[] classesConf = classes.getChildren("class");
181             for(int i=0; i<classesConf.length;i++) {
182                 final Configuration current = classesConf[i];
183                 final String JavaDoc name = current.getAttribute("name");
184                 
185                 Deprecation.logger.warn("Subscriber is deprecated. Please convert the following component to a Receiver: " + name);
186                 Subscriber subscriber = (Subscriber) ClassUtils.newInstance(name);
187                 ContainerUtil.enableLogging(subscriber, this.getLogger());
188                 ContainerUtil.contextualize(subscriber, this.context);
189                 ContainerUtil.service(subscriber, this.manager );
190                 ContainerUtil.initialize(subscriber);
191                 this.subscribe(subscriber);
192             }
193         }
194         // subscribe all configured receiver roles
195
roles = this.configuration.getChild("receiver-roles", false);
196         if ( roles != null ) {
197             Configuration[] rolesConf = roles.getChildren("role");
198             for(int i=0; i<rolesConf.length;i++) {
199                 final Configuration current = rolesConf[i];
200                 final String JavaDoc name = current.getAttribute("name");
201                 
202                 Receiver receiver = null;
203                 try {
204                     receiver = (Receiver) this.manager.lookup(name);
205                     this.subscribe(receiver);
206                 } finally {
207                     this.manager.release(receiver);
208                 }
209             }
210         }
211         // subscribe all configured receiver classes
212
classes = this.configuration.getChild("receiver-classes", false);
213         if ( classes != null ) {
214             Configuration[] classesConf = classes.getChildren("class");
215             for(int i=0; i<classesConf.length;i++) {
216                 final Configuration current = classesConf[i];
217                 final String JavaDoc name = current.getAttribute("name");
218                 
219                 Receiver receiver = (Receiver)ClassUtils.newInstance(name);
220                 ContainerUtil.enableLogging(receiver, this.getLogger());
221                 ContainerUtil.contextualize(receiver, this.context);
222                 ContainerUtil.service(receiver, this.manager );
223                 ContainerUtil.initialize(receiver);
224                 this.subscribe(receiver);
225             }
226         }
227
228     }
229
230     /* (non-Javadoc)
231      * @see org.apache.cocoon.portal.event.Publisher#publish(org.apache.cocoon.portal.event.Event)
232      */

233     public void publish( final Event event ) {
234         this.send(event);
235     }
236     
237     /* (non-Javadoc)
238      * @see org.apache.cocoon.portal.event.Register#subscribe(org.apache.cocoon.portal.event.Subscriber)
239      */

240     public void subscribe( final Subscriber subscriber ) {
241         if ( !eventClass.isAssignableFrom( subscriber.getEventType() ) ) {
242             throw new RuntimeException JavaDoc("Invalid event type " + subscriber.getEventType()
243                                       +" for subscriber " + subscriber);
244         }
245
246         if ( getLogger().isDebugEnabled() ) {
247             getLogger().debug( "Subscribing event " + subscriber.getEventType().getName() );
248         }
249         
250         // Add to list but prevent duplicate subscriptions
251
if ( !subscribers.contains( subscriber ) ) {
252             subscribers.add( subscriber );
253             if ( getLogger().isDebugEnabled() ) {
254                 getLogger().debug( "Subscribed Event " + subscriber.getEventType().getName() );
255                 getLogger().debug( "Subscribers now active: " + subscribers.size() );
256             }
257         }
258     }
259     
260     /* (non-Javadoc)
261      * @see org.apache.cocoon.portal.event.Register#unsubscribe(org.apache.cocoon.portal.event.Subscriber)
262      */

263     public void unsubscribe( Subscriber subscriber ) {
264         
265         if ( !eventClass.isAssignableFrom( subscriber.getEventType() ) ) {
266             throw new RuntimeException JavaDoc("Invalid event type " + subscriber.getEventType()
267                     +" for unsubscribing " + subscriber);
268         }
269         if ( subscribers.contains( subscriber ) ) {
270             subscribers.remove( subscriber );
271             if ( getLogger().isDebugEnabled() ) {
272                 getLogger().debug( "Unsubscribed Event " + subscriber.getEventType().getName() );
273                 getLogger().debug( "Subscribers now active: " + subscribers.size() );
274             }
275         } else {
276             getLogger().warn( "Subscriber " + subscriber + " not found" );
277         }
278     }
279
280     /* (non-Javadoc)
281      * @see org.apache.cocoon.portal.event.EventManager#processEvents()
282      */

283     public void processEvents()
284     throws ProcessingException {
285         if ( this.configuration != null ) {
286             try {
287                 this.aspectSelector = (ServiceSelector) this.manager.lookup( EventAspect.ROLE+"Selector");
288                 this.chain = new EventAspectChain();
289                 this.chain.configure(this.aspectSelector, this.configuration.getChild("event-aspects"));
290             } catch (ConfigurationException ce) {
291                 throw new ProcessingException("Unable configure component.", ce);
292             } catch (ServiceException ce) {
293                 throw new ProcessingException("Unable to lookup component.", ce);
294             }
295             this.configuration = null;
296         }
297         DefaultEventAspectContext context = new DefaultEventAspectContext(this.chain);
298         EventConverter converter = null;
299         PortalService service = null;
300         try {
301             service = (PortalService)this.manager.lookup(PortalService.ROLE);
302             converter = (EventConverter) this.manager.lookup(EventConverter.ROLE);
303             Publisher publisher = this.getPublisher();
304
305             converter.start();
306             
307             // Invoke aspects
308
context.setEventPublisher( publisher );
309             context.setObjectModel(this.getObjectModel());
310             context.setEventConverter(converter);
311             context.invokeNext( service );
312
313             converter.finish();
314
315         } catch (ServiceException ce) {
316             throw new ProcessingException("Unable to lookup component.", ce);
317         } finally {
318             this.manager.release(converter);
319             this.manager.release(service);
320         }
321
322     }
323
324     /**
325      * @see org.apache.avalon.framework.context.Contextualizable#contextualize(org.apache.avalon.framework.context.Context)
326      */

327     public void contextualize(Context context)
328     throws ContextException {
329         this.context = context;
330     }
331
332     /**
333      * @see org.apache.cocoon.portal.event.EventManager#send(org.apache.cocoon.portal.event.Event)
334      */

335     public void send(Event event) {
336         if ( getLogger().isDebugEnabled() ) {
337             getLogger().debug("Publishing event " + event.getClass());
338         }
339         for ( Iterator JavaDoc e = subscribers.iterator(); e.hasNext(); ){
340             Subscriber subscriber = (Subscriber)e.next();
341             if (subscriber.getEventType().isAssignableFrom(event.getClass())
342             && (subscriber.getFilter() == null || subscriber.getFilter().filter(event))) {
343                 if ( getLogger().isDebugEnabled() ) {
344                     getLogger().info("Informing subscriber "+subscriber+" of event "+event.getClass());
345                 }
346                 subscriber.inform(event);
347             }
348         }
349         for (Iterator JavaDoc re = receivers.entrySet().iterator(); re.hasNext(); ) {
350             final Map.Entry JavaDoc current = (Map.Entry JavaDoc)re.next();
351             final Receiver receiver = (Receiver)current.getKey();
352             final List JavaDoc methodInfos = (List JavaDoc)current.getValue();
353             boolean found = false;
354             final Iterator JavaDoc ci = methodInfos.iterator();
355             while ( !found && ci.hasNext() ) {
356                 final MethodInfo info = (MethodInfo)ci.next();
357                 if ( info.eventClass.isAssignableFrom(event.getClass()) ) {
358                     if ( getLogger().isDebugEnabled() ) {
359                         getLogger().info("Informing receiver "+receiver+" of event "+event.getClass());
360                     }
361                     try {
362                         info.method.invoke(receiver, new Object JavaDoc[] {event, this.service});
363                     } catch (Exception JavaDoc ignore) {
364                         this.getLogger().warn("Exception during event dispatching on receiver " + receiver
365                                              +" and event " + event, ignore);
366                     }
367                     found = true;
368                 }
369             }
370         }
371     }
372
373     protected static final class MethodInfo {
374         
375         public Class JavaDoc eventClass;
376         public Method JavaDoc method;
377     }
378
379     protected synchronized List JavaDoc introspect(Class JavaDoc receiverClass) {
380         List JavaDoc result = (List JavaDoc)this.receiverClasses.get(receiverClass.getName());
381         if ( result == null ) {
382             result = new ArrayList JavaDoc();
383             Method JavaDoc[] methods = receiverClass.getMethods();
384             for(int i=0; i<methods.length; i++ ) {
385                 final Method JavaDoc current = methods[i];
386                 if ( current.getName().equals("inform") ) {
387                     final Class JavaDoc[] params = current.getParameterTypes();
388                     if ( params.length == 2
389                          && params[1].getName().equals(PortalService.class.getName())) {
390                         if ( eventClass.isAssignableFrom( params[0] ) ) {
391                             MethodInfo info = new MethodInfo();
392                             info.eventClass = params[0];
393                             info.method = current;
394                             result.add(info);
395                         }
396                     }
397                 }
398             }
399             if ( result.size() == 0 ) {
400                 result = null;
401             }
402         }
403         return result;
404     }
405  
406     /**
407      * @see org.apache.cocoon.portal.event.EventManager#subscribe(org.apache.cocoon.portal.event.Receiver)
408      */

409     public void subscribe(Receiver receiver) {
410         List JavaDoc infos = this.introspect(receiver.getClass());
411         if ( infos == null ) {
412             throw new RuntimeException JavaDoc("Invalid event receiver type: " + receiver);
413         }
414
415         // Add to list but prevent duplicate subscriptions
416
List JavaDoc eventClassesForReceiver = (List JavaDoc)this.receivers.get(receiver);
417         if ( eventClassesForReceiver == null ) {
418             this.receivers.put(receiver, infos);
419         }
420         if ( getLogger().isDebugEnabled() ) {
421             for(int i=0; i<infos.size();i++) {
422                 getLogger().debug( "Receiver " + receiver + " subscribed for event: " + ((MethodInfo)infos.get(i)).eventClass.getName() );
423             }
424         }
425     }
426
427     /**
428      * @see org.apache.cocoon.portal.event.EventManager#unsubscribe(org.apache.cocoon.portal.event.Receiver)
429      */

430     public void unsubscribe(Receiver receiver) {
431         if ( getLogger().isDebugEnabled() ) {
432             getLogger().debug( "Receiver " + receiver + " unsubscribed.");
433         }
434         this.receivers.remove(receiver);
435     }
436
437 }
438
Popular Tags