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: 706640 $ $Date: 2008-10-21 14:44:05 +0000 (Tue, 21 Oct 2008) $
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 NotificationBroadcasterSupport getNotificationBroadcasterSupport() {
093            return notificationBroadcaster;
094        }
095        
096        public ObjectName preRegister(MBeanServer mBeanServer, ObjectName objectName) throws Exception {
097            return objectName;
098        }
099    
100        public void postRegister(Boolean registrationDone) {
101            if (Boolean.TRUE.equals(registrationDone)) {
102                // fire the loaded event from the gbeanMBean.. it was already fired from the GBeanInstance when it was created
103                kernel.getLifecycleMonitor().addLifecycleListener(lifecycleBridge, pattern);
104                lifecycleBridge.loaded(abstractName);
105            }
106        }
107    
108        public void preDeregister() {
109            kernel.getLifecycleMonitor().removeLifecycleListener(lifecycleBridge);
110            lifecycleBridge.unloaded(abstractName);
111        }
112    
113        public void postDeregister() {
114        }
115    
116        public MBeanInfo getMBeanInfo() {
117            return mbeanInfo;
118        }
119    
120        public Object getAttribute(String attributeName) throws ReflectionException, AttributeNotFoundException {
121            try {
122                return kernel.getAttribute(abstractName, attributeName);
123            } catch (NoSuchAttributeException e) {
124                throw (AttributeNotFoundException)new AttributeNotFoundException(attributeName).initCause(e);
125            } catch (Exception e) {
126                throw new ReflectionException(e);
127            }
128        }
129    
130        public void setAttribute(Attribute attribute) throws ReflectionException, AttributeNotFoundException {
131            String attributeName = attribute.getName();
132            Object attributeValue = attribute.getValue();
133            try {
134                kernel.setAttribute(abstractName, attributeName, attributeValue);
135            } catch (NoSuchAttributeException e) {
136                throw (AttributeNotFoundException)new AttributeNotFoundException(attributeName).initCause(e);
137            } catch (Exception e) {
138                throw new ReflectionException(e);
139            }
140        }
141    
142        public AttributeList getAttributes(String[] attributes) {
143            AttributeList results = new AttributeList(attributes.length);
144            for (int i = 0; i < attributes.length; i++) {
145                String name = attributes[i];
146                try {
147                    Object value = getAttribute(name);
148                    results.add(new Attribute(name, value));
149                } catch (JMException e) {
150                    log.warn("Exception while getting attribute " + name, e);
151                }
152            }
153            return results;
154        }
155    
156        public AttributeList setAttributes(AttributeList attributes) {
157            AttributeList results = new AttributeList(attributes.size());
158            for (Iterator iterator = attributes.iterator(); iterator.hasNext();) {
159                Attribute attribute = (Attribute) iterator.next();
160                try {
161                    setAttribute(attribute);
162                    results.add(attribute);
163                } catch (JMException e) {
164                    log.warn("Exception while setting attribute " + attribute.getName(), e);
165                }
166            }
167            return results;
168        }
169    
170        public Object invoke(String operationName, Object[] arguments, String[] types) throws ReflectionException {
171            try {
172                return kernel.invoke(abstractName, operationName, arguments, types);
173            } catch (NoSuchOperationException e) {
174                throw new ReflectionException((NoSuchMethodException)new NoSuchMethodException(new GOperationSignature(operationName, types).toString()).initCause(e));
175            } catch (Exception e) {
176                throw new ReflectionException(e);
177            }
178        }
179    
180        public MBeanNotificationInfo[] getNotificationInfo() {
181            return new MBeanNotificationInfo[]{
182                new MBeanNotificationInfo(NotificationType.TYPES, "javax.management.Notification", "J2EE Notifications")
183            };
184        }
185    
186        public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) {
187            notificationBroadcaster.addNotificationListener(listener, filter, handback);
188        }
189    
190        public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
191            notificationBroadcaster.removeNotificationListener(listener);
192        }
193    
194        public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
195            notificationBroadcaster.removeNotificationListener(listener, filter, handback);
196        }
197    
198        public String toString() {
199            return abstractName.toString();
200        }
201    
202        private static class LifecycleBridge implements LifecycleListener {
203            /**
204             * Sequence number used for notifications
205             */
206            private long sequence;
207    
208            /**
209             * AbstractName of this MBean
210             */
211            private final AbstractName mbeanAbstractName;
212    
213            /**
214             * ObjectName of this MBean
215             */
216            private final ObjectName objectName;
217    
218            /**
219             * The notification broadcaster to use
220             */
221            private final NotificationBroadcasterSupport notificationBroadcaster;
222    
223            public LifecycleBridge(AbstractName mbeanAbstractName, ObjectName objectName, NotificationBroadcasterSupport notificationBroadcaster) {
224                this.mbeanAbstractName = mbeanAbstractName;
225                this.objectName = objectName;
226                this.notificationBroadcaster = notificationBroadcaster;
227            }
228    
229            public void loaded(AbstractName abstractName) {
230                if (mbeanAbstractName.equals(abstractName)) {
231                    notificationBroadcaster.sendNotification(new Notification(NotificationType.OBJECT_CREATED, objectName, nextSequence()));
232                }
233            }
234    
235            public void starting(AbstractName abstractName) {
236                if (mbeanAbstractName.equals(abstractName)) {
237                    notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STARTING, objectName, nextSequence()));
238                }
239            }
240    
241            public void running(AbstractName abstractName) {
242                if (mbeanAbstractName.equals(abstractName)) {
243                    notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_RUNNING, objectName, nextSequence()));
244                }
245            }
246    
247            public void stopping(AbstractName abstractName) {
248                if (mbeanAbstractName.equals(abstractName)) {
249                    notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STOPPING, objectName, nextSequence()));
250                }
251            }
252    
253            public void stopped(AbstractName abstractName) {
254                if (mbeanAbstractName.equals(abstractName)) {
255                    notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_STOPPED, objectName, nextSequence()));
256                }
257            }
258    
259            public void failed(AbstractName abstractName) {
260                if (mbeanAbstractName.equals(abstractName)) {
261                    notificationBroadcaster.sendNotification(new Notification(NotificationType.STATE_FAILED, objectName, nextSequence()));
262                }
263            }
264    
265            public void unloaded(AbstractName abstractName) {
266                if (mbeanAbstractName.equals(abstractName)) {
267                    notificationBroadcaster.sendNotification(new Notification(NotificationType.OBJECT_DELETED, objectName, nextSequence()));
268                }
269            }
270    
271            public synchronized long nextSequence() {
272                return sequence++;
273            }
274        }
275    }