1 /*
2 * Copyright (c) 2005, 2015, 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 }
316