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 }