001 /**
002 *
003 * Copyright 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 package org.apache.geronimo.system.jmx;
018
019 import java.util.HashMap;
020 import java.util.Iterator;
021 import java.util.Map;
022 import java.util.Set;
023 import java.util.Collections;
024 import javax.management.InstanceAlreadyExistsException;
025 import javax.management.InstanceNotFoundException;
026 import javax.management.JMException;
027 import javax.management.JMRuntimeException;
028 import javax.management.MBeanInfo;
029 import javax.management.MBeanServer;
030 import javax.management.ObjectName;
031
032 import org.apache.commons.logging.Log;
033 import org.apache.commons.logging.LogFactory;
034 import org.apache.geronimo.gbean.GBeanLifecycle;
035 import org.apache.geronimo.gbean.GBeanInfo;
036 import org.apache.geronimo.gbean.GBeanInfoBuilder;
037 import org.apache.geronimo.gbean.AbstractName;
038 import org.apache.geronimo.gbean.AbstractNameQuery;
039 import org.apache.geronimo.kernel.GBeanNotFoundException;
040 import org.apache.geronimo.kernel.Kernel;
041 import org.apache.geronimo.kernel.lifecycle.LifecycleAdapter;
042
043 /**
044 * @version $Rev: 430508 $ $Date: 2006-08-10 12:56:47 -0700 (Thu, 10 Aug 2006) $
045 */
046 public class MBeanServerKernelBridge implements GBeanLifecycle {
047 private static final Log log = LogFactory.getLog(MBeanServerKernelBridge.class);
048 private static final AbstractNameQuery ALL = new AbstractNameQuery(null, Collections.EMPTY_MAP, Collections.EMPTY_SET);
049
050 private final HashMap registry = new HashMap();
051 private final Kernel kernel;
052 private final MBeanServer mbeanServer;
053
054 // todo remove this as soon as Geronimo supports factory beans
055 public MBeanServerKernelBridge(Kernel kernel, MBeanServerReference mbeanServerReference) {
056 this(kernel, mbeanServerReference.getMBeanServer());
057 }
058
059 public MBeanServerKernelBridge(Kernel kernel, MBeanServer mbeanServer) {
060 this.kernel = kernel;
061 this.mbeanServer = mbeanServer;
062 }
063
064 public void doStart() {
065 kernel.getLifecycleMonitor().addLifecycleListener(new GBeanRegistrationListener(), ALL);
066
067 Set allNames = kernel.listGBeans(ALL);
068 for (Iterator iterator = allNames.iterator(); iterator.hasNext();) {
069 AbstractName abstractName = (AbstractName) iterator.next();
070 register(abstractName);
071 }
072 }
073
074 public void doFail() {
075 doStop();
076 }
077
078 public void doStop() {
079 // unregister all of our GBeans from the MBeanServer
080 Map beans;
081 synchronized (this) {
082 beans = new HashMap(registry);
083 registry.clear();
084 }
085 for (Iterator i = beans.values().iterator(); i.hasNext();) {
086 MBeanGBeanBridge mbeanGBeanBridge = (MBeanGBeanBridge) i.next();
087 ObjectName objectName = mbeanGBeanBridge.getObjectName();
088 try {
089 mbeanServer.unregisterMBean(objectName);
090 } catch (Exception e) {
091 // ignore
092 }
093 }
094 }
095
096 private void register(AbstractName abstractName) {
097 try {
098 MBeanGBeanBridge mbeanGBeanBridge;
099 synchronized (this) {
100 if (registry.containsKey(abstractName)) {
101 return;
102 }
103 MBeanInfo mbeanInfo = JMXUtil.toMBeanInfo(kernel.getGBeanInfo(abstractName));
104 mbeanGBeanBridge = new MBeanGBeanBridge(kernel, abstractName, abstractName.getObjectName(), mbeanInfo);
105 registry.put(abstractName, mbeanGBeanBridge);
106 }
107 mbeanServer.registerMBean(mbeanGBeanBridge, mbeanGBeanBridge.getObjectName());
108 } catch (GBeanNotFoundException e) {
109 // ignore - gbean already unregistered
110 } catch (InstanceAlreadyExistsException e) {
111 // ignore - gbean already has an mbean shadow object
112 } catch (Exception e) {
113 log.warn("Unable to register MBean shadow object for GBean", unwrapJMException(e));
114 }
115 }
116
117 private void unregister(AbstractName abstractName) {
118 MBeanGBeanBridge mbeanGBeanBridge;
119 synchronized (this) {
120 mbeanGBeanBridge = (MBeanGBeanBridge) registry.remove(abstractName);
121 }
122
123 if (mbeanGBeanBridge != null) {
124 try {
125 mbeanServer.unregisterMBean(mbeanGBeanBridge.getObjectName());
126 } catch (InstanceNotFoundException e) {
127 // ignore - something else may have unregistered us
128 // if there truely is no GBean then we will catch it below whwn we call the superclass
129 } catch (Exception e) {
130 log.warn("Unable to unregister MBean shadow object for GBean", unwrapJMException(e));
131 }
132 }
133 }
134
135 private Throwable unwrapJMException(Throwable cause) {
136 while ((cause instanceof JMException || cause instanceof JMRuntimeException) && cause.getCause() != null) {
137 cause = cause.getCause();
138 }
139 return cause;
140 }
141
142 private class GBeanRegistrationListener extends LifecycleAdapter {
143 public void loaded(AbstractName abstractName) {
144 register(abstractName);
145 }
146
147 public void unloaded(AbstractName abstractName) {
148 unregister(abstractName);
149 }
150 }
151
152 public static final GBeanInfo GBEAN_INFO;
153
154 static {
155 GBeanInfoBuilder infoFactory = GBeanInfoBuilder.createStatic(MBeanServerKernelBridge.class);
156 infoFactory.addAttribute("kernel", Kernel.class, false);
157 infoFactory.addReference("MBeanServerReference", MBeanServerReference.class);
158 infoFactory.setConstructor(new String[]{"kernel", "MBeanServerReference"});
159 GBEAN_INFO = infoFactory.getBeanInfo();
160 }
161
162 public static GBeanInfo getGBeanInfo() {
163 return GBEAN_INFO;
164 }
165 }