001 package de.deepamehta.core.impl; 002 003 import de.deepamehta.core.osgi.PluginContext; 004 import de.deepamehta.core.service.DeepaMehtaEvent; 005 import de.deepamehta.core.service.DeepaMehtaService; 006 import de.deepamehta.core.service.EventListener; 007 008 import javax.ws.rs.WebApplicationException; 009 010 import java.util.ArrayList; 011 import java.util.HashMap; 012 import java.util.List; 013 import java.util.Map; 014 015 016 017 class EventManager { 018 019 // ---------------------------------------------------------------------------------------------- Instance Variables 020 021 /** 022 * The registered event listeners (key: event class name, value: event listeners). 023 */ 024 private Map<String, List<EventListener>> listenerRegistry = new HashMap(); 025 026 private DeepaMehtaService dms; 027 028 // ---------------------------------------------------------------------------------------------------- Constructors 029 030 EventManager(DeepaMehtaService dms) { 031 this.dms = dms; 032 // Note: actually the class CoreEvent does not need to be instantiated as it contains only statics. 033 // But if not instantiated OSGi apparently does not load the class at all. 034 new CoreEvent(); 035 } 036 037 // ----------------------------------------------------------------------------------------- Package Private Methods 038 039 void addListener(DeepaMehtaEvent event, EventListener listener) { 040 List<EventListener> listeners = getListeners(event); 041 if (listeners == null) { 042 listeners = new ArrayList(); 043 putListeners(event, listeners); 044 } 045 listeners.add(listener); 046 } 047 048 void removeListener(DeepaMehtaEvent event, EventListener listener) { 049 List<EventListener> listeners = getListeners(event); 050 if (!listeners.remove(listener)) { 051 throw new RuntimeException("Removing " + listener + " from " + 052 event + " event listeners failed: not found in " + listeners); 053 } 054 } 055 056 // --- 057 058 void fireEvent(DeepaMehtaEvent event, Object... params) { 059 List<EventListener> listeners = getListeners(event); 060 if (listeners != null) { 061 for (EventListener listener : listeners) { 062 deliverEvent(listener, event, params); 063 } 064 } 065 } 066 067 // --- 068 069 /** 070 * Checks weather the given plugin is a listener for the given event, and if so, delivers the event to the plugin. 071 * Otherwise nothing is performed. 072 */ 073 void deliverEvent(PluginImpl plugin, DeepaMehtaEvent event, Object... params) { 074 PluginContext pluginContext = plugin.getContext(); 075 if (!isListener(pluginContext, event)) { 076 return; 077 } 078 // 079 deliverEvent((EventListener) pluginContext, event, params); 080 } 081 082 /** 083 * Convenience method to check weather the specified plugin is a listener for the given event, and if so, 084 * delivers the event to the plugin. Otherwise nothing is performed. 085 */ 086 void deliverEvent(String pluginUri, DeepaMehtaEvent event, Object... params) { 087 deliverEvent((PluginImpl) dms.getPlugin(pluginUri), event, params); 088 } 089 090 // ------------------------------------------------------------------------------------------------- Private Methods 091 092 private void deliverEvent(EventListener listener, DeepaMehtaEvent event, Object... params) { 093 try { 094 event.deliver(listener, params); 095 } catch (WebApplicationException e) { 096 // Note: a WebApplicationException thrown by a event listener must reach Jersey. So we re-throw here. 097 // This allow plugins to produce specific HTTP responses by throwing a WebApplicationException. 098 // Consider the Caching plugin: it produces a possible 304 (Not Modified) response this way. 099 throw e; 100 } catch (Exception e) { 101 throw new RuntimeException("Processing event " + event + " by " + listener + " failed", e); 102 } 103 } 104 105 // --- 106 107 /** 108 * Returns true if the given plugin is a listener for the given event. 109 */ 110 private boolean isListener(PluginContext pluginContext, DeepaMehtaEvent event) { 111 return event.getListenerInterface().isAssignableFrom(pluginContext.getClass()); 112 } 113 114 // --- 115 116 private List<EventListener> getListeners(DeepaMehtaEvent event) { 117 return listenerRegistry.get(event.getClass().getName()); 118 } 119 120 private void putListeners(DeepaMehtaEvent event, List<EventListener> listeners) { 121 listenerRegistry.put(event.getClass().getName(), listeners); 122 } 123 }