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 }