KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > modelmbean > RequiredModelMBean


1 /*
2  * @(#)file RequiredModelMBean.java
3  * @(#)author Sun Microsystems, Inc.
4  * @(#)version 1.55
5  * @(#)lastedit 07/07/24
6  *
7  * Copyright IBM Corp. 1999-2000. All rights reserved.
8  *
9  * The program is provided "as is" without any warranty express or implied,
10  * including the warranty of non-infringement and the implied warranties of
11  * merchantibility and fitness for a particular purpose. IBM will not be
12  * liable for any damages suffered by you or any third party claim against
13  * you regarding the Program.
14  *
15  * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
16  * This software is the proprietary information of Sun Microsystems, Inc.
17  * Use is subject to license terms.
18  *
19  * Copyright 2005 Sun Microsystems, Inc. Tous droits reserves.
20  * Ce logiciel est propriete de Sun Microsystems, Inc.
21  * Distribue par des licences qui en restreignent l'utilisation.
22  *
23  */

24
25
26
27
28 package javax.management.modelmbean;
29
30 /* java imports */
31
32 import java.lang.reflect.Method JavaDoc;
33 import java.lang.reflect.InvocationTargetException JavaDoc;
34
35 import java.util.Date JavaDoc;
36 import java.util.HashMap JavaDoc;
37 import java.util.HashSet JavaDoc;
38 import java.util.Iterator JavaDoc;
39 import java.util.Map JavaDoc;
40 import java.util.Set JavaDoc;
41
42 import java.io.PrintStream JavaDoc;
43 import java.io.FileOutputStream JavaDoc;
44
45 import javax.management.Attribute JavaDoc;
46 import javax.management.AttributeList JavaDoc;
47 import javax.management.AttributeChangeNotification JavaDoc;
48 import javax.management.AttributeChangeNotificationFilter JavaDoc;
49 import javax.management.AttributeNotFoundException JavaDoc;
50 import javax.management.Descriptor JavaDoc;
51 import javax.management.DescriptorAccess JavaDoc;
52 import javax.management.InstanceNotFoundException JavaDoc;
53 import javax.management.InvalidAttributeValueException JavaDoc;
54 import javax.management.ListenerNotFoundException JavaDoc;
55 import javax.management.MBeanAttributeInfo JavaDoc;
56 import javax.management.MBeanConstructorInfo JavaDoc;
57 import javax.management.MBeanException JavaDoc;
58 import javax.management.MBeanInfo JavaDoc;
59 import javax.management.MBeanNotificationInfo JavaDoc;
60 import javax.management.MBeanOperationInfo JavaDoc;
61 import javax.management.MBeanRegistration JavaDoc;
62 import javax.management.MBeanRegistrationException JavaDoc;
63 import javax.management.MBeanServer JavaDoc;
64 import javax.management.MBeanServerFactory JavaDoc;
65 import javax.management.Notification JavaDoc;
66 import javax.management.NotificationBroadcasterSupport JavaDoc;
67 import javax.management.NotificationFilter JavaDoc;
68 import javax.management.NotificationListener JavaDoc;
69 import javax.management.ObjectName JavaDoc;
70 import javax.management.ReflectionException JavaDoc;
71 import javax.management.RuntimeErrorException JavaDoc;
72 import javax.management.RuntimeMBeanException JavaDoc;
73 import javax.management.RuntimeOperationsException JavaDoc;
74 import javax.management.ServiceNotFoundException JavaDoc;
75 import javax.management.NotificationEmitter JavaDoc;
76 import javax.management.loading.ClassLoaderRepository JavaDoc;
77
78 import sun.reflect.misc.MethodUtil;
79 import sun.reflect.misc.ReflectUtil;
80
81 import com.sun.jmx.trace.Trace;
82
83 /**
84  * This class is the implementation of a ModelMBean. An appropriate
85  * implementation of a ModelMBean must be shipped with every JMX Agent
86  * and the class must be named RequiredModelMBean.
87  * <P>
88  * Java resources wishing to be manageable instantiate the
89  * RequiredModelMBean using the MBeanServer's createMBean method.
90  * The resource then sets the MBeanInfo and Descriptors for the
91  * RequiredModelMBean instance. The attributes and operations exposed
92  * via the ModelMBeanInfo for the ModelMBean are accessible
93  * from MBeans, connectors/adaptors like other MBeans. Through the
94  * Descriptors, values and methods in the managed application can be
95  * defined and mapped to attributes and operations of the ModelMBean.
96  * This mapping can be defined in an XML formatted file or dynamically and
97  * programmatically at runtime.
98  * <P>
99  * Every RequiredModelMBean which is instantiated in the MBeanServer
100  * becomes manageable:<br>
101  * its attributes and operations become remotely accessible through the
102  * connectors/adaptors connected to that MBeanServer.
103  * <P>
104  * A Java object cannot be registered in the MBeanServer unless it is a
105  * JMX compliant MBean. By instantiating a RequiredModelMBean, resources
106  * are guaranteed that the MBean is valid.
107  *
108  * MBeanException and RuntimeOperationsException must be thrown on every
109  * public method. This allows for wrapping exceptions from distributed
110  * communications (RMI, EJB, etc.)
111  *
112  * @since 1.5
113  */

114
115 public class RequiredModelMBean
116     implements ModelMBean JavaDoc, MBeanRegistration JavaDoc, NotificationEmitter JavaDoc {
117
118     /*************************************/
119     /* attributes */
120     /*************************************/
121     ModelMBeanInfo JavaDoc modelMBeanInfo;
122
123     /* Notification broadcaster for any notification to be sent
124      * from the application through the RequiredModelMBean. */

125     private NotificationBroadcasterSupport JavaDoc generalBroadcaster = null;
126
127     /* Notification broadcaster for attribute change notifications */
128     private NotificationBroadcasterSupport JavaDoc attributeBroadcaster = null;
129
130     /* handle, name, or reference for instance on which the actual invoke
131      * and operations will be executed */

132     private Object JavaDoc managedResource = null;
133
134     private static final String JavaDoc currClass = "RequiredModelMBean";
135
136     /* records the registering in MBeanServer */
137     private boolean registered = false;
138     private transient MBeanServer JavaDoc server = null;
139
140     /*************************************/
141     /* constructors */
142     /*************************************/
143
144     /**
145      * Constructs an <CODE>RequiredModelMBean</CODE> with an empty
146      * ModelMBeanInfo.
147      * <P>
148      * The RequiredModelMBean's MBeanInfo and Descriptors
149      * can be customized using the {@link #setModelMBeanInfo} method.
150      * After the RequiredModelMBean's MBeanInfo and Descriptors are
151      * customized, the RequiredModelMBean can be registered with
152      * the MBeanServer.
153      *
154      * @exception MBeanException Wraps a distributed communication Exception.
155      *
156      * @exception RuntimeOperationsException Wraps a {@link
157      * RuntimeException} during the construction of the object.
158      **/

159     public RequiredModelMBean()
160     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
161
162     if (tracing())
163         trace("RequiredModelMBean()","Entry and Exit");
164
165     modelMBeanInfo = createDefaultModelMBeanInfo();
166     }
167
168     /**
169      * Constructs a RequiredModelMBean object using ModelMBeanInfo passed in.
170      * As long as the RequiredModelMBean is not registered
171      * with the MBeanServer yet, the RequiredModelMBean's MBeanInfo and
172      * Descriptors can be customized using the {@link #setModelMBeanInfo}
173      * method.
174      * After the RequiredModelMBean's MBeanInfo and Descriptors are
175      * customized, the RequiredModelMBean can be registered with the
176      * MBeanServer.
177      *
178      * @param mbi The ModelMBeanInfo object to be used by the
179      * RequiredModelMBean. The given ModelMBeanInfo is cloned
180      * and modified as specified by {@link #setModelMBeanInfo}
181      *
182      * @exception MBeanException Wraps a distributed communication Exception.
183      * @exception RuntimeOperationsException Wraps an
184      * {link java.lang.IllegalArgumentException}:
185      * The MBeanInfo passed in parameter is null.
186      *
187      **/

188     public RequiredModelMBean(ModelMBeanInfo JavaDoc mbi)
189     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
190
191     if (tracing())
192         trace("RequiredModelMBean(MBeanInfo)","Entry");
193
194     setModelMBeanInfo(mbi);
195
196     if (tracing())
197         trace("RequiredModelMBean(MBeanInfo)","Exit");
198     }
199
200
201     /*************************************/
202     /* initializers */
203     /*************************************/
204
205     /**
206      * Initializes a ModelMBean object using ModelMBeanInfo passed in.
207      * This method makes it possible to set a customized ModelMBeanInfo on
208      * the ModelMBean as long as it is not registered with the MBeanServer.
209      * <br>
210      * Once the ModelMBean's ModelMBeanInfo (with Descriptors) are
211      * customized and set on the ModelMBean, the ModelMBean be
212      * registered with the MBeanServer.
213      * <P>
214      * If the ModelMBean is currently registered, this method throws
215      * a {@link javax.management.RuntimeOperationsException} wrapping an
216      * {@link IllegalStateException}
217      * <P>
218      * If the given <var>inModelMBeanInfo</var> does not contain any
219      * {@link ModelMBeanNotificationInfo} for the <code>GENERIC</code>
220      * or <code>ATTRIBUTE_CHANGE</code> notifications, then the
221      * RequiredModelMBean will supply its own default
222      * {@link ModelMBeanNotificationInfo ModelMBeanNotificationInfo}s for
223      * those missing notifications.
224      *
225      * @param mbi The ModelMBeanInfo object to be used
226      * by the ModelMBean.
227      *
228      * @exception MBeanException Wraps a distributed communication
229      * Exception.
230      * @exception RuntimeOperationsException
231      * <ul><li>Wraps an {@link IllegalArgumentException} if
232      * the MBeanInfo passed in parameter is null.</li>
233      * <li>Wraps an {@link IllegalStateException} if the ModelMBean
234      * is currently registered in the MBeanServer.</li>
235      * </ul>
236      *
237      **/

238     public void setModelMBeanInfo(ModelMBeanInfo JavaDoc mbi)
239     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
240     
241     if (tracing())
242         trace("setModelMBeanInfo(ModelMBeanInfo)","Entry");
243     
244     if (mbi == null) {
245         if (tracing())
246         trace("setModelMBeanInfo(ModelMBeanInfo)",
247               "ModelMBeanInfo is null: Raising exception.");
248         final RuntimeException JavaDoc x = new
249         IllegalArgumentException JavaDoc("ModelMBeanInfo must not be null");
250         final String JavaDoc exceptionText =
251         "Exception occured trying to initialize the " +
252         "ModelMBeanInfo of the RequiredModelMBean";
253         throw new RuntimeOperationsException JavaDoc(x,exceptionText);
254     }
255
256     if (registered) {
257         if (tracing())
258         trace("setModelMBeanInfo(ModelMBeanInfo)",
259               "RequiredMBean is registered: Raising exception.");
260         final String JavaDoc exceptionText =
261         "Exception occured trying to set the " +
262         "ModelMBeanInfo of the RequiredModelMBean";
263         final RuntimeException JavaDoc x = new IllegalStateException JavaDoc(
264          "cannot call setModelMBeanInfo while ModelMBean is registered");
265         throw new RuntimeOperationsException JavaDoc(x,exceptionText);
266     }
267
268     if (tracing()) {
269         trace("setModelMBeanInfo(ModelMBeanInfo)",
270           "Setting ModelMBeanInfo to " + printModelMBeanInfo(mbi));
271         trace("setModelMBeanInfo(ModelMBeanInfo)",
272           "ModelMBeanInfo notifications has " +
273           (mbi.getNotifications()).length + " elements");
274     }
275
276     modelMBeanInfo = (ModelMBeanInfo JavaDoc)mbi.clone();
277     
278     if (tracing())
279         trace("setModelMBeanInfo(ModelMBeanInfo)","set mbeanInfo to: "+
280           printModelMBeanInfo(modelMBeanInfo));
281     
282     if (tracing())
283         trace("setModelMBeanInfo(ModelMBeanInfo)","Exit");
284     }
285
286
287     /**
288      * Sets the instance handle of the object against which to
289      * execute all methods in this ModelMBean management interface
290      * (MBeanInfo and Descriptors).
291      *
292      * @param mr Object that is the managed resource
293      * @param mr_type The type of reference for the managed resource.
294      * <br>Can be: "ObjectReference", "Handle", "IOR", "EJBHandle",
295      * or "RMIReference".
296      * <br>In this implementation only "ObjectReference" is supported.
297      *
298      * @exception MBeanException The initializer of the object has
299      * thrown an exception.
300      * @exception InstanceNotFoundException The managed resource
301      * object could not be found
302      * @exception InvalidTargetObjectTypeException The managed
303      * resource type should be "ObjectReference".
304      * @exception RuntimeOperationsException Wraps a {@link
305      * RuntimeException} when setting the resource.
306      **/

307     public void setManagedResource(Object JavaDoc mr, String JavaDoc mr_type)
308     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc,
309            InstanceNotFoundException JavaDoc, InvalidTargetObjectTypeException JavaDoc {
310     if (tracing())
311         trace("setManagedResource(Object,String)","Entry");
312
313     // check that the mr_type is supported by this JMXAgent
314
// only "objectReference" is supported
315
if ((mr_type == null) ||
316         (! mr_type.equalsIgnoreCase("objectReference"))) {
317         if (tracing())
318         trace("setManagedResource(Object,String)",
319               "Managed Resouce Type is not supported: " + mr_type);
320     
321         throw new InvalidTargetObjectTypeException JavaDoc(mr_type);
322     }
323
324     if (tracing())
325         trace("setManagedResource(Object,String)",
326           "Managed Resouce is valid");
327
328     managedResource = mr;
329         
330     if (tracing())
331         trace("setManagedResource(Object, String)", "Exit");
332     }
333
334     /**
335      * <p>Instantiates this MBean instance with the data found for
336      * the MBean in the persistent store. The data loaded could include
337      * attribute and operation values.</p>
338      *
339      * <p>This method should be called during construction or
340      * initialization of this instance, and before the MBean is
341      * registered with the MBeanServer.</p>
342      *
343      * <p>If the implementation of this class does not support
344      * persistence, an {@link MBeanException} wrapping a {@link
345      * ServiceNotFoundException} is thrown.</p>
346      *
347      * @exception MBeanException Wraps another exception, or
348      * persistence is not supported
349      * @exception RuntimeOperationsException Wraps exceptions from the
350      * persistence mechanism
351      * @exception InstanceNotFoundException Could not find or load
352      * this MBean from persistent storage
353      */

354     public void load()
355     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc,
356            InstanceNotFoundException JavaDoc {
357     final ServiceNotFoundException JavaDoc x = new ServiceNotFoundException JavaDoc(
358                     "Persistence not supported for this MBean");
359     throw new MBeanException JavaDoc(x, x.getMessage());
360     }
361
362         /**
363      * <p>Captures the current state of this MBean instance and writes
364      * it out to the persistent store. The state stored could include
365      * attribute and operation values.</p>
366      *
367      * <p>If the implementation of this class does not support
368      * persistence, an {@link MBeanException} wrapping a {@link
369      * ServiceNotFoundException} is thrown.</p>
370      *
371      * <p>Persistence policy from the MBean and attribute descriptor
372      * is used to guide execution of this method. The MBean should be
373      * stored if 'persistPolicy' field is:</p>
374      *
375      * <PRE> != "never"
376      * = "always"
377      * = "onTimer" and now > 'lastPersistTime' + 'persistPeriod'
378      * = "NoMoreOftenThan" and now > 'lastPersistTime' + 'persistPeriod'
379      * </PRE>
380      *
381      * <p>Do not store the MBean if 'persistPolicy' field is:</p>
382      * <PRE>
383      * = "never"
384      * = "onUpdate"
385      * = "onTimer" && now < 'lastPersistTime' + 'persistPeriod'
386      * </PRE>
387      *
388      * @exception MBeanException Wraps another exception, or
389      * persistence is not supported
390      * @exception RuntimeOperationsException Wraps exceptions from the
391      * persistence mechanism
392      * @exception InstanceNotFoundException Could not find/access the
393      * persistent store
394      */

395     public void store()
396     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc,
397            InstanceNotFoundException JavaDoc {
398     final ServiceNotFoundException JavaDoc x = new ServiceNotFoundException JavaDoc(
399                     "Persistence not supported for this MBean");
400     throw new MBeanException JavaDoc(x, x.getMessage());
401     }
402
403     /*************************************/
404     /* DynamicMBean Interface */
405     /*************************************/
406
407     /**
408      * The resolveForCacheValue method checks the descriptor passed in to
409      * see if there is a valid cached value in the descriptor.
410      * The valid value will be in the 'value' field if there is one.
411      * If the 'currencyTimeLimit' field in the descriptor is:
412      * <ul>
413      * <li><b>&lt;0</b> Then the value is not cached and is never valid.
414      * Null is returned. The 'value' and 'lastUpdatedTimeStamp'
415      * fields are cleared.</li>
416      * <li><b>=0</b> Then the value is always cached and always valid.
417      * The 'value' field is returned.
418      * The 'lastUpdatedTimeStamp' field is not checked.</li>
419      * <li><b>&gt;0</b> Represents the number of seconds that the
420      * 'value' field is valid.
421      * The 'value' field is no longer valid when
422      * 'lastUpdatedTimeStamp' + 'currencyTimeLimit' &gt; Now.</li>
423      * </ul>
424      * <li>When 'value' is valid, 'valid' is returned.</li>
425      * <li>When 'value' is no longer valid then null is returned and
426      * 'value' and 'lastUpdatedTimeStamp' fields are cleared.</li>
427      *
428      **/

429     private Object JavaDoc resolveForCacheValue(Descriptor JavaDoc descr)
430     throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
431     if (tracing())
432         trace("resolveForCacheValue(Descriptor)","Entry");
433
434     Object JavaDoc response = null;
435     boolean resetValue = false, returnCachedValue = true;
436     long currencyPeriod = 0;
437
438     if (descr == null) {
439         if (tracing())
440         trace("resolveForCacheValue(Descriptor)",
441               "Input Descriptor is null");
442         return response;
443     }
444
445     if (tracing())
446         trace("resolveForCacheValue(Descriptor)","descriptor is " +
447           descr.toString());
448
449     final Descriptor JavaDoc mmbDescr = modelMBeanInfo.getMBeanDescriptor();
450     if (mmbDescr == null) {
451         if (tracing())
452         trace("resolveForCacheValue(Descriptor)",
453               "MBean Descriptor is null");
454         //return response;
455
}
456
457     Object JavaDoc objExpTime = descr.getFieldValue("currencyTimeLimit");
458
459     String JavaDoc expTime;
460     if (objExpTime != null) {
461         expTime = objExpTime.toString();
462     } else {
463         expTime = null;
464     }
465
466     if ((expTime == null) && (mmbDescr != null)) {
467         objExpTime = mmbDescr.getFieldValue("currencyTimeLimit");
468         if (objExpTime != null) {
469         expTime = objExpTime.toString();
470         } else {
471         expTime = null;
472         }
473     }
474
475     if (expTime != null) {
476         if (tracing())
477         trace("resolveForCacheValue(Descriptor)",
478               "currencyTimeLimit: " + expTime);
479
480         // convert seconds to milliseconds for time comparison
481
currencyPeriod = ((new Long JavaDoc(expTime)).longValue()) * 1000;
482         if (currencyPeriod < 0) {
483         /* if currencyTimeLimit is -1 then value is never cached */
484         returnCachedValue = false;
485         resetValue = true;
486         if (tracing())
487             trace("resolveForCacheValue(Descriptor)",
488               currencyPeriod + ": never Cached");
489         } else if (currencyPeriod == 0) {
490         /* if currencyTimeLimit is 0 then value is always cached */
491         returnCachedValue = true;
492         resetValue = false;
493         if (tracing())
494             trace("resolveForCacheValue(Descriptor)",
495               "always valid Cache");
496         } else {
497         Object JavaDoc objtStamp =
498             descr.getFieldValue("lastUpdatedTimeStamp");
499
500         String JavaDoc tStamp;
501         if (objtStamp != null) tStamp = objtStamp.toString();
502         else tStamp = null;
503         
504         if (tracing())
505             trace("resolveForCacheValue(Descriptor)",
506               "lastUpdatedTimeStamp: " + tStamp);
507
508         if (tStamp == null)
509             tStamp = "0";
510     
511         long lastTime = (new Long JavaDoc(tStamp)).longValue();
512
513         if (tracing())
514             trace("resolveForCacheValue(Descriptor)",
515               " currencyPeriod:" + currencyPeriod +
516               " lastUpdatedTimeStamp:" + lastTime);
517
518         long now = (new Date JavaDoc()).getTime();
519
520         if (now < (lastTime + currencyPeriod)) {
521             returnCachedValue = true;
522             resetValue = false;
523             if (tracing())
524             trace("resolveForCacheValue(Descriptor)",
525                   " timed valid Cache for " + now + " < " +
526                   (lastTime + currencyPeriod));
527         } else { /* value is expired */
528             returnCachedValue = false;
529             resetValue = true;
530             if (tracing())
531             trace("resolveForCacheValue(Descriptor)",
532                   "timed expired cache for " + now + " > " +
533                   (lastTime + currencyPeriod));
534         }
535         }
536
537         if (tracing())
538         trace("resolveForCacheValue(Descriptor)",
539               "returnCachedValue:" + returnCachedValue +
540               " resetValue: " + resetValue);
541
542         if (returnCachedValue == true) {
543         Object JavaDoc currValue = descr.getFieldValue("value");
544         if (currValue != null) {
545             /* error/validity check return value here */
546             response = currValue;
547             /* need to cast string cached value to type */
548             if (tracing())
549             trace("resolveForCacheValue(Descriptor)",
550                   "valid Cache value: " + currValue);
551                     
552         } else {
553             response = null;
554             if (tracing())
555             trace("resolveForCacheValue(Descriptor)",
556                   "no Cached value");
557         }
558         }
559
560         if (resetValue == true) {
561         /* value is not current, so remove it */
562         descr.removeField("lastUpdatedTimeStamp");
563         descr.removeField("value");
564         response = null;
565         modelMBeanInfo.setDescriptor(descr,null);
566         if (tracing())
567             trace("resolveForCacheValue(Descriptor)",
568               "reset cached value to null");
569         }
570     }
571
572     if (tracing())
573         trace("resolveForCache(Descriptor)","Exit");
574
575     return response;
576     }
577
578     /**
579      * Returns the attributes, operations, constructors and notifications
580      * that this RequiredModelMBean exposes for management.
581      *
582      * @return An instance of ModelMBeanInfo allowing retrieval all
583      * attributes, operations, and Notifications of this MBean.
584      *
585      **/

586     public MBeanInfo JavaDoc getMBeanInfo() {
587     
588     if (tracing())
589         trace("getMBeanInfo()","Entry and Exit");
590
591     if (modelMBeanInfo == null) {
592         if (tracing())
593         trace("getMBeanInfo()","modelMBeanInfo is null");
594         modelMBeanInfo = createDefaultModelMBeanInfo();
595         //return new ModelMBeanInfo(" ", "", null, null, null, null);
596
}
597
598     if (tracing()) {
599         trace("getMBeanInfo()","ModelMBeanInfo is " +
600           modelMBeanInfo.getClassName() + " for " +
601           modelMBeanInfo.getDescription());
602         trace("getMBeanInfo()",printModelMBeanInfo(modelMBeanInfo));
603     }
604
605     return((MBeanInfo JavaDoc) ((ModelMBeanInfo JavaDoc)modelMBeanInfo).clone());
606     }
607
608     private String JavaDoc printModelMBeanInfo(ModelMBeanInfo JavaDoc info) {
609     final StringBuffer JavaDoc retStr = new StringBuffer JavaDoc();
610     if (info == null) {
611         if (tracing())
612         trace("printModelMBeanInfo(ModelMBeanInfo)",
613               "ModelMBeanInfo to print is null, " +
614               "printing local ModelMBeanInfo");
615         info = modelMBeanInfo;
616     }
617
618     retStr.append("\nMBeanInfo for ModelMBean is:");
619     retStr.append("\nCLASSNAME: \t"+ info.getClassName());
620     retStr.append("\nDESCRIPTION: \t"+ info.getDescription());
621
622
623     try {
624         retStr.append("\nMBEAN DESCRIPTOR: \t"+
625               info.getMBeanDescriptor());
626     } catch (Exception JavaDoc e) {
627         retStr.append("\nMBEAN DESCRIPTOR: \t" + " is invalid");
628     }
629
630     retStr.append("\nATTRIBUTES");
631
632     final MBeanAttributeInfo JavaDoc[] attrInfo = info.getAttributes();
633     if ((attrInfo != null) && (attrInfo.length>0)) {
634         for (int i=0; i<attrInfo.length; i++) {
635         final ModelMBeanAttributeInfo JavaDoc attInfo =
636             (ModelMBeanAttributeInfo JavaDoc)attrInfo[i];
637         retStr.append(" ** NAME: \t"+ attInfo.getName());
638         retStr.append(" DESCR: \t"+ attInfo.getDescription());
639         retStr.append(" TYPE: \t"+ attInfo.getType() +
640                   " READ: \t"+ attInfo.isReadable() +
641                   " WRITE: \t"+ attInfo.isWritable());
642         retStr.append(" DESCRIPTOR: " +
643                   attInfo.getDescriptor().toString());
644         }
645     } else {
646         retStr.append(" ** No attributes **");
647     }
648
649     retStr.append("\nCONSTRUCTORS");
650     final MBeanConstructorInfo JavaDoc[] constrInfo = info.getConstructors();
651     if ((constrInfo != null) && (constrInfo.length > 0 )) {
652         for (int i=0; i<constrInfo.length; i++) {
653         final ModelMBeanConstructorInfo JavaDoc ctorInfo =
654             (ModelMBeanConstructorInfo JavaDoc)constrInfo[i];
655         retStr.append(" ** NAME: \t"+ ctorInfo.getName());
656         retStr.append(" DESCR: \t"+
657                   ctorInfo.getDescription());
658         retStr.append(" PARAM: \t"+
659                   ctorInfo.getSignature().length +
660                   " parameter(s)");
661         retStr.append(" DESCRIPTOR: " +
662                   ctorInfo.getDescriptor().toString());
663         }
664     } else {
665         retStr.append(" ** No Constructors **");
666     }
667         
668     retStr.append("\nOPERATIONS");
669     final MBeanOperationInfo JavaDoc[] opsInfo = info.getOperations();
670     if ((opsInfo != null) && (opsInfo.length>0)) {
671         for (int i=0; i<opsInfo.length; i++) {
672         final ModelMBeanOperationInfo JavaDoc operInfo =
673             (ModelMBeanOperationInfo JavaDoc)opsInfo[i];
674         retStr.append(" ** NAME: \t"+ operInfo.getName());
675         retStr.append(" DESCR: \t"+ operInfo.getDescription());
676         retStr.append(" PARAM: \t"+
677                   operInfo.getSignature().length +
678                   " parameter(s)");
679         retStr.append(" DESCRIPTOR: " +
680                   operInfo.getDescriptor().toString());
681         }
682     } else {
683         retStr.append(" ** No operations ** ");
684     }
685
686     retStr.append("\nNOTIFICATIONS");
687
688     MBeanNotificationInfo JavaDoc[] notifInfo = info.getNotifications();
689     if ((notifInfo != null) && (notifInfo.length>0)) {
690         for (int i=0; i<notifInfo.length; i++) {
691         final ModelMBeanNotificationInfo JavaDoc nInfo =
692             (ModelMBeanNotificationInfo JavaDoc)notifInfo[i];
693         retStr.append(" ** NAME: \t"+ nInfo.getName());
694         retStr.append(" DESCR: \t"+ nInfo.getDescription());
695         retStr.append(" DESCRIPTOR: " +
696                   nInfo.getDescriptor().toString());
697         }
698     } else {
699         retStr.append(" ** No notifications **");
700     }
701
702     retStr.append(" ** ModelMBean: End of MBeanInfo ** ");
703
704     return retStr.toString();
705     }
706
707     private void echo(String JavaDoc txt) {
708     trace("echo(txt)",txt);
709     }
710
711
712     /**
713      * Invokes a method on or through a RequiredModelMBean and returns
714      * the result of the method execution.
715      * <P>
716      * If the given method to be invoked, together with the provided
717      * signature, matches one of RequiredModelMbean
718      * accessible methods, this one will be call. Otherwise the call to
719      * the given method will be tried on the managed resource.
720      * <P>
721      * The last value returned by an operation may be cached in
722      * the operation's descriptor which
723      * is in the ModelMBeanOperationInfo's descriptor.
724      * The valid value will be in the 'value' field if there is one.
725      * If the 'currencyTimeLimit' field in the descriptor is:
726      * <UL>
727      * <LI><b>&lt;0</b> Then the value is not cached and is never valid.
728      * The operation method is invoked.
729      * The 'value' and 'lastUpdatedTimeStamp' fields are cleared.</LI>
730      * <LI><b>=0</b> Then the value is always cached and always valid.
731      * The 'value' field is returned. If there is no 'value' field
732      * then the operation method is invoked for the attribute.
733      * The 'lastUpdatedTimeStamp' field and `value' fields are set to
734      * the operation's return value and the current time stamp.</LI>
735      * <LI><b>&gt;0</b> Represents the number of seconds that the 'value'
736      * field is valid.
737      * The 'value' field is no longer valid when
738      * 'lastUpdatedTimeStamp' + 'currencyTimeLimit' &gt; Now.
739      * <UL>
740      * <LI>When 'value' is valid, 'value' is returned.</LI>
741      * <LI>When 'value' is no longer valid then the operation
742      * method is invoked. The 'lastUpdatedTimeStamp' field
743      * and `value' fields are updated.</lI>
744      * </UL>
745      * </LI>
746      * </UL>
747      *
748      * <p><b>Note:</b> because of inconsistencies in previous versions of
749      * this specification, it is recommended not to use negative or zero
750      * values for <code>currencyTimeLimit</code>. To indicate that a
751      * cached value is never valid, omit the
752      * <code>currencyTimeLimit</code> field. To indicate that it is
753      * always valid, use a very large number for this field.</p>
754      *
755      * @param opName The name of the method to be invoked. The
756      * name can be the fully qualified method name including the
757      * classname, or just the method name if the classname is
758      * defined in the 'class' field of the operation descriptor.
759      * @param opArgs An array containing the parameters to be set
760      * when the operation is invoked
761      * @param sig An array containing the signature of the
762      * operation. The class objects will be loaded using the same
763      * class loader as the one used for loading the MBean on which
764      * the operation was invoked.
765      *
766      * @return The object returned by the method, which represents the
767      * result of invoking the method on the specified managed resource.
768      *
769      * @exception MBeanException Wraps one of the following Exceptions:
770      * <UL>
771      * <LI> An Exception thrown by the managed object's invoked method.</LI>
772      * <LI> {@link ServiceNotFoundException}: No ModelMBeanOperationInfo or
773      * no descriptor defined for the specified operation or the managed
774      * resource is null.</LI>
775      * <LI> {@link InvalidTargetObjectTypeException}: The 'targetType'
776      * field value is not 'objectReference'.</LI>
777      * </UL>
778      * @exception ReflectionException Wraps an {@link java.lang.Exception}
779      * thrown while trying to invoke the method.
780      * @exception RuntimeOperationsException Wraps an
781      * {@link IllegalArgumentException} Method name is null.
782      *
783      **/

784     /*
785       The requirement to be able to invoke methods on the
786       RequiredModelMBean class itself makes this method considerably
787       more complicated than it might otherwise be. Note that, unlike
788       earlier versions, we do not allow you to invoke such methods if
789       they are not explicitly mentioned in the ModelMBeanInfo. Doing
790       so was potentially a security problem, and certainly very
791       surprising.
792
793       We do not look for the method in the RequiredModelMBean class
794       itself if:
795       (a) there is a "targetObject" field in the Descriptor for the
796       operation; or
797       (b) there is a "class" field in the Descriptor for the operation
798       and the named class is not RequiredModelMBean or one of its
799       superinterfaces; or
800       (c) the name of the operation is not the name of a method in
801       RequiredModelMBean (this is just an optimization).
802
803       In cases (a) and (b), if you have gone to the trouble of adding
804       those fields specifically for this operation then presumably you
805       do not want RequiredModelMBean's methods to be called.
806
807       We have to pay attention to class loading issues. If the
808       "class" field is present, the named class has to be resolved
809       relative to RequiredModelMBean's class loader to test the
810       condition (b) above, and relative to the managed resource's
811       class loader to ensure that the managed resource is in fact of
812       the named class (or a subclass). The class names in the sig
813       array likewise have to be resolved, first against
814       RequiredModelMBean's class loader, then against the managed
815       resource's class loader. There is no point in using any other
816       loader because when we call Method.invoke we must call it on
817       a Method that is implemented by the target object.
818      */

819     public Object JavaDoc invoke(String JavaDoc opName, Object JavaDoc[] opArgs, String JavaDoc[] sig)
820         throws MBeanException JavaDoc, ReflectionException JavaDoc {
821     final boolean tracing = tracing();
822
823     if (tracing)
824         trace("invoke(String, Object[], String[])","Entry");
825
826     if (opName == null) {
827         final RuntimeException JavaDoc x =
828         new IllegalArgumentException JavaDoc("Method name must not be null");
829         throw new RuntimeOperationsException JavaDoc(x,
830                       "An exception occured while trying to " +
831               "invoke a method on a RequiredModelMBean");
832     }
833
834     String JavaDoc opClassName = null;
835     String JavaDoc opMethodName;
836
837     // Parse for class name and method
838
int opSplitter = opName.lastIndexOf(".");
839     if (opSplitter > 0) {
840         opClassName = opName.substring(0,opSplitter);
841         opMethodName = opName.substring(opSplitter+1);
842     } else
843         opMethodName = opName;
844
845     /* Ignore anything after a left paren. We keep this for
846        compatibility but it isn't specified. */

847     opSplitter = opMethodName.indexOf("(");
848     if (opSplitter > 0)
849         opMethodName = opMethodName.substring(0,opSplitter);
850     
851     if (tracing)
852         trace("invoke(String, Object[], String[])",
853           "Finding operation " + opName + " as " + opMethodName);
854
855     ModelMBeanOperationInfo JavaDoc opInfo =
856         modelMBeanInfo.getOperation(opMethodName);
857     if (opInfo == null) {
858         final String JavaDoc msg =
859         "Operation " + opName + " not in ModelMBeanInfo";
860         throw new MBeanException JavaDoc(new ServiceNotFoundException JavaDoc(msg), msg);
861     }
862
863     final Descriptor JavaDoc opDescr = opInfo.getDescriptor();
864     if (opDescr == null) {
865         final String JavaDoc msg = "Operation descriptor null";
866         throw new MBeanException JavaDoc(new ServiceNotFoundException JavaDoc(msg), msg);
867     }
868
869     final Object JavaDoc cached = resolveForCacheValue(opDescr);
870     if (cached != null) {
871         if (tracing)
872         trace("invoke(String, Object[], String[])",
873               "Returning cached value");
874         return cached;
875     }
876
877         if (opClassName == null)
878         opClassName = (String JavaDoc) opDescr.getFieldValue("class");
879     // may still be null now
880

881     opMethodName = (String JavaDoc) opDescr.getFieldValue("name");
882     if (opMethodName == null) {
883         final String JavaDoc msg =
884         "Method descriptor must include `name' field";
885         throw new MBeanException JavaDoc(new ServiceNotFoundException JavaDoc(msg), msg);
886     }
887
888     final String JavaDoc targetTypeField = (String JavaDoc)
889         opDescr.getFieldValue("targetType");
890     if (targetTypeField != null
891         && !targetTypeField.equalsIgnoreCase("objectReference")) {
892         final String JavaDoc msg =
893         "Target type must be objectReference: " + targetTypeField;
894         throw new MBeanException JavaDoc(new InvalidTargetObjectTypeException JavaDoc(msg),
895                      msg);
896     }
897
898     final Object JavaDoc targetObjectField = opDescr.getFieldValue("targetObject");
899     if (tracing && targetObjectField != null)
900         trace("invoke(String, Object[], String[])",
901           "Found target object in descriptor");
902
903     /* Now look for the method, either in RequiredModelMBean itself
904        or in the target object. Set "method" and "targetObject"
905        appropriately. */

906     Method JavaDoc method;
907     Object JavaDoc targetObject;
908
909     method = findRMMBMethod(opMethodName, targetObjectField,
910                 opClassName, sig);
911
912     if (method != null)
913         targetObject = this;
914     else {
915         if (tracing)
916         trace("invoke(String, Object[], String[])",
917               "looking for method in managedResource class");
918         if (targetObjectField != null)
919         targetObject = targetObjectField;
920         else {
921         targetObject = managedResource;
922         if (targetObject == null) {
923             final String JavaDoc msg =
924             "managedResource for invoke " + opName +
925             " is null";
926             Exception JavaDoc snfe = new ServiceNotFoundException JavaDoc(msg);
927             throw new MBeanException JavaDoc(snfe);
928         }
929         }
930
931         final Class JavaDoc targetClass;
932
933         if (opClassName != null) {
934         try {
935             final ClassLoader JavaDoc targetClassLoader =
936             targetObject.getClass().getClassLoader();
937             targetClass = Class.forName(opClassName, false,
938                         targetClassLoader);
939         } catch (ClassNotFoundException JavaDoc e) {
940             final String JavaDoc msg =
941             "class for invoke " + opName + " not found";
942             throw new ReflectionException JavaDoc(e, msg);
943         }
944         } else
945         targetClass = targetObject.getClass();
946
947         method = resolveMethod(targetClass, opMethodName, sig);
948     }
949
950     if (tracing)
951         trace("invoke(String, Object[], String[])",
952           "found " + opMethodName + ", now invoking");
953
954     final Object JavaDoc result =
955         invokeMethod(opName, method, targetObject, opArgs);
956
957     if (tracing)
958         trace("invoke(String, Object[], String[])",
959           "successfully invoked method");
960
961     if (result != null)
962         cacheResult(opInfo, opDescr, result);
963
964     return result;
965     }
966
967     private static Method JavaDoc resolveMethod(Class JavaDoc targetClass,
968                     String JavaDoc opMethodName,
969                     String JavaDoc[] sig)
970         throws ReflectionException JavaDoc {
971     final boolean tracing = tracing();
972
973     if (tracing)
974         trace("resolveMethod",
975           "resolving " + targetClass + "." + opMethodName);
976
977     final Class JavaDoc[] argClasses;
978
979     if (sig == null)
980         argClasses = null;
981     else {
982         final ClassLoader JavaDoc targetClassLoader = targetClass.getClassLoader();
983         argClasses = new Class JavaDoc[sig.length];
984         for (int i = 0; i < sig.length; i++) {
985         if (tracing)
986             trace("resolveMethod", "resolve type " + sig[i]);
987         argClasses[i] = (Class JavaDoc) primitiveClassMap.get(sig[i]);
988         if (argClasses[i] == null) {
989             try {
990             argClasses[i] =
991                 Class.forName(sig[i], false, targetClassLoader);
992             } catch (ClassNotFoundException JavaDoc e) {
993             if (tracing)
994                 trace("resolveMethod", "class not found");
995             final String JavaDoc msg = "Parameter class not found";
996             throw new ReflectionException JavaDoc(e, msg);
997             }
998         }
999         }
1000    }
1001
1002    try {
1003        return targetClass.getMethod(opMethodName, argClasses);
1004    } catch (NoSuchMethodException JavaDoc e) {
1005        final String JavaDoc msg =
1006        "Target method not found: " + targetClass.getName() + "." +
1007        opMethodName;
1008        throw new ReflectionException JavaDoc(e, msg);
1009    }
1010    }
1011
1012    /* Map e.g. "int" to int.class. Goodness knows how many time this
1013       particular wheel has been reinvented. */

1014    private static final Class JavaDoc[] primitiveClasses = {
1015    int.class, long.class, boolean.class, double.class,
1016    float.class, short.class, byte.class, char.class,
1017    };
1018    private static final Map JavaDoc/*<String,Class>*/ primitiveClassMap =
1019    new HashMap JavaDoc();
1020    static {
1021    for (int i = 0; i < primitiveClasses.length; i++) {
1022        final Class JavaDoc c = primitiveClasses[i];
1023        primitiveClassMap.put(c.getName(), c);
1024    }
1025    }
1026
1027    /* Find a method in RequiredModelMBean as determined by the given
1028       parameters. Return null if there is none, or if the parameters
1029       exclude using it. Called from invoke. */

1030    private static Method JavaDoc findRMMBMethod(String JavaDoc opMethodName,
1031                     Object JavaDoc targetObjectField,
1032                     String JavaDoc opClassName,
1033                     String JavaDoc[] sig) {
1034    if (tracing())
1035        trace("invoke(String, Object[], String[])",
1036          "looking for method in RequiredModelMBean class");
1037    if (!isRMMBMethodName(opMethodName))
1038        return null;
1039    if (targetObjectField != null)
1040        return null;
1041    final Class JavaDoc rmmbClass = RequiredModelMBean JavaDoc.class;
1042    final Class JavaDoc targetClass;
1043    if (opClassName == null)
1044        targetClass = rmmbClass;
1045    else {
1046        try {
1047        final ClassLoader JavaDoc targetClassLoader =
1048            rmmbClass.getClassLoader();
1049        targetClass = Class.forName(opClassName, false,
1050                        targetClassLoader);
1051        if (!rmmbClass.isAssignableFrom(targetClass))
1052            return null;
1053        } catch (ClassNotFoundException JavaDoc e) {
1054        return null;
1055        }
1056    }
1057    try {
1058        return resolveMethod(targetClass, opMethodName, sig);
1059    } catch (ReflectionException JavaDoc e) {
1060        return null;
1061    }
1062    }
1063
1064    /*
1065     * Invoke the given method, and throw the somewhat unpredictable
1066     * appropriate exception if the method itself gets an exception.
1067     */

1068    private Object JavaDoc invokeMethod(String JavaDoc opName, Method JavaDoc method,
1069                Object JavaDoc targetObject, Object JavaDoc[] opArgs)
1070        throws MBeanException JavaDoc, ReflectionException JavaDoc {
1071    try {
1072            ReflectUtil.checkPackageAccess(method.getDeclaringClass());
1073        return MethodUtil.invoke(method, targetObject, opArgs);
1074    } catch (RuntimeErrorException JavaDoc ree) {
1075        throw new RuntimeOperationsException JavaDoc(ree,
1076              "RuntimeException occured in RequiredModelMBean "+
1077              "while trying to invoke operation " + opName);
1078    } catch (RuntimeException JavaDoc re) {
1079        throw new RuntimeOperationsException JavaDoc(re,
1080              "RuntimeException occured in RequiredModelMBean "+
1081              "while trying to invoke operation " + opName);
1082    } catch (IllegalAccessException JavaDoc iae) {
1083        throw new ReflectionException JavaDoc(iae,
1084              "IllegalAccessException occured in " +
1085              "RequiredModelMBean while trying to " +
1086              "invoke operation " + opName);
1087    } catch (InvocationTargetException JavaDoc ite) {
1088        Throwable JavaDoc mmbTargEx = ite.getTargetException();
1089        if (mmbTargEx instanceof RuntimeException JavaDoc) {
1090        throw new MBeanException JavaDoc ((RuntimeException JavaDoc)mmbTargEx,
1091              "RuntimeException thrown in RequiredModelMBean "+
1092              "while trying to invoke operation " + opName);
1093        } else if (mmbTargEx instanceof Error JavaDoc) {
1094        throw new RuntimeErrorException JavaDoc((Error JavaDoc)mmbTargEx,
1095              "Error occured in RequiredModelMBean while trying "+
1096              "to invoke operation " + opName);
1097        } else if (mmbTargEx instanceof ReflectionException JavaDoc) {
1098        throw (ReflectionException JavaDoc) mmbTargEx;
1099        } else {
1100        throw new MBeanException JavaDoc ((Exception JavaDoc)mmbTargEx,
1101              "Exception thrown in RequiredModelMBean "+
1102              "while trying to invoke operation " + opName);
1103        }
1104    } catch (Error JavaDoc err) {
1105        throw new RuntimeErrorException JavaDoc(err,
1106          "Error occured in RequiredModelMBean while trying "+
1107          "to invoke operation " + opName);
1108    } catch (Exception JavaDoc e) {
1109        throw new ReflectionException JavaDoc(e,
1110          "Exception occured in RequiredModelMBean while " +
1111          "trying to invoke operation " + opName);
1112    }
1113    }
1114
1115    /*
1116     * Cache the result of an operation in the descriptor, if that is
1117     * called for by the descriptor's configuration. Note that we
1118     * don't remember operation parameters when caching the result, so
1119     * this is unlikely to be useful if there are any.
1120     */

1121    private void cacheResult(ModelMBeanOperationInfo JavaDoc opInfo,
1122                 Descriptor JavaDoc opDescr, Object JavaDoc result)
1123        throws MBeanException JavaDoc {
1124
1125    Descriptor JavaDoc mmbDesc =
1126        modelMBeanInfo.getMBeanDescriptor();
1127
1128    Object JavaDoc objctl =
1129        opDescr.getFieldValue("currencyTimeLimit");
1130    String JavaDoc ctl;
1131    if (objctl != null) {
1132        ctl = objctl.toString();
1133    } else {
1134        ctl = null;
1135    }
1136    if ((ctl == null) && (mmbDesc != null)) {
1137        objctl =
1138        mmbDesc.getFieldValue("currencyTimeLimit");
1139        if (objctl != null) {
1140        ctl = objctl.toString();
1141        } else {
1142        ctl = null;
1143        }
1144    }
1145    if ((ctl != null) && !(ctl.equals("-1"))) {
1146        opDescr.setField("value", result);
1147        opDescr.setField("lastUpdatedTimeStamp",
1148          (new Long JavaDoc((new Date JavaDoc()).getTime())).toString());
1149
1150        modelMBeanInfo.setDescriptor(opDescr,
1151                     "operation");
1152        if (tracing()) {
1153        trace("invoke(String,Object[],Object[])",
1154              "new descriptor is " +
1155              opDescr.toString());
1156        }
1157    }
1158    }
1159
1160    /*
1161     * Determine whether the given name is the name of a public method
1162     * in this class. This is only an optimization: it prevents us
1163     * from trying to do argument type lookups and reflection on a
1164     * method that will obviously fail because it has the wrong name.
1165     *
1166     * The first time this method is called we do the reflection, and
1167     * every other time we reuse the remembered values.
1168     *
1169     * It's conceivable that the (possibly malicious) first caller
1170     * doesn't have the required permissions to do reflection, in
1171     * which case we don't touch anything so as not to interfere
1172     * with a later permissionful caller.
1173     */

1174    private static Set JavaDoc/*<String>*/ rmmbMethodNames;
1175    private static synchronized boolean isRMMBMethodName(String JavaDoc name) {
1176    if (rmmbMethodNames == null) {
1177        try {
1178        Set JavaDoc names = new HashSet JavaDoc();
1179        Method JavaDoc[] methods = RequiredModelMBean JavaDoc.class.getMethods();
1180        for (int i = 0; i < methods.length; i++)
1181            names.add(methods[i].getName());
1182        rmmbMethodNames = names;
1183        } catch (Exception JavaDoc e) {
1184        return true;
1185        // This is only an optimization so we'll go on to discover
1186
// whether the name really is an RMMB method.
1187
}
1188    }
1189    return rmmbMethodNames.contains(name);
1190    }
1191
1192    /**
1193     * Returns the value of a specific attribute defined for this
1194     * ModelMBean.
1195     * The last value returned by an attribute may be cached in the
1196     * attribute's descriptor.
1197     * The valid value will be in the 'value' field if there is one.
1198     * If the 'currencyTimeLimit' field in the descriptor is:
1199     * <UL>
1200     * <LI> <b>&lt;0</b> Then the value is not cached and is never valid.
1201     * The getter method is invoked for the attribute.
1202     * The 'value' and 'lastUpdatedTimeStamp' fields are cleared.</LI>
1203     * <LI> <b>=0</b> Then the value is always cached and always valid.
1204     * The 'value' field is returned. If there is no'value' field
1205     * then the getter method is invoked for the attribute.
1206     * The 'lastUpdatedTimeStamp' field and `value' fields are set
1207     * to the attribute's value and the current time stamp.</LI>
1208     * <LI> <b>&gt;0</b> Represents the number of seconds that the 'value'
1209     * field is valid.
1210     * The 'value' field is no longer valid when
1211     * 'lastUpdatedTimeStamp' + 'currencyTimeLimit' &gt; Now.
1212     * <UL>
1213     * <LI>When 'value' is valid, 'value' is returned.</LI>
1214     * <LI>When 'value' is no longer valid then the getter
1215     * method is invoked for the attribute.
1216     * The 'lastUpdatedTimeStamp' field and `value' fields
1217     * are updated.</LI>
1218     * </UL></LI>
1219     * </UL>
1220     *
1221     * <p><b>Note:</b> because of inconsistencies in previous versions of
1222     * this specification, it is recommended not to use negative or zero
1223     * values for <code>currencyTimeLimit</code>. To indicate that a
1224     * cached value is never valid, omit the
1225     * <code>currencyTimeLimit</code> field. To indicate that it is
1226     * always valid, use a very large number for this field.</p>
1227     *
1228     * <p>If the 'getMethod' field contains the name of a valid
1229     * operation descriptor, then the method described by the
1230     * operation descriptor is executed. The response from the
1231     * method is returned as the value of the attribute. If the
1232     * operation fails or the returned value is not of the same
1233     * type as the attribute, an exception will be thrown. If no
1234     * 'getMethod' field is defined then the default value of the
1235     * attribute is returned. In this implementation, in every
1236     * case where the getMethod needs to be called, because the
1237     * method is invoked through the standard "invoke" method and
1238     * thus needs operationInfo, an operation must be specified
1239     * for that getMethod so that the invocation works correctly.</p>
1240     *
1241     * @param attrName A String specifying the name of the
1242     * attribute to be retrieved. It must match the name of a
1243     * ModelMBeanAttributeInfo.
1244     *
1245     * @return The value of the retrieved attribute from the
1246     * descriptor 'value' field or from the invocation of the
1247     * operation in the 'getMethod' field of the descriptor.
1248     *
1249     * @exception AttributeNotFoundException The specified attribute is
1250     * not accessible in the MBean.
1251     * The following cases may result in an AttributeNotFoundException:
1252     * <UL>
1253     * <LI> No ModelMBeanInfo was found for the Model MBean.</LI>
1254     * <LI> No ModelMBeanAttributeInfo was found for the specified
1255     * attribute name.</LI>
1256     * <LI> The ModelMBeanAttributeInfo isReadable method returns
1257     * 'false'.</LI>
1258     * </UL>
1259     * @exception MBeanException Wraps one of the following Exceptions:
1260     * <UL>
1261     * <LI> {@link InvalidAttributeValueException}: A wrong value type
1262     * was received from the attribute's getter method or
1263     * no 'getMethod' field defined in the descriptor for
1264     * the attribute and no default value exists.</LI>
1265     * <LI> {@link ServiceNotFoundException}: No
1266     * ModelMBeanOperationInfo defined for the attribute's
1267     * getter method or no descriptor associated with the
1268     * ModelMBeanOperationInfo or the managed resource is
1269     * null.</LI>
1270     * <LI> {@link InvalidTargetObjectTypeException} The 'targetType'
1271     * field value is not 'objectReference'.</LI>
1272     * <LI> An Exception thrown by the managed object's getter.</LI>
1273     * </UL>
1274     * @exception ReflectionException Wraps an {@link java.lang.Exception}
1275     * thrown while trying to invoke the getter.
1276     * @exception RuntimeOperationsException Wraps an
1277     * {@link IllegalArgumentException}: The attribute name in
1278     * parameter is null.
1279     *
1280     * @see #setAttribute(javax.management.Attribute)
1281     **/

1282    public Object JavaDoc getAttribute(String JavaDoc attrName)
1283    throws AttributeNotFoundException JavaDoc, MBeanException JavaDoc,
1284           ReflectionException JavaDoc {
1285    if (attrName == null)
1286        throw new RuntimeOperationsException JavaDoc(new
1287        IllegalArgumentException JavaDoc("attributeName must not be null"),
1288        "Exception occured trying to get attribute of a " +
1289            "RequiredModelMBean");
1290
1291    if (tracing())
1292        trace("getAttribute(String)","Entry with" + attrName);
1293
1294    /* Check attributeDescriptor for getMethod */
1295    ModelMBeanAttributeInfo JavaDoc attrInfo=null;
1296    Descriptor JavaDoc attrDescr=null;
1297    Object JavaDoc response = null;
1298
1299    try {
1300        if (modelMBeanInfo == null)
1301        throw new AttributeNotFoundException JavaDoc(
1302                      "getAttribute failed: ModelMBeanInfo not found for "+
1303              attrName);
1304
1305        attrInfo = modelMBeanInfo.getAttribute(attrName);
1306        Descriptor JavaDoc mmbDesc = modelMBeanInfo.getMBeanDescriptor();
1307
1308        if (attrInfo == null)
1309        throw new AttributeNotFoundException JavaDoc("getAttribute failed:"+
1310              " ModelMBeanAttributeInfo not found for " + attrName);
1311    
1312        attrDescr = attrInfo.getDescriptor();
1313        if (attrDescr != null) {
1314        if (!attrInfo.isReadable())
1315            throw new AttributeNotFoundException JavaDoc(
1316              "getAttribute failed: " + attrName +
1317              " is not readable ");
1318        
1319        response = resolveForCacheValue(attrDescr);
1320
1321        /* return current cached value */
1322        if (tracing())
1323            trace("getAttribute(String)","*** cached value is " +
1324              response);
1325
1326        if (response == null) {
1327            /* no cached value, run getMethod */
1328            if (tracing())
1329            trace("getAttribute(String)",
1330                  "**** cached value is null" +
1331                  " - " + "getting getMethod");
1332            String JavaDoc attrGetMethod =
1333            (String JavaDoc)(attrDescr.getFieldValue("getMethod"));
1334
1335            if (attrGetMethod != null) {
1336            /* run method from operations descriptor */
1337            if (tracing())
1338                trace("getAttribute(String)",
1339                  "invoking a getMethod for " + attrName);
1340
1341            Object JavaDoc getResponse =
1342                invoke(attrGetMethod, new Object JavaDoc[] {},
1343                   new String JavaDoc[] {});
1344
1345            if (getResponse != null) {
1346                // error/validity check return value here
1347
if (tracing())
1348                trace("getAttribute(String)",
1349                 "got a non-null response from getMethod\n");
1350
1351                response = getResponse;
1352
1353                // change cached value in attribute descriptor
1354
Object JavaDoc objctl =
1355                attrDescr.getFieldValue("currencyTimeLimit");
1356
1357                String JavaDoc ctl;
1358                if (objctl != null) ctl = objctl.toString();
1359                else ctl = null;
1360            
1361                if ((ctl == null) && (mmbDesc != null)) {
1362                objctl = mmbDesc.
1363                    getFieldValue("currencyTimeLimit");
1364                if (objctl != null) ctl = objctl.toString();
1365                else ctl = null;
1366                }
1367
1368                if ((ctl != null) && !(ctl.equals("-1"))) {
1369                if (tracing())
1370                    trace("getAttribute(String)",
1371                      "setting cached value and "+
1372                      "lastUpdatedTime in descriptor");
1373
1374                attrDescr.setField("value", response);
1375                final String JavaDoc stamp =
1376                    (new Long JavaDoc((new Date JavaDoc()).getTime())).
1377                    toString();
1378                attrDescr.setField("lastUpdatedTimeStamp",
1379                           stamp);
1380                attrInfo.setDescriptor(attrDescr);
1381                modelMBeanInfo.setDescriptor(attrDescr,
1382                                 "attribute");
1383                if (tracing()) {
1384                    trace("getAttribute(String)",
1385                      "new descriptor is " +
1386                      attrDescr.toString());
1387                    trace("getAttribute(String)","local: "+
1388                      "AttributeInfo descriptor is "+
1389                      attrInfo.getDescriptor().
1390                      toString());
1391                    final String JavaDoc attStr = modelMBeanInfo.
1392                    getDescriptor(attrName,"attribute").
1393                    toString();
1394                    trace("getAttribute(String)",
1395                      "modelMBeanInfo: " +
1396                      "AttributeInfo descriptor is " +
1397                      attStr);
1398                }
1399                }
1400            } else {
1401                // response was invalid or really returned null
1402
if (tracing())
1403                trace("getAttribute(String)",
1404                     "got a null response from getMethod\n");
1405                response = null;
1406            }
1407            } else {
1408            // not getMethod so return descriptor (default) value
1409
String JavaDoc qualifier="";
1410            response = attrDescr.getFieldValue("value");
1411            if (response == null) {
1412                qualifier="default ";
1413                response = attrDescr.getFieldValue("default");
1414            }
1415            if (tracing())
1416                trace("getAttribute(String)",
1417                  "could not find getMethod for " +
1418                  attrName + ", returning descriptor " +
1419                  qualifier + "value");
1420            // !! cast response to right class
1421
}
1422        }
1423
1424        // make sure response class matches type field
1425
String JavaDoc respType = attrInfo.getType();
1426        if (response != null) {
1427            String JavaDoc responseClass = response.getClass().getName();
1428            if (!respType.equals(responseClass)) {
1429            boolean wrongType = false;
1430                        boolean primitiveType = false;
1431                        boolean correspondingTypes = false;
1432                        for (int i = 0; i < primitiveTypes.length; i++) {
1433                            if (respType.equals(primitiveTypes[i])) {
1434                                primitiveType = true;
1435                                if (responseClass.equals(primitiveWrappers[i]))
1436                                    correspondingTypes = true;
1437                                break;
1438                            }
1439                        }
1440            if (primitiveType) {
1441                // inequality may come from primitive/wrapper class
1442
if (!correspondingTypes)
1443                wrongType = true;
1444            } else {
1445                // inequality may come from type subclassing
1446
boolean subtype;
1447                try {
1448                ClassLoader JavaDoc cl =
1449                    response.getClass().getClassLoader();
1450                Class JavaDoc c = Class.forName(respType, true, cl);
1451                subtype = c.isInstance(response);
1452                } catch (Exception JavaDoc e) {
1453                subtype = false;
1454                if (tracing())
1455                    traceX("getAttribute(String)", e);
1456                }
1457                if (!subtype)
1458                wrongType = true;
1459            }
1460            if (wrongType) {
1461                if (tracing())
1462                trace("getAttribute(String)",
1463                      "Wrong response type '" + respType + "'");
1464                // throw exception, didn't get
1465
// back right attribute type
1466
throw new MBeanException JavaDoc(
1467                  new InvalidAttributeValueException JavaDoc(
1468                    "Wrong value type received for get attribute"),
1469                  "An exception occurred while trying to get an " +
1470                  "attribute value through a RequiredModelMBean");
1471            }
1472                    }
1473        }
1474        } else {
1475        if (tracing())
1476            trace("getAttribute(String)","getMethod failed " +
1477              attrName + " not in attributeDescriptor\n");
1478        throw new MBeanException JavaDoc(new
1479            InvalidAttributeValueException JavaDoc(
1480            "Unable to resolve attribute value, " +
1481            "no getMethod defined in descriptor for attribute"),
1482            "An exception occured while trying to get an "+
1483            "attribute value through a RequiredModelMBean");
1484        }
1485
1486    } catch (MBeanException JavaDoc mbe) {
1487        throw mbe;
1488    } catch (AttributeNotFoundException JavaDoc t) {
1489        throw t;
1490    } catch (Exception JavaDoc e) {
1491        if (tracing())
1492        trace("getAttribute(String)","getMethod failed with " +
1493              e.getMessage() + " exception type " +
1494              (e.getClass()).toString());
1495        throw new MBeanException JavaDoc(e,"An exception occured while trying "+
1496              "to get an attribute value: " + e.getMessage());
1497    }
1498        
1499    if (tracing())
1500        trace("getAttribute(String)","Exit");
1501
1502    return response;
1503    }
1504
1505    /**
1506     * Returns the values of several attributes in the ModelMBean.
1507     * Executes a getAttribute for each attribute name in the
1508     * attrNames array passed in.
1509     *
1510     * @param attrNames A String array of names of the attributes
1511     * to be retrieved.
1512     *
1513     * @return The array of the retrieved attributes.
1514     *
1515     * @exception RuntimeOperationsException Wraps an
1516     * {@link IllegalArgumentException}: The object name in parameter is
1517     * null or attributes in parameter is null.
1518     *
1519     * @see #setAttributes(javax.management.AttributeList)
1520     */

1521    public AttributeList JavaDoc getAttributes(String JavaDoc[] attrNames) {
1522    if (tracing())
1523        trace("getAttributes(String[])","Entry");
1524
1525    AttributeList JavaDoc responseList = null;
1526    if (attrNames == null)
1527        throw new RuntimeOperationsException JavaDoc(new
1528        IllegalArgumentException JavaDoc("attributeNames must not be null"),
1529        "Exception occured trying to get attributes of a "+
1530        "RequiredModelMBean");
1531
1532    responseList = new AttributeList JavaDoc();
1533    for (int i = 0; i < attrNames.length; i++) {
1534        try {
1535        responseList.add(new Attribute JavaDoc(attrNames[i],
1536                     getAttribute(attrNames[i])));
1537        } catch (Exception JavaDoc e) {
1538        // eat exceptions because interface doesn't have an
1539
// exception on it
1540
error("getAttributes(String[])","Failed to get \"" +
1541              attrNames[i] + "\": " + e);
1542        traceX("getAttributes(String[])",e);
1543        }
1544    }
1545    
1546    if (tracing())
1547        trace("getAttributes(String[])","Exit");
1548        
1549    return responseList;
1550    }
1551
1552    /**
1553     * Sets the value of a specific attribute of a named ModelMBean.
1554     *
1555     * If the 'setMethod' field of the attribute's descriptor
1556     * contains the name of a valid operation descriptor, then the
1557     * method described by the operation descriptor is executed.
1558     * In this implementation, the operation descriptor must be specified
1559     * correctly and assigned to the modelMBeanInfo so that the 'setMethod'
1560     * works correctly.
1561     * The response from the method is set as the value of the attribute
1562     * in the descriptor.
1563     *
1564     * <p>If currencyTimeLimit is &gt; 0, then the new value for the
1565     * attribute is cached in the attribute descriptor's
1566     * 'value' field and the 'lastUpdatedTimeStamp' field is set to
1567     * the current time stamp.
1568     *
1569     * <p>If the persist field of the attribute's descriptor is not null
1570     * then Persistence policy from the attribute descriptor is used to
1571     * guide storing the attribute in a persistent store.
1572     * <br>Store the MBean if 'persistPolicy' field is:
1573     * <UL>
1574     * <Li> != "never"</Li>
1575     * <Li> = "always"</Li>
1576     * <Li> = "onUpdate"</Li>
1577     * <Li> = "onTimer" and now &gt; 'lastPersistTime' + 'persistPeriod'</Li>
1578     * <Li> = "NoMoreOftenThan" and now &gt; 'lastPersistTime' +
1579     * 'persistPeriod'</Li>
1580     * </UL>
1581     * Do not store the MBean if 'persistPolicy' field is:
1582     * <UL>
1583     * <Li> = "never"</Li>
1584     * <Li> = "onTimer" && now &lt; 'lastPersistTime' + 'persistPeriod'</Li>
1585     * <Li> = "NoMoreOftenThan" and now &lt; 'lastPersistTime' +
1586     * 'persistPeriod'</Li>
1587     * </UL>
1588     *
1589     * <p>The ModelMBeanInfo of the Model MBean is stored in a file.
1590     *
1591     * @param attribute The Attribute instance containing the name of
1592     * the attribute to be set and the value it is to be set to.
1593     *
1594     *
1595     * @exception AttributeNotFoundException The specified attribute is
1596     * not accessible in the MBean.
1597     * <br>The following cases may result in an AttributeNotFoundException:
1598     * <UL>
1599     * <LI> No ModelMBeanAttributeInfo is found for the specified
1600     * attribute.</LI>
1601     * <LI> The ModelMBeanAttributeInfo's isWritable method returns
1602     * 'false'.</LI>
1603     * </UL>
1604     * @exception InvalidAttributeValueException No descriptor is defined
1605     * for the specified attribute.
1606     * @exception MBeanException Wraps one of the following Exceptions:
1607     * <UL>
1608     * <LI> An Exception thrown by the managed object's setter.</LI>
1609     * <LI> A {@link ServiceNotFoundException} if no `setMethod` field
1610     * is defined in the descriptor for the attribute or the
1611     * managed resource is null.</LI>
1612     * <LI> {@link InvalidTargetObjectTypeException} The 'targetType'
1613     * field value is not 'objectReference'.</LI>
1614     * <LI> An Exception thrown by the managed object's getter.</LI>
1615     * </UL>
1616     * @exception ReflectionException Wraps an {@link java.lang.Exception}
1617     * thrown while trying to invoke the setter.
1618     * @exception RuntimeOperationsException Wraps an
1619     * {@link IllegalArgumentException}: The attribute in parameter is
1620     * null.
1621     *
1622     * @see #getAttribute(java.lang.String)
1623     **/

1624    public void setAttribute(Attribute JavaDoc attribute)
1625    throws AttributeNotFoundException JavaDoc, InvalidAttributeValueException JavaDoc,
1626           MBeanException JavaDoc, ReflectionException JavaDoc {
1627    
1628    if (tracing())
1629        trace("setAttribute()","Entry");
1630
1631    if (attribute == null)
1632        throw new RuntimeOperationsException JavaDoc(new
1633        IllegalArgumentException JavaDoc("attribute must not be null"),
1634        "Exception occured trying to set an attribute of a "+
1635        "RequiredModelMBean");
1636    
1637    /* run setMethod if there is one */
1638    /* return cached value if its current */
1639    /* set cached value in descriptor and set date/time */
1640    /* send attribute change Notification */
1641    /* check persistence policy and persist if need be */
1642    String JavaDoc attrName = attribute.getName();
1643    Object JavaDoc attrValue = attribute.getValue();
1644    boolean updateDescriptor = false;
1645
1646    ModelMBeanAttributeInfo JavaDoc attrInfo =
1647        modelMBeanInfo.getAttribute(attrName);
1648
1649    if (attrInfo == null)
1650        throw new AttributeNotFoundException JavaDoc("setAttribute failed: " +
1651                           attrName + " is not found ");
1652
1653    Descriptor JavaDoc mmbDesc = modelMBeanInfo.getMBeanDescriptor();
1654    Descriptor JavaDoc attrDescr = attrInfo.getDescriptor();
1655
1656    if (attrDescr != null) {
1657        if (!attrInfo.isWritable())
1658        throw new AttributeNotFoundException JavaDoc("setAttribute failed: "
1659                      + attrName + " is not writable ");
1660
1661        Object JavaDoc setResponse = null;
1662        String JavaDoc attrSetMethod = (String JavaDoc)
1663        (attrDescr.getFieldValue("setMethod"));
1664        String JavaDoc attrType = (String JavaDoc)(attrInfo.getType());
1665        Object JavaDoc currValue = "Unknown";
1666
1667        try {
1668        currValue = this.getAttribute(attrName);
1669        } catch (Throwable JavaDoc t) {
1670        // OK: Default "Unknown" value used for unknown attribute
1671
}
1672
1673        Attribute JavaDoc oldAttr = new Attribute JavaDoc(attrName, currValue);
1674                    
1675        /* run method from operations descriptor */
1676        if (attrSetMethod == null) {
1677        if (attrValue != null) {
1678            try {
1679            final Class JavaDoc clazz = loadClass(attrType);
1680            if (! clazz.isInstance(attrValue)) throw new
1681                InvalidAttributeValueException JavaDoc(clazz.getName() +
1682                               " expected, " +
1683                        attrValue.getClass().getName() +
1684                               " received.");
1685            } catch (ClassNotFoundException JavaDoc x) {
1686            error("setAttribute","Class " + attrType +
1687                  " for attribute " + attrName + " not found: " +
1688                  x);
1689            debug("setAttribute",x);
1690            }
1691        }
1692        updateDescriptor = true;
1693        } else {
1694        setResponse = invoke(attrSetMethod,
1695                 (new Object JavaDoc[] {attrValue}),
1696                 (new String JavaDoc[] {attrType}) );
1697        }
1698        
1699        /* change cached value */
1700        Object JavaDoc objctl = attrDescr.getFieldValue("currencyTimeLimit");
1701        String JavaDoc ctl;
1702        if (objctl != null) ctl = objctl.toString();
1703        else ctl = null;
1704                    
1705        if ((ctl == null) && (mmbDesc != null)) {
1706        objctl = mmbDesc.getFieldValue("currencyTimeLimit");
1707        if (objctl != null) ctl = objctl.toString();
1708        else ctl = null;
1709        }
1710        
1711        final boolean updateCache = ((ctl != null) && !(ctl.equals("-1")));
1712        if (updateCache || updateDescriptor) {
1713        if (tracing())
1714            trace("setAttribute()","setting cached value of " +
1715              attrName + " to " + attrValue);
1716
1717        attrDescr.setField("value", attrValue);
1718
1719        if (updateCache) {
1720            final String JavaDoc currtime =
1721            (new Long JavaDoc((new Date JavaDoc()).getTime())).toString();
1722
1723        attrDescr.setField("lastUpdatedTimeStamp", currtime);
1724        }
1725
1726        attrInfo.setDescriptor(attrDescr);
1727            
1728        modelMBeanInfo.setDescriptor(attrDescr,"attribute");
1729        if (tracing()) {
1730            trace("setAttribute()","new descriptor is " +
1731              attrDescr.toString());
1732            trace("setAttribute()","AttributeInfo descriptor is " +
1733              attrInfo.getDescriptor().toString());
1734            trace("setAttribute()","AttributeInfo descriptor is " +
1735              modelMBeanInfo.getDescriptor(attrName,"attribute")
1736              .toString());
1737        }
1738            
1739        }
1740
1741        if (tracing())
1742        trace("setAttribute()","sending sendAttributeNotification");
1743        
1744        sendAttributeChangeNotification(oldAttr,attribute);
1745        
1746    } else { // if descriptor ... else no descriptor
1747

1748        if (tracing())
1749        trace("setAttribute(String)","setMethod failed "+attrName+
1750              " not in attributeDescriptor\n");
1751
1752        throw new InvalidAttributeValueException JavaDoc(
1753                      "Unable to resolve attribute value, "+
1754              "no defined in descriptor for attribute");
1755    } // else no descriptor
1756

1757    if (tracing())
1758        trace("setAttribute(Attribute)","Exit");
1759
1760    }
1761
1762    /**
1763     * Sets the values of an array of attributes of this ModelMBean.
1764     * Executes the setAttribute() method for each attribute in the list.
1765     *
1766     * @param attributes A list of attributes: The identification of the
1767     * attributes to be set and the values they are to be set to.
1768     *
1769     * @return The array of attributes that were set, with their new
1770     * values in Attribute instances.
1771     *
1772     * @exception RuntimeOperationsException Wraps an
1773     * {@link IllegalArgumentException}: The object name in parameter
1774     * is null or attributes in parameter is null.
1775     *
1776     * @see #getAttributes
1777     **/

1778    public AttributeList JavaDoc setAttributes(AttributeList JavaDoc attributes) {
1779
1780    if (tracing())
1781        trace("setAttributes(AttributeList)","Entry");
1782
1783    if (attributes == null)
1784        throw new RuntimeOperationsException JavaDoc(new
1785        IllegalArgumentException JavaDoc("attributes must not be null"),
1786        "Exception occured trying to set attributes of a "+
1787        "RequiredModelMBean");
1788
1789    final AttributeList JavaDoc responseList = new AttributeList JavaDoc();
1790
1791    // Go through the list of attributes
1792
for (Iterator JavaDoc i = attributes.iterator(); i.hasNext();) {
1793        final Attribute JavaDoc attr = (Attribute JavaDoc) i.next();
1794        try {
1795        setAttribute(attr);
1796        responseList.add(attr);
1797        } catch (Exception JavaDoc excep) {
1798        responseList.remove(attr);
1799        }
1800    }
1801
1802    return responseList;
1803    }
1804
1805
1806
1807    private ModelMBeanInfo JavaDoc createDefaultModelMBeanInfo() {
1808    return(new ModelMBeanInfoSupport JavaDoc((this.getClass().getName()),
1809           "Default ModelMBean", null, null, null, null));
1810    }
1811
1812    /*************************************/
1813    /* NotificationBroadcaster Interface */
1814    /*************************************/
1815
1816
1817    private synchronized void writeToLog(String JavaDoc logFileName,
1818                     String JavaDoc logEntry) throws Exception JavaDoc {
1819    
1820    PrintStream JavaDoc logOut = null;
1821    FileOutputStream JavaDoc fos = null;
1822    if (tracing()) trace("writeToLog()","Notification Logging to " +
1823                 logFileName + ": " + logEntry);
1824    if ((logFileName == null) || (logEntry == null)) {
1825        if (tracing()) trace("writeToLog()","Bad input parameters");
1826        return;
1827    }
1828
1829    try {
1830        fos = new FileOutputStream JavaDoc(logFileName, true);
1831        logOut = new PrintStream JavaDoc(fos);
1832        logOut.println(logEntry);
1833            logOut.close();
1834        if (tracing()) trace("writeToLog()",
1835                 "Successfully opened log " + logFileName);
1836    } catch (Exception JavaDoc e) {
1837        if (tracing())
1838        trace("writeToLog","Exception " + e.toString() +
1839              " trying to write to the Notification log file " +
1840              logFileName);
1841        throw e;
1842    }
1843    }
1844
1845
1846    /**
1847     * Registers an object which implements the NotificationListener
1848     * interface as a listener. This
1849     * object's 'handleNotification()' method will be invoked when any
1850     * notification is issued through or by the ModelMBean. This does
1851     * not include attributeChangeNotifications. They must be registered
1852     * for independently.
1853     *
1854     * @param listener The listener object which will handles
1855     * notifications emitted by the registered MBean.
1856     * @param filter The filter object. If null, no filtering will be
1857     * performed before handling notifications.
1858     * @param handback The context to be sent to the listener with
1859     * the notification when a notification is emitted.
1860     *
1861     * @exception IllegalArgumentException The listener cannot be null.
1862     *
1863     * @see #removeNotificationListener
1864     */

1865    public void addNotificationListener(NotificationListener JavaDoc listener,
1866                    NotificationFilter JavaDoc filter,
1867                    Object JavaDoc handback)
1868    throws java.lang.IllegalArgumentException JavaDoc {
1869    final String JavaDoc ftag = "addNotificationListener(NotificationListener, NotificationFilter, Object)";
1870    if (tracing())
1871        trace(ftag,"Entry");
1872        
1873    if (listener == null)
1874        throw new IllegalArgumentException JavaDoc(
1875                  "notification listener must not be null");
1876
1877    if (generalBroadcaster == null)
1878        generalBroadcaster = new NotificationBroadcasterSupport JavaDoc();
1879
1880    generalBroadcaster.addNotificationListener(listener, filter,
1881                           handback);
1882    if (tracing()) {
1883        trace(ftag,"NotificationListener added");
1884        trace(ftag,"Exit");
1885    }
1886    }
1887
1888    /**
1889     * Removes a listener for Notifications from the RequiredModelMBean.
1890     *
1891     * @param listener The listener name which was handling notifications
1892     * emitted by the registered MBean.
1893     * This method will remove all information related to this listener.
1894     *
1895     * @exception ListenerNotFoundException The listener is not registered
1896     * in the MBean or is null.
1897     *
1898     * @see #addNotificationListener
1899     **/

1900    public void removeNotificationListener(NotificationListener JavaDoc listener)
1901    throws ListenerNotFoundException JavaDoc {
1902    if (listener == null)
1903        throw new ListenerNotFoundException JavaDoc(
1904              "Notification listener is null");
1905    
1906    final String JavaDoc ftag="removeNotificationListener(NotificationListener)";
1907
1908    if (tracing()) trace(ftag,"Entry");
1909
1910    if (generalBroadcaster == null)
1911        throw new ListenerNotFoundException JavaDoc(
1912                  "No notification listeners registered");
1913    
1914    
1915    generalBroadcaster.removeNotificationListener(listener);
1916
1917    if (tracing()) trace(ftag,"Exit");
1918        
1919    }
1920
1921    public void removeNotificationListener(NotificationListener JavaDoc listener,
1922                       NotificationFilter JavaDoc filter,
1923                       Object JavaDoc handback)
1924    throws ListenerNotFoundException JavaDoc {
1925
1926    if (listener == null)
1927        throw new ListenerNotFoundException JavaDoc(
1928              "Notification listener is null");
1929    
1930    final String JavaDoc ftag="removeNotificationListener(NotificationListener, NotificationFilter, Object)";
1931
1932    if (tracing()) trace(ftag,"Entry");
1933
1934    if (generalBroadcaster == null)
1935        throw new ListenerNotFoundException JavaDoc(
1936                  "No notification listeners registered");
1937    
1938    
1939    generalBroadcaster.removeNotificationListener(listener,filter,
1940                              handback);
1941
1942    if (tracing()) trace(ftag,"Exit");
1943        
1944    }
1945
1946    public void sendNotification(Notification JavaDoc ntfyObj)
1947    throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
1948    if (tracing())
1949        trace("sendNotification(Notification)","Entry");
1950
1951    if (ntfyObj == null)
1952        throw new RuntimeOperationsException JavaDoc(new
1953        IllegalArgumentException JavaDoc("notification object must not be "+
1954                     "null"),
1955        "Exception occured trying to send a notification from a "+
1956        "RequiredModelMBean");
1957        
1958    
1959    // log notification if specified in descriptor
1960
Descriptor JavaDoc ntfyDesc =
1961        modelMBeanInfo.getDescriptor(ntfyObj.getType(),"notification");
1962    Descriptor JavaDoc mmbDesc = modelMBeanInfo.getMBeanDescriptor();
1963
1964    if (ntfyDesc != null) {
1965        String JavaDoc logging = (String JavaDoc) ntfyDesc.getFieldValue("log");
1966
1967        if (logging == null) {
1968        if (mmbDesc != null)
1969            logging = (String JavaDoc) mmbDesc.getFieldValue("log");
1970        }
1971
1972        if ((logging != null) &&
1973        (logging.equalsIgnoreCase("t") ||
1974         logging.equalsIgnoreCase("true"))) {
1975
1976        String JavaDoc logfile = (String JavaDoc) ntfyDesc.getFieldValue("logfile");
1977        if (logfile == null) {
1978            if (mmbDesc != null)
1979            logfile = (String JavaDoc)mmbDesc.getFieldValue("logfile");
1980        }
1981        if (logfile != null) {
1982            try {
1983            writeToLog(logfile,"LogMsg: " +
1984                ((new Date JavaDoc(ntfyObj.getTimeStamp())).toString())+
1985                " " + ntfyObj.getType() + " " +
1986                ntfyObj.getMessage() + " Severity = " +
1987                (String JavaDoc)ntfyDesc.getFieldValue("severity"));
1988            } catch (Exception JavaDoc e) {
1989            error("sendNotification(Notification)",
1990                  "Failed to log " + ntfyObj.getType() +
1991                  " notification: " + e);
1992            traceX("sendNotification(Notification)",e);
1993            }
1994        }
1995        }
1996    }
1997    if (generalBroadcaster != null) {
1998        generalBroadcaster.sendNotification(ntfyObj);
1999    }
2000
2001    if (tracing()) trace("sendNotification(Notification)",
2002          "sendNotification sent provided notification object");
2003        
2004    if (tracing())
2005        trace("sendNotification(Notification)","Exit");
2006
2007    }
2008
2009
2010    public void sendNotification(String JavaDoc ntfyText)
2011    throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
2012    if (tracing())
2013        trace("sendNotification(String)","Entry");
2014
2015    if (ntfyText == null)
2016        throw new RuntimeOperationsException JavaDoc(new
2017        IllegalArgumentException JavaDoc("notification message must not "+
2018                     "be null"),
2019        "Exception occured trying to send a text notification "+
2020        "from a ModelMBean");
2021        
2022    Notification JavaDoc myNtfyObj = new Notification JavaDoc("jmx.modelmbean.generic",
2023                          this, 1, ntfyText);
2024    sendNotification(myNtfyObj);
2025    if (tracing()) trace("sendNotification(string)",
2026                 "Notification sent");
2027
2028    if (tracing())
2029        trace("sendNotification(String)","Exit");
2030    }
2031
2032    /**
2033     * Returns `true' if the notification `notifName' is found
2034     * in `info'. (bug 4744667)
2035     **/

2036    private static final
2037    boolean hasNotification(final ModelMBeanInfo JavaDoc info,
2038                final String JavaDoc notifName) {
2039    try {
2040        if (info == null) return false;
2041        else return (info.getNotification(notifName)!=null);
2042    } catch (MBeanException JavaDoc x) {
2043        return false;
2044    } catch (RuntimeOperationsException JavaDoc r) {
2045        return false;
2046    }
2047    }
2048
2049    /**
2050     * Creates a default ModelMBeanNotificationInfo for GENERIC
2051     * notification. (bug 4744667)
2052     **/

2053    private static final ModelMBeanNotificationInfo JavaDoc makeGenericInfo() {
2054    final Descriptor JavaDoc genericDescriptor = new DescriptorSupport JavaDoc( new
2055        String JavaDoc[] {
2056        "name=GENERIC",
2057        "descriptorType=notification",
2058        "log=T",
2059        "severity=6",
2060        "displayName=jmx.modelmbean.generic"} );
2061    
2062    return new ModelMBeanNotificationInfo JavaDoc(new
2063        String JavaDoc[] {"jmx.modelmbean.generic"},
2064        "GENERIC",
2065        "A text notification has been issued by the managed resource",
2066        genericDescriptor);
2067    }
2068
2069    /**
2070     * Creates a default ModelMBeanNotificationInfo for ATTRIBUTE_CHANGE
2071     * notification. (bug 4744667)
2072     **/

2073    private static final
2074    ModelMBeanNotificationInfo JavaDoc makeAttributeChangeInfo() {
2075    final Descriptor JavaDoc attributeDescriptor = new DescriptorSupport JavaDoc(new
2076        String JavaDoc[] {
2077        "name=ATTRIBUTE_CHANGE",
2078        "descriptorType=notification",
2079        "log=T",
2080        "severity=6",
2081        "displayName=jmx.attribute.change"});
2082
2083    return new ModelMBeanNotificationInfo JavaDoc(new
2084        String JavaDoc[] {"jmx.attribute.change"},
2085        "ATTRIBUTE_CHANGE",
2086        "Signifies that an observed MBean attribute value has changed",
2087        attributeDescriptor );
2088    }
2089
2090    /**
2091     * Returns the array of Notifications always generated by the
2092     * RequiredModelMBean.
2093     * <P>
2094     *
2095     * RequiredModelMBean may always send also two additional notifications:
2096     * <UL>
2097     * <LI> One with descriptor <code>"name=GENERIC,descriptorType=notification,log=T,severity=6,displayName=jmx.modelmbean.generic"</code></LI>
2098     * <LI> Second is a standard attribute change notification
2099     * with descriptor <code>"name=ATTRIBUTE_CHANGE,descriptorType=notification,log=T,severity=6,displayName=jmx.attribute.change"</code></LI>
2100     * </UL>
2101     * Thus these two notifications are always added to those specified
2102     * by the application.
2103     *
2104     * @return MBeanNotificationInfo[]
2105     *
2106     **/

2107    public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
2108    if (tracing())
2109       trace("getNotificationInfo()","Entry");
2110
2111    // Using hasNotification() is not optimal, but shouldn't really
2112
// matter in this context...
2113

2114    // hasGeneric==true if GENERIC notification is present.
2115
// (bug 4744667)
2116
final boolean hasGeneric = hasNotification(modelMBeanInfo,"GENERIC");
2117
2118    // hasAttributeChange==true if ATTRIBUTE_CHANGE notification is
2119
// present.
2120
// (bug 4744667)
2121
final boolean hasAttributeChange =
2122       hasNotification(modelMBeanInfo,"ATTRIBUTE_CHANGE");
2123
2124    // User supplied list of notification infos.
2125
//
2126
final ModelMBeanNotificationInfo JavaDoc[] currInfo =
2127       (ModelMBeanNotificationInfo JavaDoc[])modelMBeanInfo.getNotifications();
2128
2129    // Length of the returned list of notification infos:
2130
// length of user suplied list + possibly 1 for GENERIC, +
2131
// possibly 1 for ATTRIBUTE_CHANGE
2132
// (bug 4744667)
2133
final int len = ((currInfo==null?0:currInfo.length) +
2134             (hasGeneric?0:1) + (hasAttributeChange?0:1));
2135
2136    // Returned list of notification infos:
2137
//
2138
final ModelMBeanNotificationInfo JavaDoc[] respInfo =
2139       new ModelMBeanNotificationInfo JavaDoc[len];
2140
2141    // Preserve previous ordering (JMX 1.1)
2142
//
2143

2144    // Counter of "standard" notification inserted before user
2145
// supplied notifications.
2146
//
2147
int inserted=0;
2148    if (!hasGeneric)
2149        // We need to add description for GENERIC notification
2150
// (bug 4744667)
2151
respInfo[inserted++] = makeGenericInfo();
2152    
2153
2154    if (!hasAttributeChange)
2155        // We need to add description for ATTRIBUTE_CHANGE notification
2156
// (bug 4744667)
2157
respInfo[inserted++] = makeAttributeChangeInfo();
2158
2159    // Now copy user supplied list in returned list.
2160
//
2161
final int count = currInfo.length;
2162    final int offset = inserted;
2163    for (int j=0; j < count; j++) {
2164        respInfo[offset+j] = (ModelMBeanNotificationInfo JavaDoc)(currInfo[j]);
2165    }
2166
2167    if (tracing())
2168            trace("getNotificationInfo()","Exit");
2169
2170    return respInfo;
2171    }
2172
2173
2174    public void addAttributeChangeNotificationListener(NotificationListener JavaDoc
2175                               inlistener,
2176                               String JavaDoc
2177                               inAttributeName,
2178                               Object JavaDoc inhandback)
2179    throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc,
2180           IllegalArgumentException JavaDoc {
2181    final String JavaDoc ftag="addAttributeChangeNotificationListener(NotificationListener, String, Object)";
2182
2183    if (tracing()) trace(ftag,"Entry");
2184
2185    if (inlistener == null)
2186        throw new IllegalArgumentException JavaDoc(
2187                  "Listener to be registered must not be null");
2188        
2189            
2190    if (attributeBroadcaster == null)
2191        attributeBroadcaster = new NotificationBroadcasterSupport JavaDoc();
2192
2193    AttributeChangeNotificationFilter JavaDoc currFilter =
2194        new AttributeChangeNotificationFilter JavaDoc();
2195
2196    MBeanAttributeInfo JavaDoc[] attrInfo = modelMBeanInfo.getAttributes();
2197    boolean found = false;
2198    if (inAttributeName == null) {
2199        if ((attrInfo != null) && (attrInfo.length>0)) {
2200        for (int i=0; i<attrInfo.length; i++) {
2201            currFilter.enableAttribute(attrInfo[i].getName());
2202        }
2203        }
2204    } else {
2205        if ((attrInfo != null) && (attrInfo.length>0)) {
2206        for (int i=0; i<attrInfo.length; i++) {
2207            if (inAttributeName.equals(attrInfo[i].getName())) {
2208            found = true;
2209            currFilter.enableAttribute(inAttributeName);
2210            break;
2211            }
2212        }
2213        if (!found) {
2214            throw new RuntimeOperationsException JavaDoc(new
2215            IllegalArgumentException JavaDoc(
2216                        "The attribute name does not exist"),
2217                        "Exception occured trying to add an "+
2218            "AttributeChangeNotification listener");
2219        }
2220        }
2221    }
2222
2223    if (tracing())
2224        trace(ftag, "Set attribute change filter to " +
2225        ((currFilter.getEnabledAttributes()).firstElement()).toString());
2226
2227    attributeBroadcaster.addNotificationListener(inlistener,currFilter,
2228                             inhandback);
2229    if (tracing()) trace("addAttributeChangeNotificationListener",
2230                 "added for " + inAttributeName);
2231    
2232    if (tracing()) trace(ftag,"Exit");
2233    }
2234
2235    public void removeAttributeChangeNotificationListener(NotificationListener JavaDoc inlistener, String JavaDoc inAttributeName)
2236    throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc,
2237           ListenerNotFoundException JavaDoc {
2238    if (inlistener == null) throw new
2239        ListenerNotFoundException JavaDoc("Notification listener is null");
2240    
2241    final String JavaDoc ftag = "removeAttributeChangeNotificationListener(NotificationListener, String)";
2242
2243    if (tracing()) trace(ftag,"Entry");
2244        
2245    
2246    if (attributeBroadcaster == null)
2247        throw new ListenerNotFoundException JavaDoc(
2248                  "No attribute change notification listeners registered");
2249        
2250    
2251    MBeanAttributeInfo JavaDoc[] attrInfo = modelMBeanInfo.getAttributes();
2252    boolean found = false;
2253    if ((attrInfo != null) && (attrInfo.length>0)) {
2254        for (int i=0; i<attrInfo.length; i++) {
2255        if (attrInfo[i].getName().equals(inAttributeName)) {
2256            found = true;
2257            break;
2258        }
2259        }
2260    }
2261        
2262    if ((!found) && (inAttributeName != null)) {
2263        throw new RuntimeOperationsException JavaDoc(new
2264        IllegalArgumentException JavaDoc("Invalid attribute name"),
2265        "Exception occured trying to remove "+
2266        "attribute change notification listener");
2267    }
2268
2269    /* note: */
2270        /* this may be a problem if the same listener is registered for
2271       multiple attributes with multiple filters and/or handback
2272       objects. It may remove all of them */

2273        
2274    attributeBroadcaster.removeNotificationListener(inlistener);
2275        
2276        
2277    if (tracing()) trace(ftag,"Exit");
2278    
2279    }
2280
2281
2282    public void sendAttributeChangeNotification(AttributeChangeNotification JavaDoc
2283                        ntfyObj)
2284    throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
2285    final String JavaDoc ftag =
2286        "sendAttributeChangeNotification(AttributeChangeNotification)";
2287
2288    if (tracing()) trace(ftag,"Entry");
2289    
2290    if (ntfyObj == null)
2291        throw new RuntimeOperationsException JavaDoc(new
2292        IllegalArgumentException JavaDoc(
2293                "attribute change notification object must not be null"),
2294        "Exception occured trying to send "+
2295                "attribute change notification of a ModelMBean");
2296    
2297    Object JavaDoc oldv = ntfyObj.getOldValue();
2298    Object JavaDoc newv = ntfyObj.getNewValue();
2299
2300    if (oldv == null) oldv = "null";
2301    if (newv == null) newv = "null";
2302        
2303    if (tracing())
2304        trace(ftag,"Sending AttributeChangeNotification " +
2305          " with " + ntfyObj.getAttributeName() +
2306          ntfyObj.getAttributeType() +
2307          ntfyObj.getNewValue() +
2308          ntfyObj.getOldValue());
2309    
2310    // log notification if specified in descriptor
2311
Descriptor JavaDoc ntfyDesc =
2312        modelMBeanInfo.getDescriptor(ntfyObj.getType(),"notification");
2313    Descriptor JavaDoc mmbDesc = modelMBeanInfo.getMBeanDescriptor();
2314    
2315    String JavaDoc logging, logfile;
2316    
2317    if (ntfyDesc != null) {
2318        logging =(String JavaDoc) ntfyDesc.getFieldValue("log");
2319        if (logging == null) {
2320        if (mmbDesc != null)
2321            logging = (String JavaDoc) mmbDesc.getFieldValue("log");
2322        }
2323        if ((logging != null) &&
2324        ( logging.equalsIgnoreCase("t") ||
2325          logging.equalsIgnoreCase("true"))) {
2326        logfile = (String JavaDoc) ntfyDesc.getFieldValue("logfile");
2327        if (logfile == null) {
2328            if (mmbDesc != null)
2329            logfile = (String JavaDoc)mmbDesc.getFieldValue("logfile");
2330        }
2331            
2332        if (logfile != null) {
2333            try {
2334            writeToLog(logfile,"LogMsg: " +
2335               ((new Date JavaDoc(ntfyObj.getTimeStamp())).toString())+
2336               " " + ntfyObj.getType() + " " +
2337               ntfyObj.getMessage() +
2338               " Name = " + ntfyObj.getAttributeName() +
2339               " Old value = " + oldv +
2340               " New value = " + newv);
2341            } catch (Exception JavaDoc e) {
2342            error(ftag,"Failed to log " + ntfyObj.getType() +
2343                  " notification: " + e);
2344            traceX(ftag,e);
2345            }
2346        }
2347        }
2348    } else if (mmbDesc != null) {
2349        logging = (String JavaDoc) mmbDesc.getFieldValue("log");
2350        if ((logging != null) &&
2351        ( logging.equalsIgnoreCase("t") ||
2352          logging.equalsIgnoreCase("true") )) {
2353        logfile = (String JavaDoc) mmbDesc.getFieldValue("logfile");
2354
2355        if (logfile != null) {
2356            try {
2357            writeToLog(logfile,"LogMsg: " +
2358               ((new Date JavaDoc(ntfyObj.getTimeStamp())).toString())+
2359               " " + ntfyObj.getType() + " " +
2360               ntfyObj.getMessage() +
2361               " Name = " + ntfyObj.getAttributeName() +
2362               " Old value = " + oldv +
2363               " New value = " + newv);
2364            } catch (Exception JavaDoc e) {
2365            error(ftag,"Failed to log " + ntfyObj.getType() +
2366                  " notification: " + e);
2367            traceX(ftag,e);
2368            }
2369        }
2370        }
2371    }
2372    if (attributeBroadcaster != null) {
2373        attributeBroadcaster.sendNotification(ntfyObj);
2374    }
2375
2376    // XXX Revisit: This is a quickfix: it would be better to have a
2377
// single broadcaster. However, it is not so simple because
2378
// removeAttributeChangeNotificationListener() should
2379
// remove only listeners whose filter is an instanceof
2380
// AttributeChangeNotificationFilter.
2381
//
2382
if (generalBroadcaster != null) {
2383        generalBroadcaster.sendNotification(ntfyObj);
2384    }
2385    if (tracing()) trace(ftag,"sent notification");
2386    
2387    if (tracing()) trace(ftag,"Exit");
2388    }
2389
2390
2391    public void sendAttributeChangeNotification(Attribute JavaDoc inOldVal,
2392                        Attribute JavaDoc inNewVal)
2393    throws MBeanException JavaDoc, RuntimeOperationsException JavaDoc {
2394    final String JavaDoc ftag =
2395        "sendAttributeChangeNotification(Attribute, Attribute)";
2396    if (tracing()) trace(ftag,"Entry");
2397
2398    // do we really want to do this?
2399
if ((inOldVal == null) || (inNewVal == null))
2400        throw new RuntimeOperationsException JavaDoc(new
2401           IllegalArgumentException JavaDoc("Attribute object must not be null"),
2402           "Exception occured trying to send " +
2403           "attribute change notification of a ModelMBean");
2404    
2405
2406    if (!(inOldVal.getName().equals(inNewVal.getName())))
2407        throw new RuntimeOperationsException JavaDoc(new
2408        IllegalArgumentException JavaDoc("Attribute names are not the same"),
2409        "Exception occured trying to send " +
2410        "attribute change notification of a ModelMBean");
2411
2412    
2413    Object JavaDoc newVal = inNewVal.getValue();
2414    Object JavaDoc oldVal = inOldVal.getValue();
2415    String JavaDoc className = "unknown";
2416    if (newVal != null)
2417        className = newVal.getClass().getName();
2418    if (oldVal != null)
2419        className = oldVal.getClass().getName();
2420    
2421    AttributeChangeNotification JavaDoc myNtfyObj = new
2422        AttributeChangeNotification JavaDoc(this,
2423                    1,
2424                    ((new Date JavaDoc()).getTime()),
2425                    "AttributeChangeDetected",
2426                    inOldVal.getName(),
2427                    className,
2428                    inOldVal.getValue(),
2429                    inNewVal.getValue());
2430    
2431    sendAttributeChangeNotification(myNtfyObj);
2432
2433    if (tracing()) trace(ftag,"Exit");
2434
2435    }
2436
2437    /**
2438     * Return the Class Loader Repository used to perform class loading.
2439     * Subclasses may wish to redefine this method in order to return
2440     * the appropriate {@link javax.management.loading.ClassLoaderRepository}
2441     * that should be used in this object.
2442     *
2443     * @return the Class Loader Repository.
2444     *
2445     * @since.unbundled JMX 1.1
2446     */

2447    protected ClassLoaderRepository JavaDoc getClassLoaderRepository() {
2448    return MBeanServerFactory.getClassLoaderRepository(server);
2449    }
2450
2451    private Class JavaDoc loadClass(String JavaDoc className)
2452    throws ClassNotFoundException JavaDoc {
2453    try {
2454        return Class.forName(className);
2455    } catch (ClassNotFoundException JavaDoc e) {
2456        final ClassLoaderRepository JavaDoc clr =
2457        getClassLoaderRepository();
2458        if (clr == null) throw new ClassNotFoundException JavaDoc(className);
2459        return clr.loadClass(className);
2460    }
2461    }
2462
2463
2464    /*************************************/
2465    /* MBeanRegistration Interface */
2466    /*************************************/
2467
2468    /**
2469     * Allows the MBean to perform any operations it needs before
2470     * being registered in the MBean server. If the name of the MBean
2471     * is not specified, the MBean can provide a name for its
2472     * registration. If any exception is raised, the MBean will not be
2473     * registered in the MBean server.
2474     * <P>
2475     * In order to ensure proper run-time semantics of RequireModelMBean,
2476     * Any subclass of RequiredModelMBean overloading or overriding this
2477     * method should call <code>super.preRegister(server, name)</code>
2478     * in its own <code>preRegister</code> implementation.
2479     *
2480     * @param server The MBean server in which the MBean will be registered.
2481     *
2482     * @param name The object name of the MBean. This name is null if
2483     * the name parameter to one of the <code>createMBean</code> or
2484     * <code>registerMBean</code> methods in the {@link MBeanServer}
2485     * interface is null. In that case, this method must return a
2486     * non-null ObjectName for the new MBean.
2487     *
2488     * @return The name under which the MBean is to be registered.
2489     * This value must not be null. If the <code>name</code>
2490     * parameter is not null, it will usually but not necessarily be
2491     * the returned value.
2492     *
2493     * @exception java.lang.Exception This exception will be caught by
2494     * the MBean server and re-thrown as an
2495     * {@link javax.management.MBeanRegistrationException
2496     * MBeanRegistrationException}.
2497     */

2498    public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server,
2499                  ObjectName JavaDoc name)
2500    throws java.lang.Exception JavaDoc {
2501        // Since ModelMbeanInfo cannot be null (otherwise exception
2502
// thrown at creation)
2503
// no exception thrown on ModelMBeanInfo not set.
2504
if (name == null) throw new NullPointerException JavaDoc(
2505             "name of RequiredModelMBean to registered is null");
2506    this.server = server;
2507        return name;
2508    }
2509
2510    /**
2511     * Allows the MBean to perform any operations needed after having been
2512     * registered in the MBean server or after the registration has failed.
2513     * <P>
2514     * In order to ensure proper run-time semantics of RequireModelMBean,
2515     * Any subclass of RequiredModelMBean overloading or overriding this
2516     * method should call <code>super.postRegister(registrationDone)</code>
2517     * in its own <code>postRegister</code> implementation.
2518     *
2519     * @param registrationDone Indicates whether or not the MBean has
2520     * been successfully registered in the MBean server. The value
2521     * false means that the registration phase has failed.
2522     */

2523    public void postRegister(Boolean JavaDoc registrationDone) {
2524        registered = registrationDone.booleanValue();
2525    }
2526
2527    /**
2528     * Allows the MBean to perform any operations it needs before
2529     * being unregistered by the MBean server.
2530     * <P>
2531     * In order to ensure proper run-time semantics of RequireModelMBean,
2532     * Any subclass of RequiredModelMBean overloading or overriding this
2533     * method should call <code>super.preDeregister()</code> in its own
2534     * <code>preDeregister</code> implementation.
2535     *
2536     * @exception java.lang.Exception This exception will be caught by
2537     * the MBean server and re-thrown as an
2538     * {@link javax.management.MBeanRegistrationException
2539     * MBeanRegistrationException}.
2540     */

2541    public void preDeregister() throws java.lang.Exception JavaDoc {
2542    }
2543
2544    /**
2545     * Allows the MBean to perform any operations needed after having been
2546     * unregistered in the MBean server.
2547     * <P>
2548     * In order to ensure proper run-time semantics of RequireModelMBean,
2549     * Any subclass of RequiredModelMBean overloading or overriding this
2550     * method should call <code>super.postDeregister()</code> in its own
2551     * <code>postDeregister</code> implementation.
2552     */

2553    public void postDeregister() {
2554        registered = false;
2555    this.server=null;
2556    }
2557
2558    // SUN Trace and debug functions
2559
private final static boolean tracing() {
2560        
2561    return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN);
2562    }
2563
2564    private static void trace(String JavaDoc inClass, String JavaDoc inMethod, String JavaDoc inText) {
2565    Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN, inClass,
2566           inMethod, inText);
2567    }
2568
2569    private static void traceX(String JavaDoc inMethod, Throwable JavaDoc x) {
2570    Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN, currClass,
2571           inMethod, x);
2572    }
2573
2574    private static void trace(String JavaDoc inMethod, String JavaDoc inText) {
2575    trace(currClass, inMethod, inText);
2576    }
2577
2578    private static void error(String JavaDoc inMethod, String JavaDoc inText) {
2579    Trace.send(Trace.LEVEL_ERROR, Trace.INFO_MODELMBEAN, currClass,
2580           inMethod, inText);
2581    }
2582
2583    private static boolean debugging() {
2584    return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MODELMBEAN);
2585    }
2586
2587    private static void debug(String JavaDoc inClass, String JavaDoc inMethod, String JavaDoc inText) {
2588    Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MODELMBEAN, inClass,
2589           inMethod, inText);
2590    }
2591
2592    private static void debug(String JavaDoc inMethod, String JavaDoc inText) {
2593    debug(currClass, inMethod, inText);
2594    }
2595
2596    private static void debug(String JavaDoc inMethod, Throwable JavaDoc x) {
2597    Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MODELMBEAN, currClass,
2598           inMethod, x);
2599    }
2600
2601    private static final String JavaDoc[] primitiveTypes;
2602    private static final String JavaDoc[] primitiveWrappers;
2603    static {
2604        primitiveTypes = new String JavaDoc[] {
2605            Boolean.TYPE.getName(),
2606            Byte.TYPE.getName(),
2607            Character.TYPE.getName(),
2608            Short.TYPE.getName(),
2609            Integer.TYPE.getName(),
2610            Long.TYPE.getName(),
2611            Float.TYPE.getName(),
2612            Double.TYPE.getName(),
2613            Void.TYPE.getName()
2614        };
2615        primitiveWrappers = new String JavaDoc[] {
2616            Boolean JavaDoc.class.getName(),
2617            Byte JavaDoc.class.getName(),
2618            Character JavaDoc.class.getName(),
2619            Short JavaDoc.class.getName(),
2620            Integer JavaDoc.class.getName(),
2621            Long JavaDoc.class.getName(),
2622            Float JavaDoc.class.getName(),
2623            Double JavaDoc.class.getName(),
2624            Void JavaDoc.class.getName()
2625        };
2626    }
2627}
2628
Popular Tags