KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > tomcat > util > modeler > BaseModelMBean


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.tomcat.util.modeler;
20
21
22 import java.lang.reflect.InvocationTargetException JavaDoc;
23 import java.lang.reflect.Method JavaDoc;
24 import java.util.Iterator JavaDoc;
25
26 import javax.management.Attribute JavaDoc;
27 import javax.management.AttributeChangeNotification JavaDoc;
28 import javax.management.AttributeList JavaDoc;
29 import javax.management.AttributeNotFoundException JavaDoc;
30 import javax.management.DynamicMBean JavaDoc;
31 import javax.management.InstanceNotFoundException JavaDoc;
32 import javax.management.InvalidAttributeValueException JavaDoc;
33 import javax.management.ListenerNotFoundException JavaDoc;
34 import javax.management.MBeanException JavaDoc;
35 import javax.management.MBeanInfo JavaDoc;
36 import javax.management.MBeanNotificationInfo JavaDoc;
37 import javax.management.MBeanRegistration JavaDoc;
38 import javax.management.MBeanServer JavaDoc;
39 import javax.management.Notification JavaDoc;
40 import javax.management.NotificationFilter JavaDoc;
41 import javax.management.NotificationListener JavaDoc;
42 import javax.management.ObjectName JavaDoc;
43 import javax.management.ReflectionException JavaDoc;
44 import javax.management.RuntimeErrorException JavaDoc;
45 import javax.management.RuntimeOperationsException JavaDoc;
46 import javax.management.modelmbean.InvalidTargetObjectTypeException JavaDoc;
47 import javax.management.modelmbean.ModelMBeanNotificationBroadcaster JavaDoc;
48
49 import org.apache.commons.logging.Log;
50 import org.apache.commons.logging.LogFactory;
51
52 /*
53  * Changes from commons.modeler:
54  *
55  * - use DynamicMBean
56  * - remove methods not used in tomcat and redundant/not very generic
57  * - must be created from the ManagedBean - I don't think there were any direct
58  * uses, but now it is required.
59  * - some of the gratuituous flexibility removed - instead this is more predictive and
60  * strict with the use cases.
61  * - all Method and metadata is stored in ManagedBean. BaseModelBMean and ManagedBean act
62  * like Object and Class.
63  * - setModelMBean is no longer called on resources ( not used in tomcat )
64  * - no caching of Methods for now - operations and setters are not called repeatedly in most
65  * management use cases. Getters should't be called very frequently either - and even if they
66  * are, the overhead of getting the method should be small compared with other JMX costs ( RMI, etc ).
67  * We can add getter cache if needed.
68  * - removed unused constructor, fields
69  *
70  * TODO:
71  * - clean up catalina.mbeans, stop using weird inheritance
72  */

73
74 /**
75  * <p>Basic implementation of the <code>DynamicMBean</code> interface, which
76  * supports the minimal requirements of the interface contract.</p>
77  *
78  * <p>This can be used directly to wrap an existing java bean, or inside
79  * an mlet or anywhere an MBean would be used.
80  *
81  * Limitations:
82  * <ul>
83  * <li>Only managed resources of type <code>objectReference</code> are
84  * supportd.</li>
85  * <li>Caching of attribute values and operation results is not supported.
86  * All calls to <code>invoke()</code> are immediately executed.</li>
87  * <li>Persistence of MBean attributes and operations is not supported.</li>
88  * <li>All classes referenced as attribute types, operation parameters, or
89  * operation return values must be one of the following:
90  * <ul>
91  * <li>One of the Java primitive types (boolean, byte, char, double,
92  * float, integer, long, short). Corresponding value will be wrapped
93  * in the appropriate wrapper class automatically.</li>
94  * <li>Operations that return no value should declare a return type of
95  * <code>void</code>.</li>
96  * </ul>
97  * <li>Attribute caching is not supported</li>
98  * </ul>
99  *
100  * @author Craig R. McClanahan
101  * @author Costin Manolache
102  */

103 public class BaseModelMBean implements DynamicMBean JavaDoc, MBeanRegistration JavaDoc, ModelMBeanNotificationBroadcaster JavaDoc {
104     private static Log log = LogFactory.getLog(BaseModelMBean.class);
105
106     // ----------------------------------------------------------- Constructors
107

108     /**
109      * Construct a <code>ModelMBean</code> with default
110      * <code>ModelMBeanInfo</code> information.
111      *
112      * @exception MBeanException if the initializer of an object
113      * throws an exception
114      * @exception RuntimeOperationsException if an IllegalArgumentException
115      * occurs
116      */

117     protected BaseModelMBean() throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
118         super();
119     }
120
121     // ----------------------------------------------------- Instance Variables
122

123     protected ObjectName JavaDoc oname=null;
124
125     /**
126      * Notification broadcaster for attribute changes.
127      */

128     protected BaseNotificationBroadcaster attributeBroadcaster = null;
129
130     /**
131      * Notification broadcaster for general notifications.
132      */

133     protected BaseNotificationBroadcaster generalBroadcaster = null;
134     
135     /** Metadata for the mbean instance.
136      */

137     protected ManagedBean managedBean = null;
138
139     /**
140      * The managed resource this MBean is associated with (if any).
141      */

142     protected Object JavaDoc resource = null;
143
144     // --------------------------------------------------- DynamicMBean Methods
145
// TODO: move to ManagedBean
146
static final Object JavaDoc[] NO_ARGS_PARAM=new Object JavaDoc[0];
147     static final Class JavaDoc[] NO_ARGS_PARAM_SIG=new Class JavaDoc[0];
148     
149     protected String JavaDoc resourceType = null;
150
151     // key: operation val: invoke method
152
//private Hashtable invokeAttMap=new Hashtable();
153

154     /**
155      * Obtain and return the value of a specific attribute of this MBean.
156      *
157      * @param name Name of the requested attribute
158      *
159      * @exception AttributeNotFoundException if this attribute is not
160      * supported by this MBean
161      * @exception MBeanException if the initializer of an object
162      * throws an exception
163      * @exception ReflectionException if a Java reflection exception
164      * occurs when invoking the getter
165      */

166     public Object JavaDoc getAttribute(String JavaDoc name)
167         throws AttributeNotFoundException JavaDoc, MBeanException JavaDoc,
168             ReflectionException JavaDoc {
169         // Validate the input parameters
170
if (name == null)
171             throw new RuntimeOperationsException JavaDoc
172                 (new IllegalArgumentException JavaDoc("Attribute name is null"),
173                  "Attribute name is null");
174
175         if( (resource instanceof DynamicMBean JavaDoc) &&
176              ! ( resource instanceof BaseModelMBean )) {
177             return ((DynamicMBean JavaDoc)resource).getAttribute(name);
178         }
179         
180         Method JavaDoc m=managedBean.getGetter(name, this, resource);
181         Object JavaDoc result = null;
182         try {
183             Class JavaDoc declaring=m.getDeclaringClass();
184             // workaround for catalina weird mbeans - the declaring class is BaseModelMBean.
185
// but this is the catalina class.
186
if( declaring.isAssignableFrom(this.getClass()) ) {
187                 result = m.invoke(this, NO_ARGS_PARAM );
188             } else {
189                 result = m.invoke(resource, NO_ARGS_PARAM );
190             }
191         } catch (InvocationTargetException JavaDoc e) {
192             Throwable JavaDoc t = e.getTargetException();
193             if (t == null)
194                 t = e;
195             if (t instanceof RuntimeException JavaDoc)
196                 throw new RuntimeOperationsException JavaDoc
197                     ((RuntimeException JavaDoc) t, "Exception invoking method " + name);
198             else if (t instanceof Error JavaDoc)
199                 throw new RuntimeErrorException JavaDoc
200                     ((Error JavaDoc) t, "Error invoking method " + name);
201             else
202                 throw new MBeanException JavaDoc
203                     (e, "Exception invoking method " + name);
204         } catch (Exception JavaDoc e) {
205             throw new MBeanException JavaDoc
206                 (e, "Exception invoking method " + name);
207         }
208
209         // Return the results of this method invocation
210
// FIXME - should we validate the return type?
211
return (result);
212     }
213
214
215     /**
216      * Obtain and return the values of several attributes of this MBean.
217      *
218      * @param names Names of the requested attributes
219      */

220     public AttributeList JavaDoc getAttributes(String JavaDoc names[]) {
221
222         // Validate the input parameters
223
if (names == null)
224             throw new RuntimeOperationsException JavaDoc
225                 (new IllegalArgumentException JavaDoc("Attribute names list is null"),
226                  "Attribute names list is null");
227
228         // Prepare our response, eating all exceptions
229
AttributeList JavaDoc response = new AttributeList JavaDoc();
230         for (int i = 0; i < names.length; i++) {
231             try {
232                 response.add(new Attribute JavaDoc(names[i],getAttribute(names[i])));
233             } catch (Exception JavaDoc e) {
234                 ; // Not having a particular attribute in the response
235
; // is the indication of a getter problem
236
}
237         }
238         return (response);
239
240     }
241
242     public void setManagedBean(ManagedBean managedBean) {
243         this.managedBean = managedBean;
244     }
245
246     /**
247      * Return the <code>MBeanInfo</code> object for this MBean.
248      */

249     public MBeanInfo JavaDoc getMBeanInfo() {
250         return managedBean.getMBeanInfo();
251     }
252
253
254     /**
255      * Invoke a particular method on this MBean, and return any returned
256      * value.
257      *
258      * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation will
259      * attempt to invoke this method on the MBean itself, or (if not
260      * available) on the managed resource object associated with this
261      * MBean.</p>
262      *
263      * @param name Name of the operation to be invoked
264      * @param params Array containing the method parameters of this operation
265      * @param signature Array containing the class names representing
266      * the signature of this operation
267      *
268      * @exception MBeanException if the initializer of an object
269      * throws an exception
270      * @exception ReflectioNException if a Java reflection exception
271      * occurs when invoking a method
272      */

273     public Object JavaDoc invoke(String JavaDoc name, Object JavaDoc params[], String JavaDoc signature[])
274         throws MBeanException JavaDoc, ReflectionException JavaDoc
275     {
276         if( (resource instanceof DynamicMBean JavaDoc) &&
277              ! ( resource instanceof BaseModelMBean )) {
278             return ((DynamicMBean JavaDoc)resource).invoke(name, params, signature);
279         }
280     
281         // Validate the input parameters
282
if (name == null)
283             throw new RuntimeOperationsException JavaDoc
284                 (new IllegalArgumentException JavaDoc("Method name is null"),
285                  "Method name is null");
286
287         if( log.isDebugEnabled()) log.debug("Invoke " + name);
288     MethodKey mkey = new MethodKey(name, signature);
289         Method JavaDoc method= managedBean.getInvoke(name, params, signature, this, resource);
290         
291         // Invoke the selected method on the appropriate object
292
Object JavaDoc result = null;
293         try {
294             if( method.getDeclaringClass().isAssignableFrom( this.getClass()) ) {
295                 result = method.invoke(this, params );
296             } else {
297                 result = method.invoke(resource, params);
298             }
299         } catch (InvocationTargetException JavaDoc e) {
300             Throwable JavaDoc t = e.getTargetException();
301             log.error("Exception invoking method " + name , t );
302             if (t == null)
303                 t = e;
304             if (t instanceof RuntimeException JavaDoc)
305                 throw new RuntimeOperationsException JavaDoc
306                     ((RuntimeException JavaDoc) t, "Exception invoking method " + name);
307             else if (t instanceof Error JavaDoc)
308                 throw new RuntimeErrorException JavaDoc
309                     ((Error JavaDoc) t, "Error invoking method " + name);
310             else
311                 throw new MBeanException JavaDoc
312                     ((Exception JavaDoc)t, "Exception invoking method " + name);
313         } catch (Exception JavaDoc e) {
314             log.error("Exception invoking method " + name , e );
315             throw new MBeanException JavaDoc
316                 (e, "Exception invoking method " + name);
317         }
318
319         // Return the results of this method invocation
320
// FIXME - should we validate the return type?
321
return (result);
322
323     }
324
325     static Class JavaDoc getAttributeClass(String JavaDoc signature)
326         throws ReflectionException JavaDoc
327     {
328         if (signature.equals(Boolean.TYPE.getName()))
329             return Boolean.TYPE;
330         else if (signature.equals(Byte.TYPE.getName()))
331             return Byte.TYPE;
332         else if (signature.equals(Character.TYPE.getName()))
333             return Character.TYPE;
334         else if (signature.equals(Double.TYPE.getName()))
335             return Double.TYPE;
336         else if (signature.equals(Float.TYPE.getName()))
337             return Float.TYPE;
338         else if (signature.equals(Integer.TYPE.getName()))
339             return Integer.TYPE;
340         else if (signature.equals(Long.TYPE.getName()))
341             return Long.TYPE;
342         else if (signature.equals(Short.TYPE.getName()))
343             return Short.TYPE;
344         else {
345             try {
346                 ClassLoader JavaDoc cl=Thread.currentThread().getContextClassLoader();
347                 if( cl!=null )
348                     return cl.loadClass(signature);
349             } catch( ClassNotFoundException JavaDoc e ) {
350             }
351             try {
352                 return Class.forName(signature);
353             } catch (ClassNotFoundException JavaDoc e) {
354                 throw new ReflectionException JavaDoc
355                     (e, "Cannot find Class for " + signature);
356             }
357         }
358     }
359
360     /**
361      * Set the value of a specific attribute of this MBean.
362      *
363      * @param attribute The identification of the attribute to be set
364      * and the new value
365      *
366      * @exception AttributeNotFoundException if this attribute is not
367      * supported by this MBean
368      * @exception MBeanException if the initializer of an object
369      * throws an exception
370      * @exception ReflectionException if a Java reflection exception
371      * occurs when invoking the getter
372      */

373     public void setAttribute(Attribute JavaDoc attribute)
374         throws AttributeNotFoundException JavaDoc, MBeanException JavaDoc,
375         ReflectionException JavaDoc
376     {
377         if( log.isDebugEnabled() )
378             log.debug("Setting attribute " + this + " " + attribute );
379
380         if( (resource instanceof DynamicMBean JavaDoc) &&
381              ! ( resource instanceof BaseModelMBean )) {
382             try {
383                 ((DynamicMBean JavaDoc)resource).setAttribute(attribute);
384             } catch (InvalidAttributeValueException JavaDoc e) {
385                 throw new MBeanException JavaDoc(e);
386             }
387             return;
388         }
389         
390         // Validate the input parameters
391
if (attribute == null)
392             throw new RuntimeOperationsException JavaDoc
393                 (new IllegalArgumentException JavaDoc("Attribute is null"),
394                  "Attribute is null");
395
396         String JavaDoc name = attribute.getName();
397         Object JavaDoc value = attribute.getValue();
398
399         if (name == null)
400             throw new RuntimeOperationsException JavaDoc
401                 (new IllegalArgumentException JavaDoc("Attribute name is null"),
402                  "Attribute name is null");
403
404         Object JavaDoc oldValue=null;
405         //if( getAttMap.get(name) != null )
406
// oldValue=getAttribute( name );
407

408         Method JavaDoc m=managedBean.getSetter(name,this,resource);
409
410         try {
411             if( m.getDeclaringClass().isAssignableFrom( this.getClass()) ) {
412                 m.invoke(this, new Object JavaDoc[] { value });
413             } else {
414                 m.invoke(resource, new Object JavaDoc[] { value });
415             }
416         } catch (InvocationTargetException JavaDoc e) {
417             Throwable JavaDoc t = e.getTargetException();
418             if (t == null)
419                 t = e;
420             if (t instanceof RuntimeException JavaDoc)
421                 throw new RuntimeOperationsException JavaDoc
422                     ((RuntimeException JavaDoc) t, "Exception invoking method " + name);
423             else if (t instanceof Error JavaDoc)
424                 throw new RuntimeErrorException JavaDoc
425                     ((Error JavaDoc) t, "Error invoking method " + name);
426             else
427                 throw new MBeanException JavaDoc
428                     (e, "Exception invoking method " + name);
429         } catch (Exception JavaDoc e) {
430             log.error("Exception invoking method " + name , e );
431             throw new MBeanException JavaDoc
432                 (e, "Exception invoking method " + name);
433         }
434         try {
435             sendAttributeChangeNotification(new Attribute JavaDoc( name, oldValue),
436                     attribute);
437         } catch(Exception JavaDoc ex) {
438             log.error("Error sending notification " + name, ex);
439         }
440         //attributes.put( name, value );
441
// if( source != null ) {
442
// // this mbean is asscoiated with a source - maybe we want to persist
443
// source.updateField(oname, name, value);
444
// }
445
}
446
447     public String JavaDoc toString() {
448         if( resource==null )
449             return "BaseModelMbean[" + resourceType + "]";
450         return resource.toString();
451     }
452
453     /**
454      * Set the values of several attributes of this MBean.
455      *
456      * @param attributes THe names and values to be set
457      *
458      * @return The list of attributes that were set and their new values
459      */

460     public AttributeList JavaDoc setAttributes(AttributeList JavaDoc attributes) {
461         AttributeList JavaDoc response = new AttributeList JavaDoc();
462
463         // Validate the input parameters
464
if (attributes == null)
465             return response;
466         
467         // Prepare and return our response, eating all exceptions
468
String JavaDoc names[] = new String JavaDoc[attributes.size()];
469         int n = 0;
470         Iterator JavaDoc items = attributes.iterator();
471         while (items.hasNext()) {
472             Attribute JavaDoc item = (Attribute JavaDoc) items.next();
473             names[n++] = item.getName();
474             try {
475                 setAttribute(item);
476             } catch (Exception JavaDoc e) {
477                 ; // Ignore all exceptions
478
}
479         }
480
481         return (getAttributes(names));
482
483     }
484
485
486     // ----------------------------------------------------- ModelMBean Methods
487

488
489     /**
490      * Get the instance handle of the object against which we execute
491      * all methods in this ModelMBean management interface.
492      *
493      * @exception InstanceNotFoundException if the managed resource object
494      * cannot be found
495      * @exception MBeanException if the initializer of the object throws
496      * an exception
497      * @exception RuntimeOperationsException if the managed resource or the
498      * resource type is <code>null</code> or invalid
499      */

500     public Object JavaDoc getManagedResource()
501         throws InstanceNotFoundException JavaDoc, InvalidTargetObjectTypeException JavaDoc,
502         MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
503
504         if (resource == null)
505             throw new RuntimeOperationsException JavaDoc
506                 (new IllegalArgumentException JavaDoc("Managed resource is null"),
507                  "Managed resource is null");
508
509         return resource;
510
511     }
512
513
514     /**
515      * Set the instance handle of the object against which we will execute
516      * all methods in this ModelMBean management interface.
517      *
518      * <strike>This method will detect and call "setModelMbean" method. A resource
519      * can implement this method to get a reference to the model mbean.
520      * The reference can be used to send notification and access the
521      * registry.
522      * </strike> The caller can provide the mbean instance or the object name to
523      * the resource, if needed.
524      *
525      * @param resource The resource object to be managed
526      * @param type The type of reference for the managed resource
527      * ("ObjectReference", "Handle", "IOR", "EJBHandle", or
528      * "RMIReference")
529      *
530      * @exception InstanceNotFoundException if the managed resource object
531      * cannot be found
532      * @exception InvalidTargetObjectTypeException if this ModelMBean is
533      * asked to handle a reference type it cannot deal with
534      * @exception MBeanException if the initializer of the object throws
535      * an exception
536      * @exception RuntimeOperationsException if the managed resource or the
537      * resource type is <code>null</code> or invalid
538      */

539     public void setManagedResource(Object JavaDoc resource, String JavaDoc type)
540         throws InstanceNotFoundException JavaDoc,
541         MBeanException JavaDoc, RuntimeOperationsException JavaDoc
542     {
543         if (resource == null)
544             throw new RuntimeOperationsException JavaDoc
545                 (new IllegalArgumentException JavaDoc("Managed resource is null"),
546                  "Managed resource is null");
547
548 // if (!"objectreference".equalsIgnoreCase(type))
549
// throw new InvalidTargetObjectTypeException(type);
550

551         this.resource = resource;
552         this.resourceType = resource.getClass().getName();
553         
554 // // Make the resource aware of the model mbean.
555
// try {
556
// Method m=resource.getClass().getMethod("setModelMBean",
557
// new Class[] {ModelMBean.class});
558
// if( m!= null ) {
559
// m.invoke(resource, new Object[] {this});
560
// }
561
// } catch( NoSuchMethodException t ) {
562
// // ignore
563
// } catch( Throwable t ) {
564
// log.error( "Can't set model mbean ", t );
565
// }
566
}
567
568
569     // ------------------------------ ModelMBeanNotificationBroadcaster Methods
570

571
572     /**
573      * Add an attribute change notification event listener to this MBean.
574      *
575      * @param listener Listener that will receive event notifications
576      * @param name Name of the attribute of interest, or <code>null</code>
577      * to indicate interest in all attributes
578      * @param handback Handback object to be sent along with event
579      * notifications
580      *
581      * @exception IllegalArgumentException if the listener parameter is null
582      */

583     public void addAttributeChangeNotificationListener
584         (NotificationListener JavaDoc listener, String JavaDoc name, Object JavaDoc handback)
585         throws IllegalArgumentException JavaDoc {
586
587         if (listener == null)
588             throw new IllegalArgumentException JavaDoc("Listener is null");
589         if (attributeBroadcaster == null)
590             attributeBroadcaster = new BaseNotificationBroadcaster();
591
592         if( log.isDebugEnabled() )
593             log.debug("addAttributeNotificationListener " + listener);
594
595         BaseAttributeFilter filter = new BaseAttributeFilter(name);
596         attributeBroadcaster.addNotificationListener
597             (listener, filter, handback);
598
599     }
600
601
602     /**
603      * Remove an attribute change notification event listener from
604      * this MBean.
605      *
606      * @param listener The listener to be removed
607      * @param name The attribute name for which no more events are required
608      *
609      *
610      * @exception ListenerNotFoundException if this listener is not
611      * registered in the MBean
612      */

613     public void removeAttributeChangeNotificationListener
614         (NotificationListener JavaDoc listener, String JavaDoc name)
615         throws ListenerNotFoundException JavaDoc {
616
617         if (listener == null)
618             throw new IllegalArgumentException JavaDoc("Listener is null");
619         if (attributeBroadcaster == null)
620             attributeBroadcaster = new BaseNotificationBroadcaster();
621
622         // FIXME - currently this removes *all* notifications for this listener
623
attributeBroadcaster.removeNotificationListener(listener);
624
625     }
626
627
628     /**
629      * Remove an attribute change notification event listener from
630      * this MBean.
631      *
632      * @param listener The listener to be removed
633      * @param attributeName The attribute name for which no more events are required
634      * @param handback Handback object to be sent along with event
635      * notifications
636      *
637      *
638      * @exception ListenerNotFoundException if this listener is not
639      * registered in the MBean
640      */

641     public void removeAttributeChangeNotificationListener
642         (NotificationListener JavaDoc listener, String JavaDoc attributeName, Object JavaDoc handback)
643         throws ListenerNotFoundException JavaDoc {
644
645         removeAttributeChangeNotificationListener(listener, attributeName);
646
647     }
648
649
650     /**
651      * Send an <code>AttributeChangeNotification</code> to all registered
652      * listeners.
653      *
654      * @param notification The <code>AttributeChangeNotification</code>
655      * that will be passed
656      *
657      * @exception MBeanException if an object initializer throws an
658      * exception
659      * @exception RuntimeOperationsException wraps IllegalArgumentException
660      * when the specified notification is <code>null</code> or invalid
661      */

662     public void sendAttributeChangeNotification
663         (AttributeChangeNotification JavaDoc notification)
664         throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
665
666         if (notification == null)
667             throw new RuntimeOperationsException JavaDoc
668                 (new IllegalArgumentException JavaDoc("Notification is null"),
669                  "Notification is null");
670         if (attributeBroadcaster == null)
671             return; // This means there are no registered listeners
672
if( log.isDebugEnabled() )
673             log.debug( "AttributeChangeNotification " + notification );
674         attributeBroadcaster.sendNotification(notification);
675
676     }
677
678
679     /**
680      * Send an <code>AttributeChangeNotification</code> to all registered
681      * listeners.
682      *
683      * @param oldValue The original value of the <code>Attribute</code>
684      * @param newValue The new value of the <code>Attribute</code>
685      *
686      * @exception MBeanException if an object initializer throws an
687      * exception
688      * @exception RuntimeOperationsException wraps IllegalArgumentException
689      * when the specified notification is <code>null</code> or invalid
690      */

691     public void sendAttributeChangeNotification
692         (Attribute JavaDoc oldValue, Attribute JavaDoc newValue)
693         throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
694
695         // Calculate the class name for the change notification
696
String JavaDoc type = null;
697         if (newValue.getValue() != null)
698             type = newValue.getValue().getClass().getName();
699         else if (oldValue.getValue() != null)
700             type = oldValue.getValue().getClass().getName();
701         else
702             return; // Old and new are both null == no change
703

704         AttributeChangeNotification JavaDoc notification =
705             new AttributeChangeNotification JavaDoc
706             (this, 1, System.currentTimeMillis(),
707              "Attribute value has changed",
708              oldValue.getName(), type,
709              oldValue.getValue(), newValue.getValue());
710         sendAttributeChangeNotification(notification);
711
712     }
713
714
715
716
717     /**
718      * Send a <code>Notification</code> to all registered listeners as a
719      * <code>jmx.modelmbean.general</code> notification.
720      *
721      * @param notification The <code>Notification</code> that will be passed
722      *
723      * @exception MBeanException if an object initializer throws an
724      * exception
725      * @exception RuntimeOperationsException wraps IllegalArgumentException
726      * when the specified notification is <code>null</code> or invalid
727      */

728     public void sendNotification(Notification JavaDoc notification)
729         throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
730
731         if (notification == null)
732             throw new RuntimeOperationsException