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