View Javadoc
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 implementation the implementation of the MBean interface.
95       * @param mbeanInterface a Standard MBean interface.
96       * @param emitter the object that will handle notifications.
97       *
98       * @throws IllegalArgumentException if the {@code mbeanInterface}
99       *    does not follow JMX design patterns for Management Interfaces, or
100      *    if the given {@code implementation} does not implement the
101      *    specified interface, or if {@code emitter} is null.
102      */
103     public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
104                                     NotificationEmitter emitter) {
105         this(implementation, mbeanInterface, false, emitter);
106     }
107 
108     /**
109      * <p>Make an MBean whose management interface is specified by
110      * {@code mbeanInterface}, with the given implementation and where
111      * notifications are handled by the given {@code
112      * NotificationEmitter}.  This constructor can be used to make
113      * either Standard MBeans or MXBeans.  The resultant MBean
114      * implements the {@code NotificationEmitter} interface by
115      * forwarding its methods to {@code emitter}.  It is legal and
116      * useful for {@code implementation} and {@code emitter} to be the
117      * same object.</p>
118      *
119      * <p>If {@code emitter} is an instance of {@code
120      * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
121      * sendNotification} method will call {@code emitter.}{@link
122      * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
123      *
124      * <p>The array returned by {@link #getNotificationInfo()} on the
125      * new MBean is a copy of the array returned by
126      * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
127      * getNotificationInfo()} at the time of construction.  If the array
128      * returned by {@code emitter.getNotificationInfo()} later changes,
129      * that will have no effect on this object's
130      * {@code getNotificationInfo()}.</p>
131      *
132      * @param implementation the implementation of the MBean interface.
133      * @param mbeanInterface a Standard MBean interface.
134      * @param isMXBean If true, the {@code mbeanInterface} parameter
135      * names an MXBean interface and the resultant MBean is an MXBean.
136      * @param emitter the object that will handle notifications.
137      *
138      * @throws IllegalArgumentException if the {@code mbeanInterface}
139      *    does not follow JMX design patterns for Management Interfaces, or
140      *    if the given {@code implementation} does not implement the
141      *    specified interface, or if {@code emitter} is null.
142      */
143     public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
144                                     boolean isMXBean,
145                                     NotificationEmitter emitter) {
146         super(implementation, mbeanInterface, isMXBean);
147         if (emitter == null)
148             throw new IllegalArgumentException("Null emitter");
149         this.emitter = emitter;
150         MBeanNotificationInfo[] infos = emitter.getNotificationInfo();
151         if (infos == null || infos.length == 0) {
152             this.notificationInfo = NO_NOTIFICATION_INFO;
153         } else {
154             this.notificationInfo = infos.clone();
155         }
156     }
157 
158     /**
159      * <p>Make an MBean whose management interface is specified by
160      * {@code mbeanInterface}, and
161      * where notifications are handled by the given {@code NotificationEmitter}.
162      * The resultant MBean implements the {@code NotificationEmitter} interface
163      * by forwarding its methods to {@code emitter}.</p>
164      *
165      * <p>If {@code emitter} is an instance of {@code
166      * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
167      * sendNotification} method will call {@code emitter.}{@link
168      * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
169      *
170      * <p>The array returned by {@link #getNotificationInfo()} on the
171      * new MBean is a copy of the array returned by
172      * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
173      * getNotificationInfo()} at the time of construction.  If the array
174      * returned by {@code emitter.getNotificationInfo()} later changes,
175      * that will have no effect on this object's
176      * {@code getNotificationInfo()}.</p>
177      *
178      * <p>This constructor must be called from a subclass that implements
179      * the given {@code mbeanInterface}.</p>
180      *
181      * @param mbeanInterface a StandardMBean interface.
182      * @param emitter the object that will handle notifications.
183      *
184      * @throws IllegalArgumentException if the {@code mbeanInterface}
185      *    does not follow JMX design patterns for Management Interfaces, or
186      *    if {@code this} does not implement the specified interface, or
187      *    if {@code emitter} is null.
188      */
189     protected StandardEmitterMBean(Class<?> mbeanInterface,
190                                    NotificationEmitter emitter) {
191         this(mbeanInterface, false, emitter);
192     }
193 
194     /**
195      * <p>Make an MBean whose management interface is specified by
196      * {@code mbeanInterface}, and where notifications are handled by
197      * the given {@code NotificationEmitter}.  This constructor can be
198      * used to make either Standard MBeans or MXBeans.  The resultant
199      * MBean implements the {@code NotificationEmitter} interface by
200      * forwarding its methods to {@code emitter}.</p>
201      *
202      * <p>If {@code emitter} is an instance of {@code
203      * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
204      * sendNotification} method will call {@code emitter.}{@link
205      * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
206      *
207      * <p>The array returned by {@link #getNotificationInfo()} on the
208      * new MBean is a copy of the array returned by
209      * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
210      * getNotificationInfo()} at the time of construction.  If the array
211      * returned by {@code emitter.getNotificationInfo()} later changes,
212      * that will have no effect on this object's
213      * {@code getNotificationInfo()}.</p>
214      *
215      * <p>This constructor must be called from a subclass that implements
216      * the given {@code mbeanInterface}.</p>
217      *
218      * @param mbeanInterface a StandardMBean interface.
219      * @param isMXBean If true, the {@code mbeanInterface} parameter
220      * names an MXBean interface and the resultant MBean is an MXBean.
221      * @param emitter the object that will handle notifications.
222      *
223      * @throws IllegalArgumentException if the {@code mbeanInterface}
224      *    does not follow JMX design patterns for Management Interfaces, or
225      *    if {@code this} does not implement the specified interface, or
226      *    if {@code emitter} is null.
227      */
228     protected StandardEmitterMBean(Class<?> mbeanInterface, boolean isMXBean,
229                                    NotificationEmitter emitter) {
230         super(mbeanInterface, isMXBean);
231         if (emitter == null)
232             throw new IllegalArgumentException("Null emitter");
233         this.emitter = emitter;
234         MBeanNotificationInfo[] infos = emitter.getNotificationInfo();
235         if (infos == null || infos.length == 0) {
236             this.notificationInfo = NO_NOTIFICATION_INFO;
237         } else {
238             this.notificationInfo = infos.clone();
239         }
240     }
241 
242     public void removeNotificationListener(NotificationListener listener)
243             throws ListenerNotFoundException {
244         emitter.removeNotificationListener(listener);
245     }
246 
247     public void removeNotificationListener(NotificationListener listener,
248                                            NotificationFilter filter,
249                                            Object handback)
250             throws ListenerNotFoundException {
251         emitter.removeNotificationListener(listener, filter, handback);
252     }
253 
254     public void addNotificationListener(NotificationListener listener,
255                                         NotificationFilter filter,
256                                         Object handback) {
257         emitter.addNotificationListener(listener, filter, handback);
258     }
259 
260     public MBeanNotificationInfo[] getNotificationInfo() {
261         // this getter might get called from the super constructor
262         // when the notificationInfo has not been properly set yet
263         if (notificationInfo == null) {
264             return NO_NOTIFICATION_INFO;
265         }
266         if (notificationInfo.length == 0) {
267             return notificationInfo;
268         } else {
269             return notificationInfo.clone();
270         }
271     }
272 
273     /**
274      * <p>Sends a notification.</p>
275      *
276      * <p>If the {@code emitter} parameter to the constructor was an
277      * instance of {@code NotificationBroadcasterSupport} then this
278      * method will call {@code emitter.}{@link
279      * NotificationBroadcasterSupport#sendNotification
280      * sendNotification}.</p>
281      *
282      * @param n the notification to send.
283      *
284      * @throws ClassCastException if the {@code emitter} parameter to the
285      * constructor was not a {@code NotificationBroadcasterSupport}.
286      */
287     public void sendNotification(Notification n) {
288         if (emitter instanceof NotificationBroadcasterSupport)
289             ((NotificationBroadcasterSupport) emitter).sendNotification(n);
290         else {
291             final String msg =
292                 "Cannot sendNotification when emitter is not an " +
293                 "instance of NotificationBroadcasterSupport: " +
294                 emitter.getClass().getName();
295             throw new ClassCastException(msg);
296         }
297     }
298 
299     /**
300      * <p>Get the MBeanNotificationInfo[] that will be used in the
301      * MBeanInfo returned by this MBean.</p>
302      *
303      * <p>The default implementation of this method returns
304      * {@link #getNotificationInfo()}.</p>
305      *
306      * @param info The default MBeanInfo derived by reflection.
307      * @return the MBeanNotificationInfo[] for the new MBeanInfo.
308      */
309     @Override
310     MBeanNotificationInfo[] getNotifications(MBeanInfo info) {
311         return getNotificationInfo();
312     }
313 }