View Javadoc

1   /**
2    *
3    * Copyright 2003-2004 The Apache Software Foundation
4    *
5    *  Licensed under the Apache License, Version 2.0 (the "License");
6    *  you may not use this file except in compliance with the License.
7    *  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  
27  import org.apache.commons.logging.Log;
28  import org.apache.commons.logging.LogFactory;
29  import org.apache.geronimo.kernel.Kernel;
30  import org.apache.geronimo.kernel.GBeanNotFoundException;
31  import org.apache.geronimo.kernel.lifecycle.LifecycleMonitor;
32  import org.apache.geronimo.kernel.lifecycle.LifecycleListener;
33  import org.apache.geronimo.gbean.runtime.LifecycleBroadcaster;
34  import org.apache.geronimo.gbean.AbstractNameQuery;
35  import org.apache.geronimo.gbean.AbstractName;
36  import org.apache.geronimo.gbean.GBeanData;
37  
38  /**
39   * @version $Rev: 430508 $ $Date: 2006-08-10 12:56:47 -0700 (Thu, 10 Aug 2006) $
40   */
41  public class BasicLifecycleMonitor implements LifecycleMonitor {
42      private static final Log log = LogFactory.getLog(BasicLifecycleMonitor.class);
43  
44  
45      // todo we should only hold weak references to the listeners
46      /**
47       * Map of AbstractName to set of Listeners interested in this name.
48       */
49      private final Map boundListeners = new HashMap();
50  
51      /**
52       * Map of listener to patterns they are interested in.
53       */
54      private final Map listenerPatterns = new HashMap();
55  
56      public BasicLifecycleMonitor(Kernel kernel) {
57  
58          // register for state change notifications with all mbeans that match the target patterns
59          Set names = kernel.listGBeans((AbstractNameQuery)null);
60          for (Iterator objectNameIterator = names.iterator(); objectNameIterator.hasNext();) {
61              AbstractName source = (AbstractName) objectNameIterator.next();
62              GBeanData gBeanData;
63              try {
64                  gBeanData = kernel.getGBeanData(source);
65              } catch (GBeanNotFoundException e) {
66                  //this should never happen
67                  throw new AssertionError(e);
68              }
69              addSource(source, gBeanData.getGBeanInfo().getInterfaces());
70          }
71      }
72  
73      public synchronized void destroy() {
74          boundListeners.clear();
75          listenerPatterns.clear();
76      }
77  
78      private synchronized void addSource(AbstractName source, Set interfaceTypes) {
79          if (boundListeners.containsKey(source)) {
80              // already registered
81              return;
82          }
83  
84          // find all listeners interested in events from this source
85          SourceInfo sourceInfo = new SourceInfo(interfaceTypes);
86          HashSet listeners = sourceInfo.getListeners();
87          for (Iterator listenerIterator = listenerPatterns.entrySet().iterator(); listenerIterator.hasNext();) {
88              Map.Entry entry = (Map.Entry) listenerIterator.next();
89              Set patterns = (Set) entry.getValue();
90              for (Iterator patternIterator = patterns.iterator(); patternIterator.hasNext();) {
91                  AbstractNameQuery pattern = (AbstractNameQuery) patternIterator.next();
92                  if (pattern.matches(source, interfaceTypes)) {
93                      LifecycleListener listener = (LifecycleListener) entry.getKey();
94                      listeners.add(listener);
95                  }
96              }
97          }
98  
99          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 }