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 }