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 }