1 /** 2 * Licensed to the Apache Software Foundation (ASF) under one or more 3 * contributor license agreements. See the NOTICE file distributed with 4 * this work for additional information regarding copyright ownership. 5 * The ASF licenses this file to You under the Apache License, Version 2.0 6 * (the "License"); you may not use this file except in compliance with 7 * the License. You may obtain a copy of the License at 8 * 9 * http://www.apache.org/licenses/LICENSE-2.0 10 * 11 * Unless required by applicable law or agreed to in writing, software 12 * distributed under the License is distributed on an "AS IS" BASIS, 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 * See the License for the specific language governing permissions and 15 * limitations under the License. 16 */ 17 18 package org.apache.geronimo.kernel.basic; 19 20 import java.util.Collections; 21 import java.util.HashMap; 22 import java.util.HashSet; 23 import java.util.Iterator; 24 import java.util.Map; 25 import java.util.Set; 26 import java.util.LinkedHashSet; 27 import java.util.ArrayList; 28 import java.util.Collection; 29 30 import org.slf4j.Logger; 31 import org.slf4j.LoggerFactory; 32 import org.apache.geronimo.kernel.Kernel; 33 import org.apache.geronimo.kernel.GBeanNotFoundException; 34 import org.apache.geronimo.kernel.lifecycle.LifecycleMonitor; 35 import org.apache.geronimo.kernel.lifecycle.LifecycleListener; 36 import org.apache.geronimo.gbean.runtime.LifecycleBroadcaster; 37 import org.apache.geronimo.gbean.AbstractNameQuery; 38 import org.apache.geronimo.gbean.AbstractName; 39 import org.apache.geronimo.gbean.GBeanData; 40 41 /** 42 * @version $Rev: 653740 $ $Date: 2008-05-06 03:44:18 -0700 (Tue, 06 May 2008) $ 43 */ 44 public class BasicLifecycleMonitor implements LifecycleMonitor { 45 private static final Logger log = LoggerFactory.getLogger(BasicLifecycleMonitor.class); 46 47 // todo we should only hold weak references to the listeners 48 /** 49 * Map of AbstractName to set of Listeners interested in this name. 50 */ 51 private final Map boundListeners = new HashMap(); 52 53 /** 54 * Map of listener to patterns they are interested in. 55 */ 56 private final Map listenerPatterns = new HashMap(); 57 58 public BasicLifecycleMonitor(Kernel kernel) { 59 60 // register for state change notifications with all mbeans that match the target patterns 61 Set names = kernel.listGBeans((AbstractNameQuery)null); 62 for (Iterator objectNameIterator = names.iterator(); objectNameIterator.hasNext();) { 63 AbstractName source = (AbstractName) objectNameIterator.next(); 64 GBeanData gBeanData; 65 try { 66 gBeanData = kernel.getGBeanData(source); 67 } catch (GBeanNotFoundException e) { 68 //this should never happen 69 throw new AssertionError(e); 70 } 71 addSource(source, gBeanData.getGBeanInfo().getInterfaces()); 72 } 73 } 74 75 public synchronized void destroy() { 76 boundListeners.clear(); 77 listenerPatterns.clear(); 78 } 79 80 private synchronized void addSource(AbstractName source, Set interfaceTypes) { 81 if (boundListeners.containsKey(source)) { 82 // already registered 83 return; 84 } 85 86 // find all listeners interested in events from this source 87 SourceInfo sourceInfo = new SourceInfo(interfaceTypes); 88 Set listeners = sourceInfo.getListeners(); 89 for (Iterator listenerIterator = listenerPatterns.entrySet().iterator(); listenerIterator.hasNext();) { 90 Map.Entry entry = (Map.Entry) listenerIterator.next(); 91 Set patterns = (Set) entry.getValue(); 92 for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) { 93 AbstractNameQuery pattern = (AbstractNameQuery) patternIterator.next(); 94 if (pattern.matches(source, interfaceTypes)) { 95 LifecycleListener listener = (LifecycleListener) entry.getKey(); 96 listeners.add(listener); 97 } 98 } 99 } 100 101 boundListeners.put(source, sourceInfo); 102 } 103 104 private synchronized void removeSource(AbstractName source) { 105 boundListeners.remove(source); 106 } 107 108 public synchronized void addLifecycleListener(LifecycleListener listener, AbstractNameQuery pattern) { 109 addLifecycleListener(listener, Collections.singleton(pattern)); 110 } 111 112 public synchronized void addLifecycleListener(LifecycleListener listener, Set patterns) { 113 for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) { 114 AbstractNameQuery pattern = (AbstractNameQuery) patternIterator.next(); 115 for (Iterator iterator = boundListeners.entrySet().iterator(); iterator.hasNext();) { 116 Map.Entry entry = (Map.Entry) iterator.next(); 117 AbstractName source = (AbstractName) entry.getKey(); 118 SourceInfo sourceInfo = (SourceInfo) entry.getValue(); 119 if (pattern.matches(source, sourceInfo.getInterfaceTypes())) { 120 Set listeners = sourceInfo.getListeners(); 121 listeners.add(listener); 122 } 123 } 124 } 125 listenerPatterns.put(listener, patterns); 126 } 127 128 public synchronized void removeLifecycleListener(LifecycleListener listener) { 129 for (Iterator iterator = boundListeners.values().iterator(); iterator.hasNext();) { 130 SourceInfo sourceInfo = (SourceInfo) iterator.next(); 131 sourceInfo.getListeners().remove(listener); 132 } 133 listenerPatterns.remove(listener); 134 } 135 136 private synchronized Collection getTargets(AbstractName source) { 137 SourceInfo targets = (SourceInfo) boundListeners.get(source); 138 if (targets == null) { 139 // no one is interested in this event 140 return Collections.EMPTY_SET; 141 } else { 142 return new ArrayList<LifecycleListener>(targets.getListeners()); 143 } 144 } 145 146 private void fireLoadedEvent(AbstractName refInfoName) { 147 Collection targets = getTargets(refInfoName); 148 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 149 LifecycleListener listener = (LifecycleListener) iterator.next(); 150 try { 151 listener.loaded(refInfoName); 152 } catch (Throwable e) { 153 log.warn("Exception occured while notifying listener", e); 154 } 155 } 156 } 157 158 private void fireStartingEvent(AbstractName source) { 159 Collection targets = getTargets(source); 160 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 161 LifecycleListener listener = (LifecycleListener) iterator.next(); 162 try { 163 listener.starting(source); 164 } catch (Throwable e) { 165 log.warn("Exception occured while notifying listener", e); 166 } 167 } 168 } 169 170 private void fireRunningEvent(AbstractName source) { 171 Collection targets = getTargets(source); 172 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 173 LifecycleListener listener = (LifecycleListener) iterator.next(); 174 try { 175 listener.running(source); 176 } catch (Throwable e) { 177 log.warn("Exception occured while notifying listener", e); 178 } 179 } 180 } 181 182 private void fireStoppingEvent(AbstractName source) { 183 Collection targets = getTargets(source); 184 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 185 LifecycleListener listener = (LifecycleListener) iterator.next(); 186 try { 187 listener.stopping(source); 188 } catch (Throwable e) { 189 log.warn("Exception occured while notifying listener", e); 190 } 191 } 192 } 193 194 private void fireStoppedEvent(AbstractName source) { 195 Collection targets = getTargets(source); 196 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 197 LifecycleListener listener = (LifecycleListener) iterator.next(); 198 try { 199 listener.stopped(source); 200 } catch (Throwable e) { 201 log.warn("Exception occured while notifying listener", e); 202 } 203 } 204 } 205 206 private void fireFailedEvent(AbstractName source) { 207 Collection targets = getTargets(source); 208 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 209 LifecycleListener listener = (LifecycleListener) iterator.next(); 210 try { 211 listener.failed(source); 212 } catch (Throwable e) { 213 log.warn("Exception occured while notifying listener", e); 214 } 215 } 216 } 217 218 private void fireUnloadedEvent(AbstractName source) { 219 Collection targets = getTargets(source); 220 for (Iterator iterator = targets.iterator(); iterator.hasNext();) { 221 LifecycleListener listener = (LifecycleListener) iterator.next(); 222 try { 223 listener.unloaded(source); 224 } catch (Throwable e) { 225 log.warn("Exception occured while notifying listener", e); 226 } 227 } 228 } 229 230 public LifecycleBroadcaster createLifecycleBroadcaster(AbstractName abstractName, Set interfaceTypes) { 231 return new RawLifecycleBroadcaster(abstractName, interfaceTypes); 232 } 233 234 private class RawLifecycleBroadcaster implements LifecycleBroadcaster { 235 private final AbstractName abstractName; 236 private final Set interfaceTypes; 237 238 public RawLifecycleBroadcaster(AbstractName abstractName, Set interfaceTypes) { 239 this.abstractName = abstractName; 240 this.interfaceTypes = interfaceTypes; 241 } 242 243 public void fireLoadedEvent() { 244 addSource(abstractName, interfaceTypes); 245 BasicLifecycleMonitor.this.fireLoadedEvent(abstractName); 246 } 247 248 public void fireStartingEvent() { 249 BasicLifecycleMonitor.this.fireStartingEvent(abstractName); 250 } 251 252 public void fireRunningEvent() { 253 BasicLifecycleMonitor.this.fireRunningEvent(abstractName); 254 } 255 256 public void fireStoppingEvent() { 257 BasicLifecycleMonitor.this.fireStoppingEvent(abstractName); 258 } 259 260 public void fireStoppedEvent() { 261 BasicLifecycleMonitor.this.fireStoppedEvent(abstractName); 262 } 263 264 public void fireFailedEvent() { 265 BasicLifecycleMonitor.this.fireFailedEvent(abstractName); 266 } 267 268 public void fireUnloadedEvent() { 269 BasicLifecycleMonitor.this.fireUnloadedEvent(abstractName); 270 removeSource(abstractName); 271 } 272 } 273 274 private final class SourceInfo { 275 private final Set interfaceTypes; 276 private final HashSet listeners = new LinkedHashSet(); 277 278 public SourceInfo(Set interfaceTypes) { 279 this.interfaceTypes = interfaceTypes; 280 } 281 282 public Set getInterfaceTypes() { 283 return interfaceTypes; 284 } 285 286 public Set getListeners() { 287 return listeners; 288 } 289 } 290 291 }