78 * The resultant MBean implements the {@code NotificationEmitter} interface |
74 * The resultant MBean implements the {@code NotificationEmitter} interface |
79 * by forwarding its methods to {@code emitter}. It is legal and useful |
75 * by forwarding its methods to {@code emitter}. It is legal and useful |
80 * for {@code implementation} and {@code emitter} to be the same object.</p> |
76 * for {@code implementation} and {@code emitter} to be the same object.</p> |
81 * |
77 * |
82 * <p>If {@code emitter} is an instance of {@code |
78 * <p>If {@code emitter} is an instance of {@code |
83 * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), |
79 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification |
84 * then the MBean's {@link #sendNotification |
80 * sendNotification} method will call {@code emitter.}{@link |
85 * sendNotification} method will call {@code emitter.}{@link |
81 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> |
86 * SendNotification#sendNotification sendNotification}.</p> |
|
87 * |
82 * |
88 * <p>The array returned by {@link #getNotificationInfo()} on the |
83 * <p>The array returned by {@link #getNotificationInfo()} on the |
89 * new MBean is a copy of the array returned by |
84 * new MBean is a copy of the array returned by |
90 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
85 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
91 * getNotificationInfo()} at the time of construction. If the array |
86 * getNotificationInfo()} at the time of construction. If the array |
93 * that will have no effect on this object's |
88 * that will have no effect on this object's |
94 * {@code getNotificationInfo()}.</p> |
89 * {@code getNotificationInfo()}.</p> |
95 * |
90 * |
96 * @param implementation the implementation of the MBean interface. |
91 * @param implementation the implementation of the MBean interface. |
97 * @param mbeanInterface a Standard MBean interface. |
92 * @param mbeanInterface a Standard MBean interface. |
98 * @param emitter the object that will handle notifications. If null, |
93 * @param emitter the object that will handle notifications. |
99 * a new {@code NotificationEmitter} will be constructed that also |
|
100 * implements {@link SendNotification}. |
|
101 * |
94 * |
102 * @throws IllegalArgumentException if the {@code mbeanInterface} |
95 * @throws IllegalArgumentException if the {@code mbeanInterface} |
103 * does not follow JMX design patterns for Management Interfaces, or |
96 * does not follow JMX design patterns for Management Interfaces, or |
104 * if the given {@code implementation} does not implement the |
97 * if the given {@code implementation} does not implement the |
105 * specified interface. |
98 * specified interface, or if {@code emitter} is null. |
106 */ |
99 */ |
107 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, |
100 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, |
108 NotificationEmitter emitter) { |
101 NotificationEmitter emitter) { |
109 this(implementation, mbeanInterface, false, emitter); |
102 super(implementation, mbeanInterface, false); |
|
103 if (emitter == null) |
|
104 throw new IllegalArgumentException("Null emitter"); |
|
105 this.emitter = emitter; |
|
106 this.notificationInfo = emitter.getNotificationInfo(); |
110 } |
107 } |
111 |
108 |
112 /** |
109 /** |
113 * <p>Make an MBean whose management interface is specified by |
110 * <p>Make an MBean whose management interface is specified by |
114 * {@code mbeanInterface}, with the given implementation and where |
111 * {@code mbeanInterface}, with the given implementation and where |
119 * forwarding its methods to {@code emitter}. It is legal and |
116 * forwarding its methods to {@code emitter}. It is legal and |
120 * useful for {@code implementation} and {@code emitter} to be the |
117 * useful for {@code implementation} and {@code emitter} to be the |
121 * same object.</p> |
118 * same object.</p> |
122 * |
119 * |
123 * <p>If {@code emitter} is an instance of {@code |
120 * <p>If {@code emitter} is an instance of {@code |
124 * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), |
121 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification |
125 * then the MBean's {@link #sendNotification |
122 * sendNotification} method will call {@code emitter.}{@link |
126 * sendNotification} method will call {@code emitter.}{@link |
123 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> |
127 * SendNotification#sendNotification sendNotification}.</p> |
|
128 * |
124 * |
129 * <p>The array returned by {@link #getNotificationInfo()} on the |
125 * <p>The array returned by {@link #getNotificationInfo()} on the |
130 * new MBean is a copy of the array returned by |
126 * new MBean is a copy of the array returned by |
131 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
127 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
132 * getNotificationInfo()} at the time of construction. If the array |
128 * getNotificationInfo()} at the time of construction. If the array |
136 * |
132 * |
137 * @param implementation the implementation of the MBean interface. |
133 * @param implementation the implementation of the MBean interface. |
138 * @param mbeanInterface a Standard MBean interface. |
134 * @param mbeanInterface a Standard MBean interface. |
139 * @param isMXBean If true, the {@code mbeanInterface} parameter |
135 * @param isMXBean If true, the {@code mbeanInterface} parameter |
140 * names an MXBean interface and the resultant MBean is an MXBean. |
136 * names an MXBean interface and the resultant MBean is an MXBean. |
141 * @param emitter the object that will handle notifications. If null, |
137 * @param emitter the object that will handle notifications. |
142 * a new {@code NotificationEmitter} will be constructed that also |
|
143 * implements {@link SendNotification}. |
|
144 * |
138 * |
145 * @throws IllegalArgumentException if the {@code mbeanInterface} |
139 * @throws IllegalArgumentException if the {@code mbeanInterface} |
146 * does not follow JMX design patterns for Management Interfaces, or |
140 * does not follow JMX design patterns for Management Interfaces, or |
147 * if the given {@code implementation} does not implement the |
141 * if the given {@code implementation} does not implement the |
148 * specified interface. |
142 * specified interface, or if {@code emitter} is null. |
149 */ |
143 */ |
150 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, |
144 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, |
151 boolean isMXBean, |
145 boolean isMXBean, |
152 NotificationEmitter emitter) { |
146 NotificationEmitter emitter) { |
153 this(implementation, mbeanInterface, |
147 super(implementation, mbeanInterface, isMXBean); |
154 isMXBean ? MBeanOptions.MXBEAN : null, emitter); |
148 if (emitter == null) |
155 } |
149 throw new IllegalArgumentException("Null emitter"); |
156 |
150 this.emitter = emitter; |
157 /** |
151 this.notificationInfo = emitter.getNotificationInfo(); |
158 * <p>Make an MBean whose management interface is specified by {@code |
|
159 * mbeanInterface}, with the given implementation and options, and where |
|
160 * notifications are handled by the given {@code NotificationEmitter}. |
|
161 * Options select whether to make a Standard MBean or an MXBean, and |
|
162 * whether the result of {@link #getWrappedObject()} is the {@code |
|
163 * StandardEmitterMBean} object or the given implementation. The resultant |
|
164 * MBean implements the {@code NotificationEmitter} interface by forwarding |
|
165 * its methods to {@code emitter}. It is legal and useful for {@code |
|
166 * implementation} and {@code emitter} to be the same object.</p> |
|
167 * |
|
168 * <p>If {@code emitter} is an instance of {@code |
|
169 * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), |
|
170 * then the MBean's {@link #sendNotification |
|
171 * sendNotification} method will call {@code emitter.}{@link |
|
172 * SendNotification#sendNotification sendNotification}.</p> |
|
173 * |
|
174 * <p>The array returned by {@link #getNotificationInfo()} on the |
|
175 * new MBean is a copy of the array returned by |
|
176 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
|
177 * getNotificationInfo()} at the time of construction. If the array |
|
178 * returned by {@code emitter.getNotificationInfo()} later changes, |
|
179 * that will have no effect on this object's |
|
180 * {@code getNotificationInfo()}.</p> |
|
181 * |
|
182 * @param implementation the implementation of the MBean interface. |
|
183 * @param mbeanInterface a Standard MBean interface. |
|
184 * @param options MBeanOptions that control the operation of the resulting |
|
185 * MBean. |
|
186 * @param emitter the object that will handle notifications. If null, |
|
187 * a new {@code NotificationEmitter} will be constructed that also |
|
188 * implements {@link SendNotification}. |
|
189 * |
|
190 * @throws IllegalArgumentException if the {@code mbeanInterface} |
|
191 * does not follow JMX design patterns for Management Interfaces, or |
|
192 * if the given {@code implementation} does not implement the |
|
193 * specified interface. |
|
194 */ |
|
195 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface, |
|
196 MBeanOptions options, |
|
197 NotificationEmitter emitter) { |
|
198 super(implementation, mbeanInterface, options); |
|
199 MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(implementation); |
|
200 if (emitter == null) |
|
201 emitter = defaultEmitter(defaultMBNIs); |
|
202 this.emitter = emitter; |
|
203 this.notificationInfo = |
|
204 firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs); |
|
205 injectEmitter(); |
|
206 } |
152 } |
207 |
153 |
208 /** |
154 /** |
209 * <p>Make an MBean whose management interface is specified by |
155 * <p>Make an MBean whose management interface is specified by |
210 * {@code mbeanInterface}, and |
156 * {@code mbeanInterface}, and |
211 * where notifications are handled by the given {@code NotificationEmitter}. |
157 * where notifications are handled by the given {@code NotificationEmitter}. |
212 * The resultant MBean implements the {@code NotificationEmitter} interface |
158 * The resultant MBean implements the {@code NotificationEmitter} interface |
213 * by forwarding its methods to {@code emitter}.</p> |
159 * by forwarding its methods to {@code emitter}.</p> |
214 * |
160 * |
215 * <p>If {@code emitter} is an instance of {@code |
161 * <p>If {@code emitter} is an instance of {@code |
216 * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), |
162 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification |
217 * then the MBean's {@link #sendNotification |
163 * sendNotification} method will call {@code emitter.}{@link |
218 * sendNotification} method will call {@code emitter.}{@link |
164 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> |
219 * SendNotification#sendNotification sendNotification}.</p> |
|
220 * |
165 * |
221 * <p>The array returned by {@link #getNotificationInfo()} on the |
166 * <p>The array returned by {@link #getNotificationInfo()} on the |
222 * new MBean is a copy of the array returned by |
167 * new MBean is a copy of the array returned by |
223 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
168 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
224 * getNotificationInfo()} at the time of construction. If the array |
169 * getNotificationInfo()} at the time of construction. If the array |
228 * |
173 * |
229 * <p>This constructor must be called from a subclass that implements |
174 * <p>This constructor must be called from a subclass that implements |
230 * the given {@code mbeanInterface}.</p> |
175 * the given {@code mbeanInterface}.</p> |
231 * |
176 * |
232 * @param mbeanInterface a StandardMBean interface. |
177 * @param mbeanInterface a StandardMBean interface. |
233 * @param emitter the object that will handle notifications. If null, |
178 * @param emitter the object that will handle notifications. |
234 * a new {@code NotificationEmitter} will be constructed that also |
179 * |
235 * implements {@link SendNotification}. |
180 * @throws IllegalArgumentException if the {@code mbeanInterface} |
236 * |
181 * does not follow JMX design patterns for Management Interfaces, or |
237 * @throws IllegalArgumentException if the {@code mbeanInterface} |
182 * if {@code this} does not implement the specified interface, or |
238 * does not follow JMX design patterns for Management Interfaces, or |
183 * if {@code emitter} is null. |
239 * if {@code this} does not implement the specified interface. |
|
240 */ |
184 */ |
241 protected StandardEmitterMBean(Class<?> mbeanInterface, |
185 protected StandardEmitterMBean(Class<?> mbeanInterface, |
242 NotificationEmitter emitter) { |
186 NotificationEmitter emitter) { |
243 this(mbeanInterface, false, emitter); |
187 super(mbeanInterface, false); |
|
188 if (emitter == null) |
|
189 throw new IllegalArgumentException("Null emitter"); |
|
190 this.emitter = emitter; |
|
191 this.notificationInfo = emitter.getNotificationInfo(); |
244 } |
192 } |
245 |
193 |
246 /** |
194 /** |
247 * <p>Make an MBean whose management interface is specified by |
195 * <p>Make an MBean whose management interface is specified by |
248 * {@code mbeanInterface}, and where notifications are handled by |
196 * {@code mbeanInterface}, and where notifications are handled by |
250 * used to make either Standard MBeans or MXBeans. The resultant |
198 * used to make either Standard MBeans or MXBeans. The resultant |
251 * MBean implements the {@code NotificationEmitter} interface by |
199 * MBean implements the {@code NotificationEmitter} interface by |
252 * forwarding its methods to {@code emitter}.</p> |
200 * forwarding its methods to {@code emitter}.</p> |
253 * |
201 * |
254 * <p>If {@code emitter} is an instance of {@code |
202 * <p>If {@code emitter} is an instance of {@code |
255 * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), |
203 * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification |
256 * then the MBean's {@link #sendNotification |
204 * sendNotification} method will call {@code emitter.}{@link |
257 * sendNotification} method will call {@code emitter.}{@link |
205 * NotificationBroadcasterSupport#sendNotification sendNotification}.</p> |
258 * SendNotification#sendNotification sendNotification}.</p> |
|
259 * |
206 * |
260 * <p>The array returned by {@link #getNotificationInfo()} on the |
207 * <p>The array returned by {@link #getNotificationInfo()} on the |
261 * new MBean is a copy of the array returned by |
208 * new MBean is a copy of the array returned by |
262 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
209 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
263 * getNotificationInfo()} at the time of construction. If the array |
210 * getNotificationInfo()} at the time of construction. If the array |
269 * the given {@code mbeanInterface}.</p> |
216 * the given {@code mbeanInterface}.</p> |
270 * |
217 * |
271 * @param mbeanInterface a StandardMBean interface. |
218 * @param mbeanInterface a StandardMBean interface. |
272 * @param isMXBean If true, the {@code mbeanInterface} parameter |
219 * @param isMXBean If true, the {@code mbeanInterface} parameter |
273 * names an MXBean interface and the resultant MBean is an MXBean. |
220 * names an MXBean interface and the resultant MBean is an MXBean. |
274 * @param emitter the object that will handle notifications. If null, |
221 * @param emitter the object that will handle notifications. |
275 * a new {@code NotificationEmitter} will be constructed that also |
222 * |
276 * implements {@link SendNotification}. |
223 * @throws IllegalArgumentException if the {@code mbeanInterface} |
277 * |
224 * does not follow JMX design patterns for Management Interfaces, or |
278 * @throws IllegalArgumentException if the {@code mbeanInterface} |
225 * if {@code this} does not implement the specified interface, or |
279 * does not follow JMX design patterns for Management Interfaces, or |
226 * if {@code emitter} is null. |
280 * if {@code this} does not implement the specified interface. |
|
281 */ |
227 */ |
282 protected StandardEmitterMBean(Class<?> mbeanInterface, boolean isMXBean, |
228 protected StandardEmitterMBean(Class<?> mbeanInterface, boolean isMXBean, |
283 NotificationEmitter emitter) { |
229 NotificationEmitter emitter) { |
284 this(mbeanInterface, isMXBean ? MBeanOptions.MXBEAN : null, emitter); |
230 super(mbeanInterface, isMXBean); |
285 } |
231 if (emitter == null) |
286 |
232 throw new IllegalArgumentException("Null emitter"); |
287 /** |
233 this.emitter = emitter; |
288 * <p>Make an MBean whose management interface is specified by {@code |
234 this.notificationInfo = emitter.getNotificationInfo(); |
289 * mbeanInterface}, with the given options, and where notifications are |
|
290 * handled by the given {@code NotificationEmitter}. This constructor can |
|
291 * be used to make either Standard MBeans or MXBeans. The resultant MBean |
|
292 * implements the {@code NotificationEmitter} interface by forwarding its |
|
293 * methods to {@code emitter}.</p> |
|
294 * |
|
295 * <p>If {@code emitter} is an instance of {@code |
|
296 * SendNotification} (for example, a {@link NotificationBroadcasterSupport}), |
|
297 * then the MBean's {@link #sendNotification |
|
298 * sendNotification} method will call {@code emitter.}{@link |
|
299 * SendNotification#sendNotification sendNotification}.</p> |
|
300 * |
|
301 * <p>The array returned by {@link #getNotificationInfo()} on the |
|
302 * new MBean is a copy of the array returned by |
|
303 * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo |
|
304 * getNotificationInfo()} at the time of construction. If the array |
|
305 * returned by {@code emitter.getNotificationInfo()} later changes, |
|
306 * that will have no effect on this object's |
|
307 * {@code getNotificationInfo()}.</p> |
|
308 * |
|
309 * <p>This constructor must be called from a subclass that implements |
|
310 * the given {@code mbeanInterface}.</p> |
|
311 * |
|
312 * @param mbeanInterface a StandardMBean interface. |
|
313 * @param options MBeanOptions that control the operation of the resulting |
|
314 * MBean. |
|
315 * @param emitter the object that will handle notifications. If null, |
|
316 * a new {@code NotificationEmitter} will be constructed that also |
|
317 * implements {@link SendNotification}. |
|
318 * |
|
319 * @throws IllegalArgumentException if the {@code mbeanInterface} |
|
320 * does not follow JMX design patterns for Management Interfaces, or |
|
321 * if {@code this} does not implement the specified interface. |
|
322 */ |
|
323 protected StandardEmitterMBean(Class<?> mbeanInterface, MBeanOptions options, |
|
324 NotificationEmitter emitter) { |
|
325 super(mbeanInterface, options); |
|
326 MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(this); |
|
327 if (emitter == null) |
|
328 emitter = defaultEmitter(defaultMBNIs); |
|
329 this.emitter = emitter; |
|
330 this.notificationInfo = |
|
331 firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs); |
|
332 injectEmitter(); |
|
333 } |
|
334 |
|
335 private static MBeanNotificationInfo[] defaultMBNIs(Object mbean) { |
|
336 return MBeanIntrospector.findNotificationsFromAnnotations( |
|
337 mbean.getClass()); |
|
338 } |
|
339 |
|
340 private NotificationEmitter defaultEmitter(MBeanNotificationInfo[] defaultMBNIs) { |
|
341 MBeanNotificationInfo[] mbnis = |
|
342 firstNonEmpty(getNotificationInfo(), defaultMBNIs); |
|
343 // Will be null unless getNotificationInfo() is overridden, |
|
344 // since the notificationInfo field has not been set at this point. |
|
345 if (mbnis == null) |
|
346 mbnis = getMBeanInfo().getNotifications(); |
|
347 return new NotificationBroadcasterSupport(mbnis); |
|
348 } |
|
349 |
|
350 private static <T> T[] firstNonEmpty(T[]... items) { |
|
351 for (T[] t : items) { |
|
352 if (t != null && t.length != 0) |
|
353 return t; |
|
354 } |
|
355 return null; |
|
356 } |
|
357 |
|
358 private void injectEmitter() { |
|
359 if (emitter instanceof SendNotification) { |
|
360 try { |
|
361 Object resource = getImplementation(); |
|
362 SendNotification send = (SendNotification) emitter; |
|
363 MBeanInjector.injectSendNotification(resource, send); |
|
364 } catch (RuntimeException e) { |
|
365 throw e; |
|
366 } catch (Exception e) { |
|
367 throw new IllegalArgumentException(e); |
|
368 } |
|
369 } |
|
370 } |
235 } |
371 |
236 |
372 public void removeNotificationListener(NotificationListener listener) |
237 public void removeNotificationListener(NotificationListener listener) |
373 throws ListenerNotFoundException { |
238 throws ListenerNotFoundException { |
374 emitter.removeNotificationListener(listener); |
239 emitter.removeNotificationListener(listener); |
392 } |
257 } |
393 |
258 |
394 /** |
259 /** |
395 * <p>Sends a notification.</p> |
260 * <p>Sends a notification.</p> |
396 * |
261 * |
397 * <p>If the {@code emitter} parameter to the constructor was |
262 * <p>If the {@code emitter} parameter to the constructor was an |
398 * an instance of {@link SendNotification}, such as {@link |
263 * instance of {@code NotificationBroadcasterSupport} then this |
399 * NotificationBroadcasterSupport}, then this method will call {@code |
264 * method will call {@code emitter.}{@link |
400 * emitter.}{@link SendNotification#sendNotification |
265 * NotificationBroadcasterSupport#sendNotification |
401 * sendNotification}.</p> |
266 * sendNotification}.</p> |
402 * |
267 * |
403 * @param n the notification to send. |
268 * @param n the notification to send. |
404 * |
269 * |
405 * @throws ClassCastException if the {@code emitter} parameter to the |
270 * @throws ClassCastException if the {@code emitter} parameter to the |
406 * constructor was not a {@code NotificationBroadcasterSupport}. |
271 * constructor was not a {@code NotificationBroadcasterSupport}. |
407 */ |
272 */ |
408 public void sendNotification(Notification n) { |
273 public void sendNotification(Notification n) { |
409 if (emitter instanceof SendNotification) |
274 if (emitter instanceof NotificationBroadcasterSupport) |
410 ((SendNotification) emitter).sendNotification(n); |
275 ((NotificationBroadcasterSupport) emitter).sendNotification(n); |
411 else { |
276 else { |
412 final String msg = |
277 final String msg = |
413 "Cannot sendNotification when emitter is not an " + |
278 "Cannot sendNotification when emitter is not an " + |
414 "instance of SendNotification: " + emitter.getClass().getName(); |
279 "instance of NotificationBroadcasterSupport: " + |
|
280 emitter.getClass().getName(); |
415 throw new ClassCastException(msg); |
281 throw new ClassCastException(msg); |
416 } |
282 } |
417 } |
283 } |
418 |
284 |
419 /** |
285 /** |