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 018 package org.apache.geronimo.system.jmx; 019 020 import java.util.Iterator; 021 import javax.management.Attribute; 022 import javax.management.AttributeList; 023 import javax.management.AttributeNotFoundException; 024 import javax.management.DynamicMBean; 025 import javax.management.JMException; 026 import javax.management.ListenerNotFoundException; 027 import javax.management.MBeanInfo; 028 import javax.management.MBeanNotificationInfo; 029 import javax.management.Notification; 030 import javax.management.NotificationBroadcasterSupport; 031 import javax.management.NotificationEmitter; 032 import javax.management.NotificationFilter; 033 import javax.management.NotificationListener; 034 import javax.management.ObjectName; 035 import javax.management.ReflectionException; 036 import javax.management.MBeanRegistration; 037 import javax.management.MBeanServer; 038 039 import org.apache.commons.logging.Log; 040 import org.apache.commons.logging.LogFactory; 041 import org.apache.geronimo.gbean.GOperationSignature; 042 import org.apache.geronimo.gbean.AbstractName; 043 import org.apache.geronimo.gbean.AbstractNameQuery; 044 import org.apache.geronimo.kernel.NoSuchAttributeException; 045 import org.apache.geronimo.kernel.NoSuchOperationException; 046 import org.apache.geronimo.kernel.Kernel; 047 import org.apache.geronimo.kernel.lifecycle.LifecycleListener; 048 import org.apache.geronimo.kernel.management.NotificationType; 049 050 /** 051 * @version $Rev: 550523 $ $Date: 2007-06-25 11:02:09 -0400 (Mon, 25 Jun 2007) $ 052 */ 053 public final class MBeanGBeanBridge implements MBeanRegistration, DynamicMBean, NotificationEmitter { 054 private static final Log log = LogFactory.getLog(MBeanGBeanBridge.class); 055 056 /** 057 * The kernel 058 */ 059 private final Kernel kernel; 060 061 /** 062 * The unique name of this service. 063 */ 064 private final AbstractName abstractName; 065 private final ObjectName objectName; 066 private final AbstractNameQuery pattern; 067 068 /** 069 * The mbean info 070 */ 071 private final MBeanInfo mbeanInfo; 072 073 /** 074 * The broadcaster for notifications 075 */ 076 private final NotificationBroadcasterSupport notificationBroadcaster = new NotificationBroadcasterSupport(); 077 private final LifecycleBridge lifecycleBridge; 078 079 public MBeanGBeanBridge(Kernel kernel, AbstractName abstractName, ObjectName objectName, MBeanInfo mbeanInfo) { 080 this.kernel = kernel; 081 this.abstractName = abstractName; 082 this.pattern = new AbstractNameQuery(abstractName); 083 this.mbeanInfo = mbeanInfo; 084 this.objectName = objectName; 085 lifecycleBridge = new LifecycleBridge(abstractName, objectName, notificationBroadcaster); 086 } 087 088 public ObjectName getObjectName() { 089 return objectName; 090 } 091 092 public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception { 093 return objectName; 094 } 095 096 public void postRegister(Boolean registrationDone) { 097 if (Boolean.TRUE.equals(registrationDone)) { 098 // fire the loaded event from the gbeanMBean.. it was already fired from the GBeanInstance when it was created 099 kernel.getLifecycleMonitor().addLifecycleListener(lifecycleBridge, pattern); 100 lifecycleBridge.loaded(abstractName); 101 } 102 } 103 104 public void preDeregister() { 105 kernel.getLifecycleMonitor().removeLifecycleListener(lifecycleBridge); 106 lifecycleBridge.unloaded(abstractName); 107 } 108 109 public void postDeregister() { 110 } 111 112 public MBeanInfo getMBeanInfo() { 113 return mbeanInfo; 114 } 115 116 public Object getAttribute(String attributeName) throws ReflectionException, AttributeNotFoundException { 117 try { 118 return kernel.getAttribute(abstractName, attributeName); 119 } catch (NoSuchAttributeException e) { 120 throw (AttributeNotFoundException)new AttributeNotFoundException(attributeName).initCause(e); 121 } catch (Exception e) { 122 throw new ReflectionException(e); 123 } 124 } 125 126 public void setAttribute(Attribute attribute) throws ReflectionException, AttributeNotFoundException { 127 String attributeName = attribute.getName(); 128 Object attributeValue = attribute.getValue(); 129 try { 130 kernel.setAttribute(abstractName, attributeName, attributeValue); 131 } catch (NoSuchAttributeException e) { 132 throw (AttributeNotFoundException)new AttributeNotFoundException(attributeName).initCause(e); 133 } catch (Exception e) { 134 throw new ReflectionException(e); 135 } 136 } 137 138 public AttributeList getAttributes(String[] attributes) { 139 AttributeList results = new AttributeList(attributes.length); 140 for (int i = 0; i < attributes.length; i++) { 141 String name = attributes[i]; 142 try { 143 Object value = getAttribute(name); 144 results.add(new Attribute(name, value)); 145 } catch (JMException e) { 146 log.warn("Exception while getting attribute " + name, e); 147 } 148 } 149 return results; 150 } 151 152 public AttributeList setAttributes(AttributeList attributes) { 153 AttributeList results = new AttributeList(attributes.size()); 154 for (Iterator iterator = attributes.iterator(); iterator.hasNext();) { 155 Attribute attribute = (Attribute) iterator.next(); 156 try { 157 setAttribute(attribute); 158 results.add(attribute); 159 } catch (JMException e) { 160 log.warn("Exception while setting attribute " + attribute.getName(), e); 161 } 162 } 163 return results; 164 } 165 166 public Object invoke(String operationName, Object[] arguments, String[] types) throws ReflectionException { 167 try { 168 return kernel.invoke(abstractName, operationName, arguments, types); 169 } catch (NoSuchOperationException e) { 170 throw new ReflectionException((NoSuchMethodException)new NoSuchMethodException(new GOperationSignature(operationName, types).toString()).initCause(e)); 171 } catch (Exception e) { 172 throw new ReflectionException(e); 173 } 174 } 175 176 public MBeanNotificationInfo[] getNotificationInfo() { 177 return new MBeanNotificationInfo[]{ 178 new MBeanNotificationInfo(NotificationType.TYPES, "javax.management.Notification", "J2EE Notifications") 179 }; 180 } 181 182 public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { 183 notificationBroadcaster.addNotificationListener(listener, filter, handback); 184 } 185 186 public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { 187 notificationBroadcaster.removeNotificationListener(listener); 188 } 189 190 public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { 191 notificationBroadcaster.removeNotificationListener(listener, filter, handback); 192 } 193 194 public String toString() { 195 return abstractName.toString(); 196 } 197 198 private static class LifecycleBridge implements LifecycleListener { 199 /** 200 * Sequence number used for notifications 201 */ 202 private long sequence; 203 204 /** 205 * AbstractName of this MBean 206 */ 207 private final AbstractName mbeanAbstractName; 208 209 /** 210 * ObjectName of this MBean 211 */ 212 private final ObjectName objectName; 213 214 /** 215 * The notification broadcaster to use 216 */ 217 private final NotificationBroadcasterSupport notificationBroadcaster; 218 219 public LifecycleBridge(AbstractName mbeanAbstractName, ObjectName objectName, NotificationBroadcasterSupport notificationBroadcaster) { 220 this.mbeanAbstractName = mbeanAbstractName; 221 this.objectName = objectName; 222 this.notificationBroadcaster = notificationBroadcaster; 223 } 224 225 public void loaded(AbstractName abstractName) { 226 if (mbeanAbstractName.equals(abstractName)) { 227 notificationBroadcaster.sendNotification(new Notification(NotificationType.OBJECT_CREATED, objectName, nextSequence())); 228 } 229 } 230 231 public void starting(AbstractName abstractName) { 232 if (mbeanAbstractName.equals(abstractName)) { 233 notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STARTING, objectName, nextSequence())); 234 } 235 } 236 237 public void running(AbstractName abstractName) { 238 if (mbeanAbstractName.equals(abstractName)) { 239 notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_RUNNING, objectName, nextSequence())); 240 } 241 } 242 243 public void stopping(AbstractName abstractName) { 244 if (mbeanAbstractName.equals(abstractName)) { 245 notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STOPPING, objectName, nextSequence())); 246 } 247 } 248 249 public void stopped(AbstractName abstractName) { 250 if (mbeanAbstractName.equals(abstractName)) { 251 notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STOPPED, objectName, nextSequence())); 252 } 253 } 254 255 public void failed(AbstractName abstractName) { 256 if (mbeanAbstractName.equals(abstractName)) { 257 notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_FAILED, objectName, nextSequence())); 258 } 259 } 260 261 public void unloaded(AbstractName abstractName) { 262 if (mbeanAbstractName.equals(abstractName)) { 263 notificationBroadcaster.sendNotification(new Notification(NotificationType.OBJECT_DELETED, objectName, nextSequence())); 264 } 265 } 266 267 public synchronized long nextSequence() { 268 return sequence++; 269 } 270 } 271 }