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 }