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