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 }