/** * * Copyright 2003-2004 The Apache Software Foundation * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.geronimo.system.jmx; import java.util.Iterator; import javax.management.Attribute; import javax.management.AttributeList; import javax.management.AttributeNotFoundException; import javax.management.DynamicMBean; import javax.management.JMException; import javax.management.ListenerNotFoundException; import javax.management.MBeanInfo; import javax.management.MBeanNotificationInfo; import javax.management.Notification; import javax.management.NotificationBroadcasterSupport; import javax.management.NotificationEmitter; import javax.management.NotificationFilter; import javax.management.NotificationListener; import javax.management.ObjectName; import javax.management.ReflectionException; import javax.management.MBeanRegistration; import javax.management.MBeanServer; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.apache.geronimo.gbean.GOperationSignature; import org.apache.geronimo.kernel.NoSuchAttributeException; import org.apache.geronimo.kernel.NoSuchOperationException; import org.apache.geronimo.kernel.Kernel; import org.apache.geronimo.kernel.lifecycle.LifecycleListener; import org.apache.geronimo.kernel.management.NotificationType; /** * @version $Rev$ $Date$ */ public final class MBeanGBeanBridge implements MBeanRegistration, DynamicMBean, NotificationEmitter { private static final Log log = LogFactory.getLog(MBeanGBeanBridge.class); /** * The kernel */ private final Kernel kernel; /** * The unique name of this service. */ private final ObjectName objectName; /** * The mbean info */ private final MBeanInfo mbeanInfo; /** * The broadcaster for notifications */ private final NotificationBroadcasterSupport notificationBroadcaster = new NotificationBroadcasterSupport(); private final LifecycleBridge lifecycleBridge; public MBeanGBeanBridge(Kernel kernel, ObjectName objectName, MBeanInfo mbeanInfo) { this.kernel = kernel; this.objectName = objectName; this.mbeanInfo = mbeanInfo; lifecycleBridge = new LifecycleBridge(objectName, notificationBroadcaster); } public ObjectName getObjectName() { return objectName; } public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception { return objectName; } public void postRegister(Boolean registrationDone) { if (Boolean.TRUE.equals(registrationDone)) { // fire the loaded event from the gbeanMBean.. it was already fired from the GBeanInstance when it was created kernel.getLifecycleMonitor().addLifecycleListener(lifecycleBridge, objectName); lifecycleBridge.loaded(objectName); } } public void preDeregister() { kernel.getLifecycleMonitor().removeLifecycleListener(lifecycleBridge); lifecycleBridge.unloaded(objectName); } public void postDeregister() { } public MBeanInfo getMBeanInfo() { return mbeanInfo; } public Object getAttribute(String attributeName) throws ReflectionException, AttributeNotFoundException { try { return kernel.getAttribute(objectName, attributeName); } catch (NoSuchAttributeException e) { throw new AttributeNotFoundException(attributeName); } catch (Exception e) { throw new ReflectionException(e); } } public void setAttribute(Attribute attribute) throws ReflectionException, AttributeNotFoundException { String attributeName = attribute.getName(); Object attributeValue = attribute.getValue(); try { kernel.setAttribute(objectName, attributeName, attributeValue); } catch (NoSuchAttributeException e) { throw new AttributeNotFoundException(attributeName); } catch (Exception e) { throw new ReflectionException(e); } } public AttributeList getAttributes(String[] attributes) { AttributeList results = new AttributeList(attributes.length); for (int i = 0; i < attributes.length; i++) { String name = attributes[i]; try { Object value = getAttribute(name); results.add(new Attribute(name, value)); } catch (JMException e) { log.warn("Exception while getting attribute " + name, e); } } return results; } public AttributeList setAttributes(AttributeList attributes) { AttributeList results = new AttributeList(attributes.size()); for (Iterator iterator = attributes.iterator(); iterator.hasNext();) { Attribute attribute = (Attribute) iterator.next(); try { setAttribute(attribute); results.add(attribute); } catch (JMException e) { log.warn("Exception while setting attribute " + attribute.getName(), e); } } return results; } public Object invoke(String operationName, Object[] arguments, String[] types) throws ReflectionException { try { return kernel.invoke(objectName, operationName, arguments, types); } catch (NoSuchOperationException e) { throw new ReflectionException(new NoSuchMethodException(new GOperationSignature(operationName, types).toString())); } catch (Exception e) { throw new ReflectionException(e); } } public MBeanNotificationInfo[] getNotificationInfo() { return new MBeanNotificationInfo[]{ new MBeanNotificationInfo(NotificationType.TYPES, "javax.management.Notification", "J2EE Notifications") }; } public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) { notificationBroadcaster.addNotificationListener(listener, filter, handback); } public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException { notificationBroadcaster.removeNotificationListener(listener); } public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException { notificationBroadcaster.removeNotificationListener(listener, filter, handback); } public String toString() { return objectName.toString(); } private static class LifecycleBridge implements LifecycleListener { /** * Sequence number used for notifications */ private long sequence; /** * Name of the MBeanGBean */ private final ObjectName mbeanGBeanName; /** * The notification broadcaster to use */ private final NotificationBroadcasterSupport notificationBroadcaster; public LifecycleBridge(ObjectName mbeanGBeanName, NotificationBroadcasterSupport notificationBroadcaster) { this.mbeanGBeanName = mbeanGBeanName; this.notificationBroadcaster = notificationBroadcaster; } public void loaded(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.OBJECT_CREATED, objectName, nextSequence())); } } public void starting(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STARTING, objectName, nextSequence())); } } public void running(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_RUNNING, objectName, nextSequence())); } } public void stopping(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STOPPING, objectName, nextSequence())); } } public void stopped(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STOPPED, objectName, nextSequence())); } } public void failed(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_FAILED, objectName, nextSequence())); } } public void unloaded(ObjectName objectName) { if (mbeanGBeanName.equals(objectName)) { notificationBroadcaster.sendNotification(new Notification(NotificationType.OBJECT_DELETED, objectName, nextSequence())); } } public synchronized long nextSequence() { return sequence++; } } }