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 }