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 package org.apache.xbean.kernel.standard;
018
019 import java.util.ArrayList;
020 import java.util.Collections;
021 import java.util.Iterator;
022 import java.util.LinkedHashMap;
023 import java.util.LinkedHashSet;
024 import java.util.List;
025 import java.util.Map;
026 import java.util.Set;
027
028 import org.apache.xbean.kernel.ServiceMonitor;
029 import org.apache.xbean.kernel.KernelMonitor;
030 import org.apache.xbean.kernel.ServiceName;
031 import org.apache.xbean.kernel.ServiceEvent;
032 import org.apache.xbean.kernel.KernelErrorsError;
033
034 /**
035 * The ServiceMonitorBroadcaster broadcasts kernel events to registered service monitors.
036 *
037 * @author Dain Sundstrom
038 * @version $Id$
039 * @since 2.0
040 */
041 public class ServiceMonitorBroadcaster implements ServiceMonitor {
042 /**
043 * The monitors for service events.
044 */
045 private final Map serviceMonitors = new LinkedHashMap();
046
047 /**
048 * The monitor we notify when we get an exception from a service monitor.
049 */
050 private final KernelMonitor kernelMonitor;
051
052 /**
053 * Creates a ServiceMonitorBroadcaster that notifies the specified kernel monitor when an error occurs while
054 * notifying the registered service monitors.
055 *
056 * @param kernelMonitor the monitor to notify when an error occurs while notifying the registered service monitors
057 */
058 public ServiceMonitorBroadcaster(KernelMonitor kernelMonitor) {
059 if (kernelMonitor == null) throw new NullPointerException("kernelMonitor is null");
060 this.kernelMonitor = kernelMonitor;
061 }
062
063 /**
064 * Adds a service monitor for a specific service, or if the specified service name is null, a global monitor.
065 * <p/>
066 * Note: the order in which service monitors are notified is not specified.
067 *
068 * @param serviceMonitor the service monitor to add
069 * @param serviceName the unique name of the service to monitor or null to monitor all services
070 */
071 public void addServiceMonitor(ServiceMonitor serviceMonitor, ServiceName serviceName) {
072 if (serviceMonitor == null) throw new NullPointerException("serviceMonitor is null");
073 synchronized (serviceMonitors) {
074 Set monitors = (Set) serviceMonitors.get(serviceName);
075 if (monitors == null) {
076 monitors = new LinkedHashSet();
077 serviceMonitors.put(serviceName, monitors);
078 }
079 monitors.add(serviceMonitor);
080 }
081 }
082
083 /**
084 * Removes a service monitor.
085 *
086 * @param serviceMonitor the service monitor to remove
087 */
088 public void removeServiceMonitor(ServiceMonitor serviceMonitor) {
089 if (serviceMonitor == null) throw new NullPointerException("serviceMonitor is null");
090 synchronized (serviceMonitors) {
091 for (Iterator iterator = serviceMonitors.values().iterator(); iterator.hasNext();) {
092 Set monitors = (Set) iterator.next();
093 monitors.remove(serviceMonitor);
094 if (monitors.isEmpty()) {
095 iterator.remove();
096 }
097 }
098 }
099 }
100
101 /**
102 * Gets the service monitors registered to recieve events for the specified service. This will include all global
103 * monitors and service specific monitors.
104 *
105 * @param serviceName the name of the service
106 * @return the monitors registerd to recieve events for the specified service
107 */
108 private Set getServiceMonitors(ServiceName serviceName) {
109 synchronized (serviceMonitors) {
110 Set monitors = new LinkedHashSet();
111 Set globalMonitors = (Set) serviceMonitors.get(null);
112 if (globalMonitors != null) {
113 monitors.addAll(globalMonitors);
114 }
115 Set specificMonitors = (Set) serviceMonitors.get(serviceName);
116 if (specificMonitors != null) {
117 monitors.addAll(specificMonitors);
118 }
119 return monitors;
120 }
121 }
122
123 /**
124 * {@inheritDoc}
125 */
126 public void serviceRegistered(ServiceEvent serviceEvent) {
127 List errors = new ArrayList();
128 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
129 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
130 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
131 try {
132 serviceMonitor.serviceRegistered(serviceEvent);
133 } catch (Throwable e) {
134 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
135 }
136 }
137 if (!errors.isEmpty()) {
138 throw new KernelErrorsError(errors);
139 }
140 }
141
142 /**
143 * {@inheritDoc}
144 */
145 public void serviceStarting(ServiceEvent serviceEvent) {
146 List errors = new ArrayList();
147 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
148 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
149 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
150 try {
151 serviceMonitor.serviceStarting(serviceEvent);
152 } catch (Throwable e) {
153 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
154 }
155 }
156 if (!errors.isEmpty()) {
157 throw new KernelErrorsError(errors);
158 }
159 }
160
161 /**
162 * {@inheritDoc}
163 */
164 public void serviceWaitingToStart(ServiceEvent serviceEvent) {
165 List errors = new ArrayList();
166 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
167 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
168 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
169 try {
170 serviceMonitor.serviceWaitingToStart(serviceEvent);
171 } catch (Throwable e) {
172 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
173 }
174 }
175 if (!errors.isEmpty()) {
176 throw new KernelErrorsError(errors);
177 }
178 }
179
180 /**
181 * {@inheritDoc}
182 */
183 public void serviceStartError(ServiceEvent serviceEvent) {
184 List errors = new ArrayList();
185 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
186 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
187 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
188 try {
189 serviceMonitor.serviceStartError(serviceEvent);
190 } catch (Throwable e) {
191 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
192 }
193 }
194 if (!errors.isEmpty()) {
195 throw new KernelErrorsError(errors);
196 }
197 }
198
199 /**
200 * {@inheritDoc}
201 */
202 public void serviceRunning(ServiceEvent serviceEvent) {
203 List errors = new ArrayList();
204 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
205 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
206 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
207 try {
208 serviceMonitor.serviceRunning(serviceEvent);
209 } catch (Throwable e) {
210 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
211 }
212 }
213 if (!errors.isEmpty()) {
214 throw new KernelErrorsError(errors);
215 }
216 }
217
218 /**
219 * {@inheritDoc}
220 */
221 public void serviceStopping(ServiceEvent serviceEvent) {
222 List errors = new ArrayList();
223 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
224 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
225 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
226 try {
227 serviceMonitor.serviceStopping(serviceEvent);
228 } catch (Throwable e) {
229 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
230 }
231 }
232 if (!errors.isEmpty()) {
233 throw new KernelErrorsError(errors);
234 }
235 }
236
237 /**
238 * {@inheritDoc}
239 */
240 public void serviceWaitingToStop(ServiceEvent serviceEvent) {
241 List errors = new ArrayList();
242 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
243 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
244 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
245 try {
246 serviceMonitor.serviceWaitingToStop(serviceEvent);
247 } catch (Throwable e) {
248 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
249 }
250 }
251 if (!errors.isEmpty()) {
252 throw new KernelErrorsError(errors);
253 }
254 }
255
256 /**
257 * {@inheritDoc}
258 */
259 public void serviceStopError(ServiceEvent serviceEvent) {
260 List errors = new ArrayList();
261 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
262 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
263 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
264 try {
265 serviceMonitor.serviceStopError(serviceEvent);
266 } catch (Throwable e) {
267 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
268 }
269 }
270 if (!errors.isEmpty()) {
271 throw new KernelErrorsError(errors);
272 }
273 }
274
275 /**
276 * {@inheritDoc}
277 */
278 public void serviceStopped(ServiceEvent serviceEvent) {
279 List errors = new ArrayList();
280 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
281 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
282 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
283 try {
284 serviceMonitor.serviceStopped(serviceEvent);
285 } catch (Throwable e) {
286 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
287 }
288 }
289 if (!errors.isEmpty()) {
290 throw new KernelErrorsError(errors);
291 }
292 }
293
294 /**
295 * {@inheritDoc}
296 */
297 public void serviceUnregistered(ServiceEvent serviceEvent) {
298 List errors = new ArrayList();
299 Set serviceMonitors = getServiceMonitors(serviceEvent.getServiceName());
300 for (Iterator iterator = serviceMonitors.iterator(); iterator.hasNext();) {
301 ServiceMonitor serviceMonitor = (ServiceMonitor) iterator.next();
302 try {
303 serviceMonitor.serviceUnregistered(serviceEvent);
304 } catch (Throwable e) {
305 errors.addAll(fireServiceNotificationError(serviceMonitor, serviceEvent, e));
306 }
307 }
308 if (!errors.isEmpty()) {
309 throw new KernelErrorsError(errors);
310 }
311 }
312
313 private List fireServiceNotificationError(ServiceMonitor serviceMonitor, ServiceEvent serviceEvent, Throwable throwable) {
314 try {
315 kernelMonitor.serviceNotificationError(serviceMonitor, serviceEvent, throwable);
316 } catch (RuntimeException ignored) {
317 // ignore - we did our best to notify the world
318 } catch (KernelErrorsError e) {
319 return e.getErrors();
320 } catch (Error e) {
321 return Collections.singletonList(e);
322 }
323 return Collections.EMPTY_LIST;
324 }
325 }