1 /* 2 * Copyright (c) 2005, 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javax.management; 27 28 /** 29 * <p>An MBean whose management interface is determined by reflection 30 * on a Java interface, and that emits notifications.</p> 31 * 32 * <p>The following example shows how to use the public constructor 33 * {@link #StandardEmitterMBean(Object, Class, NotificationEmitter) 34 * StandardEmitterMBean(implementation, mbeanInterface, emitter)} to 35 * create an MBean emitting notifications with any 36 * implementation class name <i>Impl</i>, with a management 37 * interface defined (as for current Standard MBeans) by any interface 38 * <i>Intf</i>, and with any implementation of the interface 39 * {@link NotificationEmitter}. The example uses the class 40 * {@link NotificationBroadcasterSupport} as an implementation 41 * of the interface {@link NotificationEmitter}.</p> 42 * 43 * <pre> 44 * MBeanServer mbs; 45 * ... 46 * final String[] types = new String[] {"sun.disc.space","sun.disc.alarm"}; 47 * final MBeanNotificationInfo info = new MBeanNotificationInfo( 48 * types, 49 * Notification.class.getName(), 50 * "Notification about disc info."); 51 * final NotificationEmitter emitter = 52 * new NotificationBroadcasterSupport(info); 53 * 54 * final Intf impl = new Impl(...); 55 * final Object mbean = new StandardEmitterMBean( 56 * impl, Intf.class, emitter); 57 * mbs.registerMBean(mbean, objectName); 58 * </pre> 59 * 60 * @see StandardMBean 61 * 62 * @since 1.6 63 */ 64 public class StandardEmitterMBean extends StandardMBean 65 implements NotificationEmitter { 66 67 private static final MBeanNotificationInfo[] NO_NOTIFICATION_INFO = 68 new MBeanNotificationInfo[0]; 69 70 private final NotificationEmitter emitter; 71 private final MBeanNotificationInfo[] notificationInfo; 72 73 /** 74 * <p>Make an MBean whose management interface is specified by 75 * {@code mbeanInterface}, with the given implementation and 76 * where notifications are handled by the given {@code NotificationEmitter}. 77 * The resultant MBean implements the {@code NotificationEmitter} interface 78 * by forwarding its methods to {@code emitter}. It is legal and useful 79 * for {@code implementation} and {@code emitter} to be the same object.</p> 80 * 81 * <p>If {@code emitter} is an instance of {@code 82 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification 83 * sendNotification} method will call {@code emitter.}{@link 84 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> 85 * 86 * <p>The array returned by {@link #getNotificationInfo()} on the 87 * new MBean is a copy of the array returned by 88 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo 89 * getNotificationInfo()} at the time of construction. If the array 90 * returned by {@code emitter.getNotificationInfo()} later changes, 91 * that will have no effect on this object's 92 * {@code getNotificationInfo()}.</p> 93 * 94 * @param <T> the implementation type of the MBean 95 * @param implementation the implementation of the MBean interface. 96 * @param mbeanInterface a Standard MBean interface. 97 * @param emitter the object that will handle notifications. 98 * 99 * @throws IllegalArgumentException if the {@code mbeanInterface} 100 * does not follow JMX design patterns for Management Interfaces, or 101 * if the given {@code implementation} does not implement the 102 * specified interface, or if {@code emitter} is null. 103 */ 104 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, 105 NotificationEmitter emitter) { 106 this(implementation, mbeanInterface, false, emitter); 107 } 108 109 /** 110 * <p>Make an MBean whose management interface is specified by 111 * {@code mbeanInterface}, with the given implementation and where 112 * notifications are handled by the given {@code 113 * NotificationEmitter}. This constructor can be used to make 114 * either Standard MBeans or MXBeans. The resultant MBean 115 * implements the {@code NotificationEmitter} interface by 116 * forwarding its methods to {@code emitter}. It is legal and 117 * useful for {@code implementation} and {@code emitter} to be the 118 * same object.</p> 119 * 120 * <p>If {@code emitter} is an instance of {@code 121 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification 122 * sendNotification} method will call {@code emitter.}{@link 123 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> 124 * 125 * <p>The array returned by {@link #getNotificationInfo()} on the 126 * new MBean is a copy of the array returned by 127 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo 128 * getNotificationInfo()} at the time of construction. If the array 129 * returned by {@code emitter.getNotificationInfo()} later changes, 130 * that will have no effect on this object's 131 * {@code getNotificationInfo()}.</p> 132 * 133 * @param <T> the implementation type of the MBean 134 * @param implementation the implementation of the MBean interface. 135 * @param mbeanInterface a Standard MBean interface. 136 * @param isMXBean If true, the {@code mbeanInterface} parameter 137 * names an MXBean interface and the resultant MBean is an MXBean. 138 * @param emitter the object that will handle notifications. 139 * 140 * @throws IllegalArgumentException if the {@code mbeanInterface} 141 * does not follow JMX design patterns for Management Interfaces, or 142 * if the given {@code implementation} does not implement the 143 * specified interface, or if {@code emitter} is null. 144 */ 145 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, 146 boolean isMXBean, 147 NotificationEmitter emitter) { 148 super(implementation, mbeanInterface, isMXBean); 149 if (emitter == null) 150 throw new IllegalArgumentException("Null emitter"); 151 this.emitter = emitter; 152 MBeanNotificationInfo[] infos = emitter.getNotificationInfo(); 153 if (infos == null || infos.length == 0) { 154 this.notificationInfo = NO_NOTIFICATION_INFO; 155 } else { 156 this.notificationInfo = infos.clone(); 157 } 158 } 159 160 /** 161 * <p>Make an MBean whose management interface is specified by 162 * {@code mbeanInterface}, and 163 * where notifications are handled by the given {@code NotificationEmitter}. 164 * The resultant MBean implements the {@code NotificationEmitter} interface 165 * by forwarding its methods to {@code emitter}.</p> 166 * 167 * <p>If {@code emitter} is an instance of {@code 168 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification 169 * sendNotification} method will call {@code emitter.}{@link 170 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> 171 * 172 * <p>The array returned by {@link #getNotificationInfo()} on the 173 * new MBean is a copy of the array returned by 174 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo 175 * getNotificationInfo()} at the time of construction. If the array 176 * returned by {@code emitter.getNotificationInfo()} later changes, 177 * that will have no effect on this object's 178 * {@code getNotificationInfo()}.</p> 179 * 180 * <p>This constructor must be called from a subclass that implements 181 * the given {@code mbeanInterface}.</p> 182 * 183 * @param mbeanInterface a StandardMBean interface. 184 * @param emitter the object that will handle notifications. 185 * 186 * @throws IllegalArgumentException if the {@code mbeanInterface} 187 * does not follow JMX design patterns for Management Interfaces, or 188 * if {@code this} does not implement the specified interface, or 189 * if {@code emitter} is null. 190 */ 191 protected StandardEmitterMBean(Class<?> mbeanInterface, 192 NotificationEmitter emitter) { 193 this(mbeanInterface, false, emitter); 194 } 195 196 /** 197 * <p>Make an MBean whose management interface is specified by 198 * {@code mbeanInterface}, and where notifications are handled by 199 * the given {@code NotificationEmitter}. This constructor can be 200 * used to make either Standard MBeans or MXBeans. The resultant 201 * MBean implements the {@code NotificationEmitter} interface by 202 * forwarding its methods to {@code emitter}.</p> 203 * 204 * <p>If {@code emitter} is an instance of {@code 205 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification 206 * sendNotification} method will call {@code emitter.}{@link 207 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> 208 * 209 * <p>The array returned by {@link #getNotificationInfo()} on the 210 * new MBean is a copy of the array returned by 211 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo 212 * getNotificationInfo()} at the time of construction. If the array 213 * returned by {@code emitter.getNotificationInfo()} later changes, 214 * that will have no effect on this object's 215 * {@code getNotificationInfo()}.</p> 216 * 217 * <p>This constructor must be called from a subclass that implements 218 * the given {@code mbeanInterface}.</p> 219 * 220 * @param mbeanInterface a StandardMBean interface. 221 * @param isMXBean If true, the {@code mbeanInterface} parameter 222 * names an MXBean interface and the resultant MBean is an MXBean. 223 * @param emitter the object that will handle notifications. 224 * 225 * @throws IllegalArgumentException if the {@code mbeanInterface} 226 * does not follow JMX design patterns for Management Interfaces, or 227 * if {@code this} does not implement the specified interface, or 228 * if {@code emitter} is null. 229 */ 230 protected StandardEmitterMBean(Class<?> mbeanInterface, boolean isMXBean, 231 NotificationEmitter emitter) { 232 super(mbeanInterface, isMXBean); 233 if (emitter == null) 234 throw new IllegalArgumentException("Null emitter"); 235 this.emitter = emitter; 236 MBeanNotificationInfo[] infos = emitter.getNotificationInfo(); 237 if (infos == null || infos.length == 0) { 238 this.notificationInfo = NO_NOTIFICATION_INFO; 239 } else { 240 this.notificationInfo = infos.clone(); 241 } 242 } 243 244 public void removeNotificationListener(NotificationListener listener) 245 throws ListenerNotFoundException { 246 emitter.removeNotificationListener(listener); 247 } 248 249 public void removeNotificationListener(NotificationListener listener, 250 NotificationFilter filter, 251 Object handback) 252 throws ListenerNotFoundException { 253 emitter.removeNotificationListener(listener, filter, handback); 254 } 255 256 public void addNotificationListener(NotificationListener listener, 257 NotificationFilter filter, 258 Object handback) { 259 emitter.addNotificationListener(listener, filter, handback); 260 } 261 262 public MBeanNotificationInfo[] getNotificationInfo() { 263 // this getter might get called from the super constructor 264 // when the notificationInfo has not been properly set yet 265 if (notificationInfo == null) { 266 return NO_NOTIFICATION_INFO; 267 } 268 if (notificationInfo.length == 0) { 269 return notificationInfo; 270 } else { 271 return notificationInfo.clone(); 272 } 273 } 274 275 /** 276 * <p>Sends a notification.</p> 277 * 278 * <p>If the {@code emitter} parameter to the constructor was an 279 * instance of {@code NotificationBroadcasterSupport} then this 280 * method will call {@code emitter.}{@link 281 * NotificationBroadcasterSupport#sendNotification 282 * sendNotification}.</p> 283 * 284 * @param n the notification to send. 285 * 286 * @throws ClassCastException if the {@code emitter} parameter to the 287 * constructor was not a {@code NotificationBroadcasterSupport}. 288 */ 289 public void sendNotification(Notification n) { 290 if (emitter instanceof NotificationBroadcasterSupport) 291 ((NotificationBroadcasterSupport) emitter).sendNotification(n); 292 else { 293 final String msg = 294 "Cannot sendNotification when emitter is not an " + 295 "instance of NotificationBroadcasterSupport: " + 296 emitter.getClass().getName(); 297 throw new ClassCastException(msg); 298 } 299 } 300 301 /** 302 * <p>Get the MBeanNotificationInfo[] that will be used in the 303 * MBeanInfo returned by this MBean.</p> 304 * 305 * <p>The default implementation of this method returns 306 * {@link #getNotificationInfo()}.</p> 307 * 308 * @param info The default MBeanInfo derived by reflection. 309 * @return the MBeanNotificationInfo[] for the new MBeanInfo. 310 */ 311 @Override 312 MBeanNotificationInfo[] getNotifications(MBeanInfo info) { 313 return getNotificationInfo(); 314 } 315 }