001/* 002 * This library is part of OpenCms - 003 * the Open Source Content Management System 004 * 005 * Copyright (c) Alkacon Software GmbH & Co. KG (http://www.alkacon.com) 006 * 007 * This library is free software; you can redistribute it and/or 008 * modify it under the terms of the GNU Lesser General Public 009 * License as published by the Free Software Foundation; either 010 * version 2.1 of the License, or (at your option) any later version. 011 * 012 * This library is distributed in the hope that it will be useful, 013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 * Lesser General Public License for more details. 016 * 017 * For further information about Alkacon Software, please see the 018 * company website: http://www.alkacon.com 019 * 020 * For further information about OpenCms, please see the 021 * project website: http://www.opencms.org 022 * 023 * You should have received a copy of the GNU Lesser General Public 024 * License along with this library; if not, write to the Free Software 025 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 026 */ 027 028package org.opencms.main; 029 030import java.util.ArrayList; 031import java.util.HashMap; 032import java.util.Iterator; 033import java.util.List; 034import java.util.Map; 035 036import org.apache.commons.logging.Log; 037 038/** 039 * Manager that controls the OpenCms event system. 040 * 041 * There is only one instance of this event manager class used by the OpenCms runtime. 042 * This instance can be obtained by calling {@link OpenCms#getEventManager()}.<p> 043 * 044 * Events can be used in OpenCms to notify custom event listeners that certain system events have happened. 045 * Event listeners have to implement the interface {@link org.opencms.main.I_CmsEventListener}.<p> 046 * 047 * @since 7.0.0 048 * 049 * @see org.opencms.main.CmsEvent 050 * @see org.opencms.main.I_CmsEventListener 051 */ 052public class CmsEventManager { 053 054 /** Required as template for event list generation. */ 055 protected static final I_CmsEventListener[] EVENT_LIST = new I_CmsEventListener[0]; 056 057 /** The static log object for this class. */ 058 private static final Log LOG = CmsLog.getLog(CmsEventManager.class); 059 060 /** Stores the active event listeners. */ 061 private Map<Integer, List<I_CmsEventListener>> m_eventListeners; 062 063 /** 064 * Create a new instance of an OpenCms event manager.<p> 065 */ 066 public CmsEventManager() { 067 068 m_eventListeners = new HashMap<Integer, List<I_CmsEventListener>>(); 069 } 070 071 /** 072 * Add an OpenCms event listener that listens to all events.<p> 073 * 074 * @param listener the listener to add 075 */ 076 public void addCmsEventListener(I_CmsEventListener listener) { 077 078 addCmsEventListener(listener, null); 079 } 080 081 /** 082 * Add an OpenCms event listener.<p> 083 * 084 * @param listener the listener to add 085 * @param eventTypes the events to listen for 086 */ 087 public void addCmsEventListener(I_CmsEventListener listener, int[] eventTypes) { 088 089 synchronized (m_eventListeners) { 090 if (eventTypes == null) { 091 // no event types given - register the listener for all event types 092 eventTypes = new int[] {I_CmsEventListener.LISTENERS_FOR_ALL_EVENTS.intValue()}; 093 } 094 for (int i = 0; i < eventTypes.length; i++) { 095 // register the listener for all configured event types 096 Integer eventType = Integer.valueOf(eventTypes[i]); 097 List<I_CmsEventListener> listeners = m_eventListeners.get(eventType); 098 if (listeners == null) { 099 listeners = new ArrayList<I_CmsEventListener>(); 100 m_eventListeners.put(eventType, listeners); 101 } 102 if (!listeners.contains(listener)) { 103 // add listerner only if it is not already registered 104 listeners.add(listener); 105 } 106 } 107 } 108 } 109 110 /** 111 * Notify all event listeners that a particular event has occurred.<p> 112 * 113 * @param event the event that is forwarded to all listeners 114 */ 115 public void fireEvent(CmsEvent event) { 116 117 fireEventHandler(m_eventListeners.get(event.getTypeInteger()), event); 118 fireEventHandler(m_eventListeners.get(I_CmsEventListener.LISTENERS_FOR_ALL_EVENTS), event); 119 } 120 121 /** 122 * Notify all event listeners that a particular event has occurred without any additional event data.<p> 123 * 124 * @param type event type 125 */ 126 public void fireEvent(int type) { 127 128 fireEvent(type, new HashMap<String, Object>()); 129 } 130 131 /** 132 * Notify all event listeners that a particular event has occurred.<p> 133 * 134 * @param type event type 135 * @param data event data 136 */ 137 public void fireEvent(int type, Map<String, Object> data) { 138 139 fireEvent(new CmsEvent(type, data)); 140 } 141 142 /** 143 * Removes a cms event listener.<p> 144 * 145 * @param listener the listener to remove 146 */ 147 public void removeCmsEventListener(I_CmsEventListener listener) { 148 149 synchronized (m_eventListeners) { 150 Iterator<Integer> it = m_eventListeners.keySet().iterator(); 151 while (it.hasNext()) { 152 List<I_CmsEventListener> listeners = m_eventListeners.get(it.next()); 153 listeners.remove(listener); 154 } 155 } 156 } 157 158 /** 159 * Fires the specified event to a list of event listeners.<p> 160 * 161 * @param listeners the listeners to fire 162 * @param event the event to fire 163 */ 164 protected void fireEventHandler(List<I_CmsEventListener> listeners, CmsEvent event) { 165 166 if (!LOG.isDebugEnabled()) { 167 // no logging required 168 if ((listeners != null) && (listeners.size() > 0)) { 169 // handle all event listeners that listen to this event type 170 I_CmsEventListener[] list = listeners.toArray(EVENT_LIST); 171 // loop through all registered event listeners 172 for (int i = 0; i < list.length; i++) { 173 try { 174 // fire the event 175 list[i].cmsEvent(event); 176 } catch (Throwable t) { 177 LOG.error( 178 Messages.get().getBundle().key( 179 Messages.ERR_CALLING_EVENT_LISTENER_FAILED_2, 180 list[i].getClass().getName(), 181 event.toString()), 182 t); 183 } 184 } 185 } 186 } else { 187 // add lots of event debug output (this should usually be disabled) 188 // repeat event handling code to avoid multiple "is log enabled" checks in normal operation 189 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEBUG_EVENT_1, event.toString())); 190 if ((listeners != null) && (listeners.size() > 0)) { 191 // handle all event listeners that listen to this event type 192 I_CmsEventListener[] list = listeners.toArray(EVENT_LIST); 193 // log the event data 194 if (event.getData() != null) { 195 Iterator<String> i = event.getData().keySet().iterator(); 196 while (i.hasNext()) { 197 String key = i.next(); 198 Object value = event.getData().get(key); 199 LOG.debug( 200 Messages.get().getBundle().key( 201 Messages.LOG_DEBUG_EVENT_VALUE_3, 202 key, 203 value, 204 event.toString())); 205 } 206 } else { 207 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEBUG_NO_EVENT_VALUE_1, event.toString())); 208 } 209 // log all the registered event listeners 210 for (int j = 0; j < list.length; j++) { 211 LOG.debug( 212 Messages.get().getBundle().key( 213 Messages.LOG_DEBUG_EVENT_LISTENERS_3, 214 list[j], 215 Integer.valueOf(j), 216 event.toString())); 217 } 218 // loop through all registered event listeners 219 for (int i = 0; i < list.length; i++) { 220 LOG.debug( 221 Messages.get().getBundle().key( 222 Messages.LOG_DEBUG_EVENT_START_LISTENER_3, 223 list[i], 224 Integer.valueOf(i), 225 event.toString())); 226 try { 227 // fire the event 228 list[i].cmsEvent(event); 229 } catch (Throwable t) { 230 LOG.error( 231 Messages.get().getBundle().key( 232 Messages.ERR_CALLING_EVENT_LISTENER_FAILED_2, 233 list[i].getClass().getName(), 234 event.toString()), 235 t); 236 } 237 LOG.debug( 238 Messages.get().getBundle().key( 239 Messages.LOG_DEBUG_EVENT_END_LISTENER_3, 240 list[i], 241 Integer.valueOf(i), 242 event.toString())); 243 } 244 } else { 245 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEBUG_EVENT_NO_LISTENER_1, event.toString())); 246 } 247 LOG.debug(Messages.get().getBundle().key(Messages.LOG_DEBUG_EVENT_COMPLETE_1, event.toString())); 248 } 249 } 250 251 /** 252 * Returns the map of all configured event listeners.<p> 253 * 254 * @return the map of all configured event listeners 255 */ 256 protected Map<Integer, List<I_CmsEventListener>> getEventListeners() { 257 258 return m_eventListeners; 259 } 260 261 /** 262 * Initialize this event manager with all events from the given base event manager.<p> 263 * 264 * @param base the base event manager to initialize this event manager with 265 */ 266 protected void initialize(CmsEventManager base) { 267 268 m_eventListeners = new HashMap<Integer, List<I_CmsEventListener>>(base.getEventListeners()); 269 270 } 271}