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    }