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.List; 020 import java.util.ArrayList; 021 import java.util.Iterator; 022 023 import java.util.concurrent.Executors; 024 import java.util.concurrent.ExecutorService; 025 import java.util.concurrent.TimeUnit; 026 import java.util.concurrent.locks.Lock; 027 import java.util.concurrent.locks.ReentrantLock; 028 import java.util.concurrent.locks.Condition; 029 import org.apache.xbean.kernel.IllegalServiceStateException; 030 import org.apache.xbean.kernel.Kernel; 031 import org.apache.xbean.kernel.KernelErrorsError; 032 import org.apache.xbean.kernel.KernelMonitor; 033 import org.apache.xbean.kernel.ServiceAlreadyExistsException; 034 import org.apache.xbean.kernel.ServiceFactory; 035 import org.apache.xbean.kernel.ServiceMonitor; 036 import org.apache.xbean.kernel.ServiceName; 037 import org.apache.xbean.kernel.ServiceNotFoundException; 038 import org.apache.xbean.kernel.ServiceRegistrationException; 039 import org.apache.xbean.kernel.ServiceState; 040 import org.apache.xbean.kernel.StartStrategies; 041 import org.apache.xbean.kernel.StartStrategy; 042 import org.apache.xbean.kernel.StopStrategies; 043 import org.apache.xbean.kernel.StopStrategy; 044 import org.apache.xbean.kernel.UnregisterServiceException; 045 import org.apache.xbean.kernel.UnsatisfiedConditionsException; 046 import org.apache.xbean.kernel.KernelFactory; 047 048 /** 049 * The standard kernel implementation. 050 * 051 * @author Dain Sundstrom 052 * @version $Id$ 053 * @since 2.0 054 */ 055 public class StandardKernel implements Kernel { 056 /** 057 * The unique name of this kernel. 058 */ 059 private final String kernelName; 060 061 /** 062 * The registered service managers. 063 */ 064 private final ServiceManagerRegistry serviceManagerRegistry; 065 066 /** 067 * Tracks and broadcasts kernel evnents to the registered listeners. 068 */ 069 private final KernelMonitorBroadcaster kernelMonitor = new KernelMonitorBroadcaster(); 070 071 /** 072 * This monitor broadcasts events to the listeners registered for service. 073 */ 074 private final ServiceMonitorBroadcaster serviceMonitor = new ServiceMonitorBroadcaster(kernelMonitor); 075 076 /** 077 * If true, the kernel is still running. 078 */ 079 private boolean running = true; 080 081 /** 082 * Lock that should be acquired before accessing the running boolean flag. 083 */ 084 private final Lock destroyLock = new ReentrantLock(); 085 086 /** 087 * The condition that is notified when the kernel has been destroyed. 088 */ 089 private final Condition destroyCondition = destroyLock.newCondition(); 090 091 /** 092 * Creates the service managers with handle service lifecycle. 093 */ 094 private ServiceManagerFactory serviceManagerFactory; 095 096 /** 097 * The service executor for this kernel 098 */ 099 private ExecutorService serviceExecutor; 100 101 /** 102 * True if the executor is owned by this kernel and should be shutdown 103 * when the kernel is destroyed 104 */ 105 private boolean ownsServiceExecutor; 106 107 /** 108 * Creates a kernel using the specified name. 109 * 110 * @param kernelName the unique name of this kernel 111 */ 112 public StandardKernel(String kernelName) { 113 this(kernelName, Executors.newCachedThreadPool(), 30, TimeUnit.SECONDS); 114 ownsServiceExecutor = true; 115 } 116 117 /** 118 * Creates a kernel using the specified name. 119 * 120 * @param kernelName the unique name of this kernel 121 * @param serviceExecutor the executor to use for asynchronous service operations 122 * @param timeoutDuration the maximum duration to wait for a service event to complete 123 * @param timeoutUnits the unit of measure for the timeoutDuration 124 */ 125 public StandardKernel(String kernelName, ExecutorService serviceExecutor, long timeoutDuration, TimeUnit timeoutUnits) { 126 if (kernelName == null) throw new NullPointerException("kernelName is null"); 127 if (kernelName.length() ==0) throw new IllegalArgumentException("kernelName must be atleast one character long"); 128 if (serviceExecutor == null) throw new NullPointerException("serviceExecutor is null"); 129 if (timeoutUnits == null) throw new NullPointerException("timeoutUnits is null"); 130 131 this.kernelName = kernelName; 132 this.serviceExecutor = serviceExecutor; 133 serviceManagerFactory = new ServiceManagerFactory(this, serviceMonitor, serviceExecutor, timeoutDuration, timeoutUnits); 134 serviceManagerRegistry = new ServiceManagerRegistry(serviceManagerFactory); 135 } 136 137 /** 138 * {@inheritDoc} 139 */ 140 public void destroy() throws KernelErrorsError { 141 destroyLock.lock(); 142 try { 143 // if we are already stopped simply return 144 if (!running) { 145 return; 146 } 147 running = false; 148 } finally { 149 destroyLock.unlock(); 150 } 151 152 // destroy all services 153 serviceManagerRegistry.destroy(); 154 155 // shutdown service executor 156 if (ownsServiceExecutor) { 157 serviceExecutor.shutdown(); 158 } 159 160 // remove this kernel from the kernel factory registry 161 KernelFactory.destroyInstance(this); 162 163 // notify threads waiting for destroy to complete 164 destroyLock.lock(); 165 try { 166 destroyCondition.signalAll(); 167 } finally { 168 destroyLock.unlock(); 169 } 170 } 171 172 /** 173 * {@inheritDoc} 174 */ 175 public void waitForDestruction() { 176 destroyLock.lock(); 177 try { 178 // if we are already stopped simply return 179 if (!running) { 180 return; 181 } 182 183 // wait until destroy completes 184 destroyCondition.awaitUninterruptibly(); 185 } finally { 186 destroyLock.unlock(); 187 } 188 189 } 190 191 /** 192 * {@inheritDoc} 193 */ 194 public boolean isRunning() { 195 destroyLock.lock(); 196 try { 197 return running; 198 } finally { 199 destroyLock.unlock(); 200 } 201 } 202 203 /** 204 * {@inheritDoc} 205 */ 206 public String getKernelName() { 207 return kernelName; 208 } 209 210 /** 211 * {@inheritDoc} 212 */ 213 public void registerService(ServiceName serviceName, ServiceFactory serviceFactory) throws ServiceAlreadyExistsException, ServiceRegistrationException { 214 if (serviceName == null) throw new NullPointerException("serviceName is null"); 215 if (serviceFactory == null) throw new NullPointerException("serviceFactory is null"); 216 if (!isRunning()) { 217 throw new ServiceRegistrationException(serviceName, new IllegalStateException("Kernel is destroyed")); 218 } 219 220 serviceManagerRegistry.registerService(serviceName, serviceFactory); 221 } 222 223 /** 224 * {@inheritDoc} 225 */ 226 public void unregisterService(ServiceName serviceName) throws ServiceNotFoundException, ServiceRegistrationException { 227 if (serviceName == null) throw new NullPointerException("serviceName is null"); 228 unregisterService(serviceName, StopStrategies.SYNCHRONOUS); 229 } 230 231 /** 232 * {@inheritDoc} 233 */ 234 public void unregisterService(ServiceName serviceName, StopStrategy stopStrategy) throws ServiceNotFoundException, ServiceRegistrationException { 235 if (serviceName == null) throw new NullPointerException("serviceName is null"); 236 if (stopStrategy == null) throw new NullPointerException("stopStrategy is null"); 237 if (!isRunning()) { 238 return; 239 } 240 241 serviceManagerRegistry.unregisterService(serviceName, stopStrategy); 242 } 243 244 /** 245 * {@inheritDoc} 246 */ 247 public boolean isRegistered(ServiceName serviceName) { 248 if (serviceName == null) throw new NullPointerException("serviceName is null"); 249 if (!isRunning()) { 250 return false; 251 } 252 253 return serviceManagerRegistry.isRegistered(serviceName); 254 } 255 256 /** 257 * {@inheritDoc} 258 */ 259 public ServiceState getServiceState(ServiceName serviceName) throws ServiceNotFoundException { 260 if (serviceName == null) throw new NullPointerException("serviceName is null"); 261 ServiceManager serviceManager = getServiceManager(serviceName); 262 return serviceManager.getState(); 263 } 264 265 /** 266 * {@inheritDoc} 267 */ 268 public long getServiceStartTime(ServiceName serviceName) throws ServiceNotFoundException { 269 if (serviceName == null) throw new NullPointerException("serviceName is null"); 270 ServiceManager serviceManager = getServiceManager(serviceName); 271 return serviceManager.getStartTime(); 272 } 273 274 /** 275 * {@inheritDoc} 276 */ 277 public void startService(ServiceName serviceName) throws ServiceNotFoundException, IllegalServiceStateException, UnsatisfiedConditionsException, Exception { 278 if (serviceName == null) throw new NullPointerException("serviceName is null"); 279 startService(serviceName, false, StartStrategies.SYNCHRONOUS); 280 } 281 282 /** 283 * {@inheritDoc} 284 */ 285 public void startService(ServiceName serviceName, StartStrategy startStrategy) throws ServiceNotFoundException, IllegalServiceStateException, UnsatisfiedConditionsException, Exception { 286 if (serviceName == null) throw new NullPointerException("serviceName is null"); 287 if (startStrategy == null) throw new NullPointerException("startStrategy is null"); 288 startService(serviceName, false, startStrategy); 289 } 290 291 /** 292 * {@inheritDoc} 293 */ 294 public void startServiceRecursive(ServiceName serviceName) throws ServiceNotFoundException, IllegalServiceStateException, UnsatisfiedConditionsException, Exception { 295 if (serviceName == null) throw new NullPointerException("serviceName is null"); 296 startService(serviceName, true, StartStrategies.SYNCHRONOUS); 297 } 298 299 /** 300 * {@inheritDoc} 301 */ 302 public void startServiceRecursive(ServiceName serviceName, StartStrategy startStrategy) throws ServiceNotFoundException, IllegalServiceStateException, UnsatisfiedConditionsException, Exception { 303 if (serviceName == null) throw new NullPointerException("serviceName is null"); 304 if (startStrategy == null) throw new NullPointerException("startStrategy is null"); 305 startService(serviceName, true, startStrategy); 306 } 307 308 private void startService(ServiceName serviceName, boolean recursive, StartStrategy startStrategy) throws Exception { 309 if (startStrategy == null) throw new NullPointerException("startStrategy is null"); 310 ServiceManager serviceManager = getServiceManager(serviceName); 311 try { 312 serviceManager.start(recursive, startStrategy); 313 } catch (UnregisterServiceException e) { 314 try { 315 unregisterService(serviceName, StopStrategies.FORCE); 316 } catch (ServiceNotFoundException ignored) { 317 // that is weird, but what ever 318 } catch (ServiceRegistrationException ignored) { 319 // we are alredy throwing an exception so ignore this one 320 } 321 Throwable cause = e.getCause(); 322 if (cause instanceof Exception) { 323 throw (Exception) cause; 324 } else if (cause instanceof Error) { 325 throw (Error) cause; 326 } else { 327 throw new AssertionError(cause); 328 } 329 } 330 } 331 332 /** 333 * {@inheritDoc} 334 */ 335 public void stopService(ServiceName serviceName) throws ServiceNotFoundException, UnsatisfiedConditionsException { 336 if (serviceName == null) throw new NullPointerException("serviceName is null"); 337 stopService(serviceName, StopStrategies.SYNCHRONOUS); 338 } 339 340 /** 341 * {@inheritDoc} 342 */ 343 public void stopService(ServiceName serviceName, StopStrategy stopStrategy) throws ServiceNotFoundException, UnsatisfiedConditionsException { 344 if (serviceName == null) throw new NullPointerException("serviceName is null"); 345 if (stopStrategy == null) throw new NullPointerException("stopStrategy is null"); 346 ServiceManager serviceManager = getServiceManager(serviceName); 347 serviceManager.stop(stopStrategy); 348 } 349 350 /** 351 * {@inheritDoc} 352 */ 353 public boolean isServiceEnabled(ServiceName serviceName) throws ServiceNotFoundException { 354 if (serviceName == null) throw new NullPointerException("serviceName is null"); 355 ServiceManager serviceManager = getServiceManager(serviceName); 356 ServiceFactory serviceFactory = serviceManager.getServiceFactory(); 357 return serviceFactory.isEnabled(); 358 } 359 360 /** 361 * {@inheritDoc} 362 */ 363 public void setServiceEnabled(ServiceName serviceName, boolean enabled) throws ServiceNotFoundException { 364 if (serviceName == null) throw new NullPointerException("serviceName is null"); 365 ServiceManager serviceManager = getServiceManager(serviceName); 366 ServiceFactory serviceFactory = serviceManager.getServiceFactory(); 367 serviceFactory.setEnabled(enabled); 368 } 369 370 /** 371 * {@inheritDoc} 372 */ 373 public Object getService(ServiceName serviceName) throws ServiceNotFoundException, IllegalArgumentException { 374 if (serviceName == null) throw new NullPointerException("serviceName is null"); 375 ServiceManager serviceManager = getServiceManager(serviceName); 376 return serviceManager.getService(); 377 } 378 379 /** 380 * {@inheritDoc} 381 */ 382 public Object getService(Class type) { 383 if (type == null) throw new NullPointerException("type is null"); 384 if (!isRunning()) { 385 return null; 386 } 387 388 Object service = serviceManagerRegistry.getService(type); 389 return service; 390 } 391 392 /** 393 * {@inheritDoc} 394 */ 395 public List getServices(Class type) { 396 if (type == null) throw new NullPointerException("type is null"); 397 if (!isRunning()) { 398 return null; 399 } 400 401 List services = serviceManagerRegistry.getServices(type); 402 return services; 403 } 404 405 /** 406 * {@inheritDoc} 407 */ 408 public ServiceFactory getServiceFactory(ServiceName serviceName) throws ServiceNotFoundException { 409 if (serviceName == null) throw new NullPointerException("serviceName is null"); 410 ServiceManager serviceManager = getServiceManager(serviceName); 411 return serviceManager.getServiceFactory(); 412 } 413 414 /** 415 * {@inheritDoc} 416 */ 417 public ServiceFactory getServiceFactory(Class type) { 418 if (type == null) throw new NullPointerException("type is null"); 419 if (!isRunning()) { 420 return null; 421 } 422 423 ServiceManager serviceManager = serviceManagerRegistry.getServiceManager(type); 424 return serviceManager.getServiceFactory(); 425 } 426 427 /** 428 * {@inheritDoc} 429 */ 430 public List getServiceFactories(Class type) { 431 if (type == null) throw new NullPointerException("type is null"); 432 if (!isRunning()) { 433 return null; 434 } 435 436 List serviceManagers = serviceManagerRegistry.getServiceManagers(type); 437 List serviceFactories = new ArrayList(serviceManagers.size()); 438 for (Iterator iterator = serviceManagers.iterator(); iterator.hasNext();) { 439 ServiceManager serviceManager = (ServiceManager) iterator.next(); 440 serviceFactories.add(serviceManager.getServiceFactory()); 441 } 442 return serviceFactories; 443 } 444 445 /** 446 * {@inheritDoc} 447 */ 448 public ClassLoader getClassLoaderFor(ServiceName serviceName) throws ServiceNotFoundException { 449 if (serviceName == null) throw new NullPointerException("serviceName is null"); 450 ServiceManager serviceManager = getServiceManager(serviceName); 451 return serviceManager.getClassLoader(); 452 } 453 454 private ServiceManager getServiceManager(ServiceName serviceName) throws ServiceNotFoundException { 455 if (!isRunning()) { 456 throw new ServiceNotFoundException(serviceName); 457 } 458 459 ServiceManager serviceManager = serviceManagerRegistry.getServiceManager(serviceName); 460 return serviceManager; 461 } 462 463 /** 464 * {@inheritDoc} 465 */ 466 public void addKernelMonitor(KernelMonitor kernelMonitor) { 467 if (kernelMonitor == null) throw new NullPointerException("kernelMonitor is null"); 468 if (!isRunning()) { 469 throw new IllegalStateException("Kernel is stopped"); 470 } 471 this.kernelMonitor.addKernelMonitor(kernelMonitor); 472 } 473 474 /** 475 * {@inheritDoc} 476 */ 477 public void removeKernelMonitor(KernelMonitor kernelMonitor) { 478 if (kernelMonitor == null) throw new NullPointerException("kernelMonitor is null"); 479 this.kernelMonitor.removeKernelMonitor(kernelMonitor); 480 } 481 482 /** 483 * {@inheritDoc} 484 */ 485 public void addServiceMonitor(ServiceMonitor serviceMonitor) { 486 if (serviceMonitor == null) throw new NullPointerException("serviceMonitor is null"); 487 if (!isRunning()) { 488 throw new IllegalStateException("Kernel is stopped"); 489 } 490 addServiceMonitor(serviceMonitor, null); 491 } 492 493 /** 494 * {@inheritDoc} 495 */ 496 public void addServiceMonitor(ServiceMonitor serviceMonitor, ServiceName serviceName) { 497 if (serviceMonitor == null) throw new NullPointerException("serviceMonitor is null"); 498 if (serviceName == null) throw new NullPointerException("serviceName is null"); 499 if (!isRunning()) { 500 throw new IllegalStateException("Kernel is stopped"); 501 } 502 this.serviceMonitor.addServiceMonitor(serviceMonitor, serviceName); 503 } 504 505 /** 506 * {@inheritDoc} 507 */ 508 public void removeServiceMonitor(ServiceMonitor serviceMonitor) { 509 if (serviceMonitor == null) throw new NullPointerException("serviceMonitor is null"); 510 this.serviceMonitor.removeServiceMonitor(serviceMonitor); 511 } 512 }