001    /**
002     *
003     * Copyright 2003-2004 The Apache Software Foundation
004     *
005     *  Licensed under the Apache License, Version 2.0 (the "License");
006     *  you may not use this file except in compliance with the License.
007     *  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    
018    package org.apache.geronimo.kernel.basic;
019    
020    import java.util.Date;
021    import java.util.HashSet;
022    import java.util.Iterator;
023    import java.util.LinkedList;
024    import java.util.Set;
025    import javax.management.ObjectName;
026    
027    import org.apache.commons.logging.Log;
028    import org.apache.commons.logging.LogFactory;
029    import org.apache.geronimo.gbean.GBeanData;
030    import org.apache.geronimo.gbean.GBeanInfo;
031    import org.apache.geronimo.gbean.AbstractNameQuery;
032    import org.apache.geronimo.gbean.AbstractName;
033    import org.apache.geronimo.gbean.runtime.GBeanInstance;
034    import org.apache.geronimo.gbean.runtime.LifecycleBroadcaster;
035    import org.apache.geronimo.kernel.DependencyManager;
036    import org.apache.geronimo.kernel.GBeanAlreadyExistsException;
037    import org.apache.geronimo.kernel.GBeanNotFoundException;
038    import org.apache.geronimo.kernel.InternalKernelException;
039    import org.apache.geronimo.kernel.Kernel;
040    import org.apache.geronimo.kernel.KernelGBean;
041    import org.apache.geronimo.kernel.KernelRegistry;
042    import org.apache.geronimo.kernel.NoSuchAttributeException;
043    import org.apache.geronimo.kernel.NoSuchOperationException;
044    import org.apache.geronimo.kernel.Jsr77Naming;
045    import org.apache.geronimo.kernel.Naming;
046    import org.apache.geronimo.kernel.management.State;
047    import org.apache.geronimo.kernel.lifecycle.LifecycleMonitor;
048    import org.apache.geronimo.kernel.proxy.ProxyManager;
049    
050    
051    /**
052     * The core of a Geronimo instance.
053     * A Kernel is responsible for managing the Configurations that comprise a
054     * Geronimo system and exposing them using JMX. Each Kernel is associated
055     * with an MBeanServer that is used to register the Configurations themselves
056     * and the MBeans they define.
057     * <p/>
058     * Dependencies between MBeans are handled by a dedicated DependencyManager
059     * that is responsible for tracking those dependencies and ensuring that the
060     * dependent objects follow the appropriate lifecycle and receive appropriate
061     * notifications.
062     * <p/>
063     * The Kernel also provides a ConfigurationStore which is used to stage
064     * installed Configurations (providing a local filesystem based classpath) and
065     * used hold the persistent state of each Configuration. This allows
066     * Configurations to restart in the event of system failure.
067     * 
068     * TODO: Describe the order of method invocation (e.g. if loadGbean may be before boot)
069     *
070     * @version $Rev:386276 $ $Date: 2006-04-24 00:27:37 -0700 (Mon, 24 Apr 2006) $
071     */
072    public class BasicKernel implements Kernel {
073        /**
074         * Helper objects for invoke and getAttribute
075         */
076        private static final String[] NO_TYPES = new String[0];
077        private static final Object[] NO_ARGS = new Object[0];
078    
079        /**
080         * Name of this kernel
081         */
082        private final String kernelName;
083    
084        /**
085         * The log
086         */
087        private Log log;
088    
089        /**
090         * Is this kernel running?
091         */
092        private boolean running;
093    
094        /**
095         * The timestamp when the kernel was started
096         */
097        private Date bootTime;
098    
099        /**
100         * The registry
101         */
102        private final BasicRegistry registry;
103    
104        /**
105         * Listeners for when the kernel shutdown
106         */
107        private final LinkedList shutdownHooks = new LinkedList();
108    
109        /**
110         * This manager is used by the kernel to manage dependencies between gbeans
111         */
112        private DependencyManager dependencyManager;
113    
114        /**
115         * Monitors the lifecycle of all gbeans.
116         */
117        private BasicLifecycleMonitor lifecycleMonitor;
118        private LifecycleMonitor publicLifecycleMonitor;
119    
120        /**
121         * This factory gbean proxies, and tracks all proxies in the system
122         */
123        private ProxyManager proxyManager;
124    
125        private static final Naming INSTANCE = new Jsr77Naming();
126    
127        /**
128         * Construct a Kernel with the specified name.
129         *
130         * @param kernelName the name of the kernel
131         */
132        public BasicKernel(String kernelName) {
133            if (kernelName.indexOf(':') >= 0 || kernelName.indexOf('*') >= 0 || kernelName.indexOf('?') >= 0) {
134                throw new IllegalArgumentException("Kernel name may not contain a ':', '*' or '?' character");
135            }
136            this.kernelName = kernelName;
137            this.registry = new BasicRegistry();
138        }
139    
140        public String getKernelName() {
141            return kernelName;
142        }
143    
144        public Naming getNaming() {
145            return INSTANCE;
146        }
147    
148        /**
149         * @deprecated this will be removed as when we add generalized dependencies to gbeans... the only current user is Configuration
150         */
151        public DependencyManager getDependencyManager() {
152            return dependencyManager;
153        }
154    
155        /**
156         * Gets the lifecycle monitor.
157         * @deprecated don't use this yet... it may change or go away
158         */
159        public LifecycleMonitor getLifecycleMonitor() {
160            return publicLifecycleMonitor;
161        }
162    
163        /**
164         * Gets the proxy manager.
165         * @deprecated don't use this yet... it may change or go away
166         */
167        public ProxyManager getProxyManager() {
168            return proxyManager;
169        }
170    
171        public Object getAttribute(ObjectName objectName, String attributeName) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
172            GBeanInstance gbeanInstance = registry.getGBeanInstance(objectName);
173            return gbeanInstance.getAttribute(attributeName);
174        }
175    
176        public Object getAttribute(AbstractName abstractName, String attributeName) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
177            GBeanInstance gbeanInstance = registry.getGBeanInstance(abstractName);
178            return gbeanInstance.getAttribute(attributeName);
179        }
180    
181        public Object getAttribute(String shortName, String attributeName) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
182            return getAttribute(shortName, null, attributeName);
183        }
184    
185        public Object getAttribute(Class type, String attributeName) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
186            return getAttribute(null, type, attributeName);
187        }
188    
189        public Object getAttribute(String shortName, Class type, String attributeName) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
190            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
191            return gbeanInstance.getAttribute(attributeName);
192        }
193    
194        public void setAttribute(AbstractName abstractName, String attributeName, Object attributeValue) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
195            GBeanInstance gbeanInstance = registry.getGBeanInstance(abstractName);
196            gbeanInstance.setAttribute(attributeName, attributeValue);
197        }
198    
199        public void setAttribute(String shortName, String attributeName, Object attributeValue) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
200            setAttribute(shortName, null, attributeName, attributeValue);
201        }
202    
203        public void setAttribute(Class type, String attributeName, Object attributeValue) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
204            setAttribute(null, type, attributeName, attributeValue);
205        }
206    
207        public void setAttribute(String shortName, Class type, String attributeName, Object attributeValue) throws GBeanNotFoundException, NoSuchAttributeException, Exception {
208            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
209            gbeanInstance.setAttribute(attributeName, attributeValue);
210        }
211    
212        public Object invoke(ObjectName objectName, String methodName) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
213            return invoke(objectName, methodName, NO_ARGS, NO_TYPES);
214        }
215    
216        public Object invoke(AbstractName abstractName, String methodName) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
217            return invoke(abstractName, methodName, NO_ARGS, NO_TYPES);
218        }
219    
220        public Object invoke(String shortName, String methodName) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
221            return invoke(shortName, null, methodName, NO_ARGS, NO_TYPES);
222        }
223    
224        public Object invoke(Class type, String methodName) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
225            return invoke(null, type, methodName, NO_ARGS, NO_TYPES);
226        }
227    
228        public Object invoke(String shortName, Class type, String methodName) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
229            return invoke(shortName, type, methodName, NO_ARGS, NO_TYPES);
230        }
231    
232        public Object invoke(ObjectName objectName, String methodName, Object[] args, String[] types) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
233            GBeanInstance gbeanInstance = registry.getGBeanInstance(objectName);
234            return gbeanInstance.invoke(methodName, args, types);
235        }
236    
237        public Object invoke(AbstractName abstractName, String methodName, Object[] args, String[] types) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
238            GBeanInstance gbeanInstance = registry.getGBeanInstance(abstractName);
239            return gbeanInstance.invoke(methodName, args, types);
240        }
241    
242        public Object invoke(String shortName, String methodName, Object[] args, String[] types) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
243            return invoke(shortName, null, methodName, args, types);
244        }
245    
246        public Object invoke(Class type, String methodName, Object[] args, String[] types) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
247            return invoke(null, type,methodName, args, types);
248        }
249    
250        public Object invoke(String shortName, Class type, String methodName, Object[] args, String[] types) throws GBeanNotFoundException, NoSuchOperationException, InternalKernelException, Exception {
251            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
252            return gbeanInstance.invoke(methodName, args, types);
253        }
254    
255        public boolean isLoaded(AbstractName name) {
256            return registry.isRegistered(name);
257        }
258    
259        public boolean isLoaded(String shortName) {
260            return isLoaded(shortName, null);
261        }
262    
263        public boolean isLoaded(Class type) {
264            return isLoaded(null, type);
265        }
266    
267        public boolean isLoaded(String shortName, Class type) {
268            try {
269                registry.getGBeanInstance(shortName, type);
270                return true;
271            } catch (GBeanNotFoundException e) {
272                // Dain: yes this is flow control using exceptions, but I'm too lazy to add another isRegistered method to the basic registry
273                return false;
274            }
275        }
276    
277        public Object getGBean(String shortName) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
278            return getGBean(shortName, null);
279        }
280    
281        public Object getGBean(Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
282            return getGBean(null, type);
283        }
284    
285        public Object getGBean(String shortName, Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
286            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
287            if (gbeanInstance.getState() != State.RUNNING_INDEX) {
288                throw new IllegalStateException("GBean is not running: " + gbeanInstance.getAbstractName());
289            }
290            return gbeanInstance.getTarget();
291        }
292    
293        public Object getGBean(ObjectName name) throws GBeanNotFoundException, InternalKernelException, IllegalStateException  {
294            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
295            if (gbeanInstance.getState() != State.RUNNING_INDEX) {
296                throw new IllegalStateException("GBean is not running: " + name);
297            }
298            return gbeanInstance.getTarget();
299        }
300    
301        public Object getGBean(AbstractName name) throws GBeanNotFoundException, InternalKernelException, IllegalStateException  {
302            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
303            if (gbeanInstance.getState() != State.RUNNING_INDEX) {
304                throw new IllegalStateException("GBean is not running: " + name);
305            }
306            return gbeanInstance.getTarget();
307        }
308    
309        public GBeanInfo getGBeanInfo(ObjectName name) throws GBeanNotFoundException {
310            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
311            return gbeanInstance.getGBeanInfo();
312        }
313    
314        public GBeanInfo getGBeanInfo(AbstractName name) throws GBeanNotFoundException {
315            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
316            return gbeanInstance.getGBeanInfo();
317        }
318    
319        public GBeanInfo getGBeanInfo(String shortName) throws GBeanNotFoundException {
320            return getGBeanInfo(shortName, null);
321        }
322    
323        public GBeanInfo getGBeanInfo(Class type) throws GBeanNotFoundException {
324            return getGBeanInfo(null, type);
325        }
326    
327        public GBeanInfo getGBeanInfo(String shortName, Class type) throws GBeanNotFoundException {
328            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
329            return gbeanInstance.getGBeanInfo();
330        }
331    
332        public GBeanData getGBeanData(AbstractName name) throws GBeanNotFoundException, InternalKernelException {
333            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
334            return gbeanInstance.getGBeanData();
335        }
336    
337        public GBeanData getGBeanData(String shortName) throws GBeanNotFoundException, InternalKernelException {
338            return getGBeanData(shortName, null);
339        }
340    
341        public GBeanData getGBeanData(Class type) throws GBeanNotFoundException, InternalKernelException {
342            return getGBeanData(null, type);
343        }
344    
345        public GBeanData getGBeanData(String shortName, Class type) throws GBeanNotFoundException, InternalKernelException {
346            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
347            return gbeanInstance.getGBeanData();
348        }
349    
350        public void loadGBean(GBeanData gbeanData, ClassLoader classLoader) throws GBeanAlreadyExistsException, InternalKernelException {
351            AbstractName abstractName = gbeanData.getAbstractName();
352            Set interfaces = gbeanData.getGBeanInfo().getInterfaces();
353            LifecycleBroadcaster lifecycleBroadcaster = lifecycleMonitor.createLifecycleBroadcaster(abstractName, interfaces);
354            GBeanInstance gbeanInstance = new GBeanInstance(gbeanData, this, dependencyManager, lifecycleBroadcaster, classLoader);
355            registry.register(gbeanInstance);
356            lifecycleBroadcaster.fireLoadedEvent();        
357        }
358    
359        public void startGBean(AbstractName name) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
360            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
361            gbeanInstance.start();
362        }
363    
364        public void startGBean(String shortName) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
365            startGBean(shortName, null);
366        }
367    
368        public void startGBean(Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
369            startGBean(null, type);
370        }
371    
372        public void startGBean(String shortName, Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
373            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
374            gbeanInstance.start();
375        }
376    
377        public void startRecursiveGBean(AbstractName name) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
378            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
379            gbeanInstance.startRecursive();
380        }
381    
382        public void startRecursiveGBean(String shortName) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
383            startRecursiveGBean(shortName, null);
384        }
385    
386        public void startRecursiveGBean(Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
387            startRecursiveGBean(null, type);
388        }
389    
390        public void startRecursiveGBean(String shortName, Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
391            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
392            gbeanInstance.startRecursive();
393        }
394    
395        public boolean isRunning(AbstractName name) {
396            try {
397                GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
398                return gbeanInstance.getState() == State.RUNNING_INDEX;
399            } catch (GBeanNotFoundException e) {
400                return false;
401            }
402        }
403    
404        public boolean isRunning(String shortName) {
405            return isRunning(shortName, null);
406        }
407    
408        public boolean isRunning(Class type) {
409            return isRunning(null, type);
410        }
411    
412        public boolean isRunning(String shortName, Class type) {
413            try {
414                GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
415                return gbeanInstance.getState() == State.RUNNING_INDEX;
416            } catch (GBeanNotFoundException e) {
417                return false;
418            }
419        }
420    
421        public void stopGBean(AbstractName name) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
422            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
423            gbeanInstance.stop();
424        }
425    
426        public void stopGBean(String shortName) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
427            stopGBean(shortName, null);
428        }
429    
430        public void stopGBean(Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
431            stopGBean(null, type);
432        }
433    
434        public void stopGBean(String shortName, Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
435            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
436            gbeanInstance.stop();
437        }
438    
439        public void unloadGBean(AbstractName name) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
440            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
441            gbeanInstance.die();
442            registry.unregister(name);
443        }
444    
445        public void unloadGBean(String shortName) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
446            unloadGBean(shortName, null);
447        }
448    
449        public void unloadGBean(Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
450            unloadGBean(null, type);
451        }
452    
453        public void unloadGBean(String shortName, Class type) throws GBeanNotFoundException, InternalKernelException, IllegalStateException {
454            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
455            AbstractName name = gbeanInstance.getAbstractName();
456            gbeanInstance.die();
457            registry.unregister(name);
458        }
459    
460        public int getGBeanState(ObjectName name) throws GBeanNotFoundException {
461            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
462            return gbeanInstance.getState();
463        }
464    
465        public int getGBeanState(AbstractName name) throws GBeanNotFoundException {
466            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
467            return gbeanInstance.getState();
468        }
469    
470        public int getGBeanState(String shortName) throws GBeanNotFoundException {
471            return getGBeanState(shortName, null);
472        }
473    
474        public int getGBeanState(Class type) throws GBeanNotFoundException {
475            return getGBeanState(null, type);
476        }
477    
478        public int getGBeanState(String shortName, Class type) throws GBeanNotFoundException {
479            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
480            return gbeanInstance.getState();
481        }
482    
483        public long getGBeanStartTime(AbstractName name) throws GBeanNotFoundException {
484            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
485            return gbeanInstance.getStartTime();
486        }
487    
488        public long getGBeanStartTime(String shortName) throws GBeanNotFoundException {
489            return getGBeanStartTime(shortName, null);
490        }
491    
492        public long getGBeanStartTime(Class type) throws GBeanNotFoundException {
493            return getGBeanStartTime(null, type);
494        }
495    
496        public long getGBeanStartTime(String shortName, Class type) throws GBeanNotFoundException {
497            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
498            return gbeanInstance.getStartTime();
499        }
500    
501        public Set listGBeans(ObjectName pattern) {
502            Set gbeans = registry.listGBeans(pattern);
503    
504            Set result = new HashSet(gbeans.size());
505            for (Iterator i = gbeans.iterator(); i.hasNext();) {
506                GBeanInstance instance = (GBeanInstance) i.next();
507                result.add(instance.getObjectNameObject());
508            }
509            return result;
510        }
511    
512        public Set listGBeans(Set patterns) {
513            Set gbeans = new HashSet();
514            for (Iterator iterator = patterns.iterator(); iterator.hasNext();) {
515                Object pattern = iterator.next();
516                if (pattern instanceof ObjectName) {
517                    gbeans.addAll(listGBeans((ObjectName)pattern));
518                } else if (pattern instanceof AbstractNameQuery) {
519                    gbeans.addAll(listGBeans((AbstractNameQuery)pattern));
520                }
521            }
522            return gbeans;
523        }
524    
525        public Set listGBeans(AbstractNameQuery query) {
526            Set gbeans = registry.listGBeans(query);
527            Set result = new HashSet(gbeans.size());
528            for (Iterator i = gbeans.iterator(); i.hasNext();) {
529                GBeanInstance instance = (GBeanInstance) i.next();
530                result.add(instance.getAbstractName());
531            }
532            return result;
533        }
534    
535        public Set listGBeansByInterface(String[] interfaces) {
536            Set gbeans = new HashSet();
537            Set all = listGBeans((AbstractNameQuery)null);
538            for (Iterator it = all.iterator(); it.hasNext();) {
539                AbstractName name = (AbstractName) it.next();
540                try {
541                    GBeanInfo info = getGBeanInfo(name);
542                    Set intfs = info.getInterfaces();
543                    for (int i = 0; i < interfaces.length; i++) {
544                        String candidate = interfaces[i];
545                        if(intfs.contains(candidate)) {
546                            gbeans.add(name);
547                            break;
548                        }
549                    }
550                } catch (GBeanNotFoundException e) {}
551            }
552            return gbeans;
553        }
554    
555        public AbstractName getAbstractNameFor(Object service) {
556            if(!running) {
557                return null;
558            }
559    
560            // check if service is a proxy
561            AbstractName name = proxyManager.getProxyTarget(service);
562            if (name != null) {
563                return name;
564            }
565    
566            // try the registry
567            GBeanInstance gbeanInstance = registry.getGBeanInstanceByInstance(service);
568            if (gbeanInstance != null) {
569                return gbeanInstance.getAbstractName();
570            }
571    
572            // didn't fing the name
573            return null;
574        }
575    
576        public String getShortNameFor(Object service) {
577            AbstractName name = getAbstractNameFor(service);
578            if (name != null) {
579                return (String) name.getName().get("name");
580            }
581            return null;
582        }
583    
584        /**
585         * Boot this Kernel, triggering the instantiation of the MBeanServer and DependencyManager,
586         * and the registration of ConfigurationStore
587         *
588         * @throws java.lang.Exception if the boot fails
589         */
590        public void boot() throws Exception {
591            if (running) {
592                return;
593            }
594            bootTime = new Date();
595            log = LogFactory.getLog(BasicKernel.class.getName());
596            log.debug("Starting boot");
597    
598            // todo cleanup when boot fails
599            KernelRegistry.registerKernel(this);
600    
601            registry.start(this);
602    
603            lifecycleMonitor = new BasicLifecycleMonitor(this);
604            publicLifecycleMonitor = new LifecycleMonitorFlyweight(lifecycleMonitor);
605            dependencyManager = new BasicDependencyManager(publicLifecycleMonitor);
606            proxyManager = new BasicProxyManager(this);
607    
608            // load and start the kernel gbean
609            GBeanData kernelGBeanData = new GBeanData(KERNEL_NAME, KernelGBean.GBEAN_INFO);
610            loadGBean(kernelGBeanData, getClass().getClassLoader());
611            startGBean(KERNEL_NAME);
612    
613            running = true;
614            log.debug("Booted");
615        }
616    
617        public Date getBootTime() {
618            return bootTime;
619        }
620    
621        public void registerShutdownHook(Runnable hook) {
622            assert hook != null : "Shutdown hook was null";
623            synchronized (shutdownHooks) {
624                shutdownHooks.add(hook);
625            }
626        }
627    
628        public void unregisterShutdownHook(Runnable hook) {
629            synchronized (shutdownHooks) {
630                shutdownHooks.remove(hook);
631            }
632        }
633    
634        /**
635         * Shut down this kernel instance, unregistering the MBeans and releasing
636         * the MBeanServer.
637         */
638        public void shutdown() {
639            if (!running) {
640                return;
641            }
642            running = false;
643            log.debug("Starting kernel shutdown");
644    
645            notifyShutdownHooks();
646    
647            registry.stop();
648    
649            dependencyManager.close();
650            dependencyManager = null;
651    
652            synchronized (this) {
653                notify();
654            }
655    
656            KernelRegistry.unregisterKernel(this);
657    
658            log.debug("Kernel shutdown complete");
659        }
660    
661        private void notifyShutdownHooks() {
662            while (!shutdownHooks.isEmpty()) {
663                Runnable hook;
664                synchronized (shutdownHooks) {
665                    hook = (Runnable) shutdownHooks.removeFirst();
666                }
667                try {
668                    hook.run();
669                } catch (Throwable e) {
670                    log.warn("Error from kernel shutdown hook", e);
671                }
672            }
673        }
674    
675        public boolean isRunning() {
676            return running;
677        }
678    
679        public ClassLoader getClassLoaderFor(AbstractName name) throws GBeanNotFoundException {
680            GBeanInstance gbeanInstance = registry.getGBeanInstance(name);
681            return gbeanInstance.getClassLoader();
682        }
683    
684        public ClassLoader getClassLoaderFor(String shortName) throws GBeanNotFoundException {
685            return getClassLoaderFor(shortName, null);
686        }
687    
688        public ClassLoader getClassLoaderFor(Class type) throws GBeanNotFoundException {
689            return getClassLoaderFor(null, type);
690        }
691    
692        public ClassLoader getClassLoaderFor(String shortName, Class type) throws GBeanNotFoundException {
693            GBeanInstance gbeanInstance = registry.getGBeanInstance(shortName, type);
694            return gbeanInstance.getClassLoader();
695        }
696    
697        /**
698         * @deprecated Experimental feature
699         */
700        public String getStateReason(AbstractName abstractName) {
701            try {
702                GBeanInstance gbeanInstance = registry.getGBeanInstance(abstractName);
703                return gbeanInstance.getStateReason();
704            } catch (GBeanNotFoundException e) {
705                return null;
706            }
707        }
708    }