1 16 package org.apache.cocoon.portal.event.impl; 17 18 import java.lang.reflect.Method ; 19 import java.util.ArrayList ; 20 import java.util.HashMap ; 21 import java.util.Iterator ; 22 import java.util.List ; 23 import java.util.Map ; 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 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 rootEventType = Event.class.getName(); 74 private Class eventClass; 75 76 private List subscribers = new ArrayList (); 77 78 private Map receivers = new HashMap (); 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 90 protected PortalService service; 91 92 93 protected Map receiverClasses = new HashMap (); 94 95 98 public void service(ServiceManager manager) throws ServiceException { 99 this.manager = manager; 100 this.service = (PortalService)manager.lookup(PortalService.ROLE); 101 } 102 103 106 public Publisher getPublisher() { 107 return this; 108 } 109 110 113 public Register getRegister() { 114 return this; 115 } 116 117 120 protected Map getObjectModel() { 121 return ContextHelper.getObjectModel( this.context ); 122 } 123 124 127 public void configure(Configuration conf) 128 throws ConfigurationException { 129 this.configuration = conf; 130 } 131 132 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 151 public void initialize() 152 throws Exception { 153 this.eventClass = Class.forName( rootEventType ); 154 if ( this.getLogger().isDebugEnabled() ) { 155 this.getLogger().debug("Initialising eventClass " + eventClass); 156 } 157 158 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 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 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 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 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 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 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 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 233 public void publish( final Event event ) { 234 this.send(event); 235 } 236 237 240 public void subscribe( final Subscriber subscriber ) { 241 if ( !eventClass.isAssignableFrom( subscriber.getEventType() ) ) { 242 throw new RuntimeException ("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 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 263 public void unsubscribe( Subscriber subscriber ) { 264 265 if ( !eventClass.isAssignableFrom( subscriber.getEventType() ) ) { 266 throw new RuntimeException ("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 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 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 327 public void contextualize(Context context) 328 throws ContextException { 329 this.context = context; 330 } 331 332 335 public void send(Event event) { 336 if ( getLogger().isDebugEnabled() ) { 337 getLogger().debug("Publishing event " + event.getClass()); 338 } 339 for ( Iterator 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 re = receivers.entrySet().iterator(); re.hasNext(); ) { 350 final Map.Entry current = (Map.Entry )re.next(); 351 final Receiver receiver = (Receiver)current.getKey(); 352 final List methodInfos = (List )current.getValue(); 353 boolean found = false; 354 final Iterator 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 [] {event, this.service}); 363 } catch (Exception 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 eventClass; 376 public Method method; 377 } 378 379 protected synchronized List introspect(Class receiverClass) { 380 List result = (List )this.receiverClasses.get(receiverClass.getName()); 381 if ( result == null ) { 382 result = new ArrayList (); 383 Method [] methods = receiverClass.getMethods(); 384 for(int i=0; i<methods.length; i++ ) { 385 final Method current = methods[i]; 386 if ( current.getName().equals("inform") ) { 387 final Class [] 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 409 public void subscribe(Receiver receiver) { 410 List infos = this.introspect(receiver.getClass()); 411 if ( infos == null ) { 412 throw new RuntimeException ("Invalid event receiver type: " + receiver); 413 } 414 415 List eventClassesForReceiver = (List )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 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 |