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 }