001 /** 002 * 003 * Copyright 2003-2004 The Apache Software Foundation 004 * 005 * Licensed under the Apache License, Version 2.0 (the "License"); 006 * you may not use this file except in compliance with the License. 007 * You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017 018 package org.apache.geronimo.kernel.basic; 019 020 import java.util.Collections; 021 import java.util.HashMap; 022 import java.util.HashSet; 023 import java.util.Iterator; 024 import java.util.Map; 025 import java.util.Set; 026 027 import org.apache.commons.logging.Log; 028 import org.apache.commons.logging.LogFactory; 029 import org.apache.geronimo.kernel.Kernel; 030 import org.apache.geronimo.kernel.GBeanNotFoundException; 031 import org.apache.geronimo.kernel.lifecycle.LifecycleMonitor; 032 import org.apache.geronimo.kernel.lifecycle.LifecycleListener; 033 import org.apache.geronimo.gbean.runtime.LifecycleBroadcaster; 034 import org.apache.geronimo.gbean.AbstractNameQuery; 035 import org.apache.geronimo.gbean.AbstractName; 036 import org.apache.geronimo.gbean.GBeanData; 037 038 /** 039 * @version $Rev: 430508 $ $Date: 2006-08-10 12:56:47 -0700 (Thu, 10 Aug 2006) $ 040 */ 041 public class BasicLifecycleMonitor implements LifecycleMonitor { 042 private static final Log log = LogFactory.getLog(BasicLifecycleMonitor.class); 043 044 045 // todo we should only hold weak references to the listeners 046 /** 047 * Map of AbstractName to set of Listeners interested in this name. 048 */ 049 private final Map boundListeners = new HashMap(); 050 051 /** 052 * Map of listener to patterns they are interested in. 053 */ 054 private final Map listenerPatterns = new HashMap(); 055 056 public BasicLifecycleMonitor(Kernel kernel) { 057 058 // register for state change notifications with all mbeans that match the target patterns 059 Set names = kernel.listGBeans((AbstractNameQuery)null); 060 for (Iterator objectNameIterator = names.iterator(); objectNameIterator.hasNext();) { 061 AbstractName source = (AbstractName) objectNameIterator.next(); 062 GBeanData gBeanData; 063 try { 064 gBeanData = kernel.getGBeanData(source); 065 } catch (GBeanNotFoundException e) { 066 //this should never happen 067 throw new AssertionError(e); 068 } 069 addSource(source, gBeanData.getGBeanInfo().getInterfaces()); 070 } 071 } 072 073 public synchronized void destroy() { 074 boundListeners.clear(); 075 listenerPatterns.clear(); 076 } 077 078 private synchronized void addSource(AbstractName source, Set interfaceTypes) { 079 if (boundListeners.containsKey(source)) { 080 // already registered 081 return; 082 } 083 084 // find all listeners interested in events from this source 085 SourceInfo sourceInfo = new SourceInfo(interfaceTypes); 086 HashSet listeners = sourceInfo.getListeners(); 087 for (Iterator listenerIterator = listenerPatterns.entrySet().iterator(); listenerIterator.hasNext();) { 088 Map.Entry entry = (Map.Entry) listenerIterator.next(); 089 Set patterns = (Set) entry.getValue(); 090 for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) { 091 AbstractNameQuery pattern = (AbstractNameQuery) patternIterator.next(); 092 if (pattern.matches(source, interfaceTypes)) { 093 LifecycleListener listener = (LifecycleListener) entry.getKey(); 094 listeners.add(listener); 095 } 096 } 097 } 098 099 boundListeners.put(source, sourceInfo); 100 } 101 102 private synchronized void removeSource(AbstractName source) { 103 boundListeners.remove(source); 104 } 105 106 public synchronized void addLifecycleListener(LifecycleListener listener, AbstractNameQuery pattern) { 107 addLifecycleListener(listener, Collections.singleton(pattern)); 108 } 109 110 public synchronized void addLifecycleListener(LifecycleListener listener, Set patterns) { 111 for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) { 112 AbstractNameQuery pattern = (AbstractNameQuery) patternIterator.next(); 113 for (Iterator iterator = boundListeners.entrySet().iterator(); iterator.hasNext();) { 114 Map.Entry entry = (Map.Entry) iterator.next(); 115 AbstractName source = (AbstractName) entry.getKey(); 116 SourceInfo sourceInfo = (SourceInfo) entry.getValue(); 117 if (pattern.matches(source, sourceInfo.getInterfaceTypes())) { 118 Set listeners = sourceInfo.getListeners(); 119 listeners.add(listener); 120 } 121 } 122 } 123 listenerPatterns.put(listener, patterns); 124 } 125 126 public synchronized void removeLifecycleListener(LifecycleListener listener) { 127 for (Iterator iterator = boundListeners.values().iterator(); iterator.hasNext();) { 128 SourceInfo sourceInfo = (SourceInfo) iterator.next(); 129 sourceInfo.getListeners().remove(listener); 130 } 131 listenerPatterns.remove(listener); 132 } 133 134 private synchronized Set getTargets(AbstractName source) { 135 SourceInfo targets = (SourceInfo) boundListeners.get(source); 136 if (targets == null) { 137 // no one is interested in this event 138 return Collections.EMPTY_SET; 139 } else { 140 return new HashSet(targets.getListeners()); 141 } 142 } 143 144 private void fireLoadedEvent(AbstractName refInfoName) { 145 Set targets = getTargets(refInfoName); 146 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 147 LifecycleListener listener = (LifecycleListener) iterator.next(); 148 try { 149 listener.loaded(refInfoName); 150 } catch (Throwable e) { 151 log.warn("Exception occured while notifying listener", e); 152 } 153 } 154 } 155 156 private void fireStartingEvent(AbstractName source) { 157 Set targets = getTargets(source); 158 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 159 LifecycleListener listener = (LifecycleListener) iterator.next(); 160 try { 161 listener.starting(source); 162 } catch (Throwable e) { 163 log.warn("Exception occured while notifying listener", e); 164 } 165 } 166 } 167 168 private void fireRunningEvent(AbstractName source) { 169 Set targets = getTargets(source); 170 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 171 LifecycleListener listener = (LifecycleListener) iterator.next(); 172 try { 173 listener.running(source); 174 } catch (Throwable e) { 175 log.warn("Exception occured while notifying listener", e); 176 } 177 } 178 } 179 180 private void fireStoppingEvent(AbstractName source) { 181 Set targets = getTargets(source); 182 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 183 LifecycleListener listener = (LifecycleListener) iterator.next(); 184 try { 185 listener.stopping(source); 186 } catch (Throwable e) { 187 log.warn("Exception occured while notifying listener", e); 188 } 189 } 190 } 191 192 private void fireStoppedEvent(AbstractName source) { 193 Set targets = getTargets(source); 194 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 195 LifecycleListener listener = (LifecycleListener) iterator.next(); 196 try { 197 listener.stopped(source); 198 } catch (Throwable e) { 199 log.warn("Exception occured while notifying listener", e); 200 } 201 } 202 } 203 204 private void fireFailedEvent(AbstractName source) { 205 Set targets = getTargets(source); 206 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 207 LifecycleListener listener = (LifecycleListener) iterator.next(); 208 try { 209 listener.failed(source); 210 } catch (Throwable e) { 211 log.warn("Exception occured while notifying listener", e); 212 } 213 } 214 } 215 216 private void fireUnloadedEvent(AbstractName source) { 217 Set targets = getTargets(source); 218 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 219 LifecycleListener listener = (LifecycleListener) iterator.next(); 220 try { 221 listener.unloaded(source); 222 } catch (Throwable e) { 223 log.warn("Exception occured while notifying listener", e); 224 } 225 } 226 } 227 228 public LifecycleBroadcaster createLifecycleBroadcaster(AbstractName abstractName, Set interfaceTypes) { 229 return new RawLifecycleBroadcaster(abstractName, interfaceTypes); 230 } 231 232 private class RawLifecycleBroadcaster implements LifecycleBroadcaster { 233 private final AbstractName abstractName; 234 private final Set interfaceTypes; 235 236 public RawLifecycleBroadcaster(AbstractName abstractName, Set interfaceTypes) { 237 this.abstractName = abstractName; 238 this.interfaceTypes = interfaceTypes; 239 } 240 241 public void fireLoadedEvent() { 242 addSource(abstractName, interfaceTypes); 243 BasicLifecycleMonitor.this.fireLoadedEvent(abstractName); 244 } 245 246 public void fireStartingEvent() { 247 BasicLifecycleMonitor.this.fireStartingEvent(abstractName); 248 } 249 250 public void fireRunningEvent() { 251 BasicLifecycleMonitor.this.fireRunningEvent(abstractName); 252 } 253 254 public void fireStoppingEvent() { 255 BasicLifecycleMonitor.this.fireStoppingEvent(abstractName); 256 } 257 258 public void fireStoppedEvent() { 259 BasicLifecycleMonitor.this.fireStoppedEvent(abstractName); 260 } 261 262 public void fireFailedEvent() { 263 BasicLifecycleMonitor.this.fireFailedEvent(abstractName); 264 } 265 266 public void fireUnloadedEvent() { 267 BasicLifecycleMonitor.this.fireUnloadedEvent(abstractName); 268 removeSource(abstractName); 269 } 270 } 271 272 private final class SourceInfo { 273 private final Set interfaceTypes; 274 private final HashSet listeners = new HashSet(); 275 276 public SourceInfo(Set interfaceTypes) { 277 this.interfaceTypes = interfaceTypes; 278 } 279 280 public Set getInterfaceTypes() { 281 return interfaceTypes; 282 } 283 284 public HashSet getListeners() { 285 return listeners; 286 } 287 } 288 289 }