KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > javax > management > monitor > StringMonitor


1 /*
2  * @(#)StringMonitor.java 4.41 04/05/18
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package javax.management.monitor;
9
10
11 // java imports
12
//
13
import java.util.Date JavaDoc;
14 import java.util.Timer JavaDoc;
15 import java.util.TimerTask JavaDoc;
16
17 // jmx imports
18
//
19
import javax.management.ObjectName JavaDoc;
20 import javax.management.MBeanNotificationInfo JavaDoc;
21 import javax.management.AttributeNotFoundException JavaDoc;
22 import javax.management.InstanceNotFoundException JavaDoc;
23 import javax.management.MBeanException JavaDoc;
24 import javax.management.ReflectionException JavaDoc;
25
26 /**
27  * Defines a monitor MBean designed to observe the values of a string
28  * attribute.
29  * <P>
30  * A string monitor sends notifications as follows:
31  * <UL>
32  * <LI> if the attribute value matches the string to compare value,
33  * a {@link MonitorNotification#STRING_TO_COMPARE_VALUE_MATCHED
34  * match notification} is sent.
35  * The notify match flag must be set to <CODE>true</CODE>.
36  * <BR>Subsequent matchings of the string to compare values do not
37  * cause further notifications unless
38  * the attribute value differs from the string to compare value.
39  * <LI> if the attribute value differs from the string to compare value,
40  * a {@link MonitorNotification#STRING_TO_COMPARE_VALUE_DIFFERED
41  * differ notification} is sent.
42  * The notify differ flag must be set to <CODE>true</CODE>.
43  * <BR>Subsequent differences from the string to compare value do
44  * not cause further notifications unless
45  * the attribute value matches the string to compare value.
46  * </UL>
47  *
48  * @version 4.41 05/18/04
49  * @author Sun Microsystems, Inc
50  *
51  * @since 1.5
52  */

53 public class StringMonitor extends Monitor JavaDoc implements StringMonitorMBean JavaDoc {
54
55
56     // TRACES & DEBUG
57
//---------------
58

59     String JavaDoc makeDebugTag() {
60         return "StringMonitor";
61     }
62
63     /*
64      * ------------------------------------------
65      * PRIVATE VARIABLES
66      * ------------------------------------------
67      */

68
69     private final static String JavaDoc[] types = {
70         MonitorNotification.RUNTIME_ERROR,
71         MonitorNotification.OBSERVED_OBJECT_ERROR,
72         MonitorNotification.OBSERVED_ATTRIBUTE_ERROR,
73         MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR,
74         MonitorNotification.STRING_TO_COMPARE_VALUE_MATCHED,
75         MonitorNotification.STRING_TO_COMPARE_VALUE_DIFFERED};
76     private final static MBeanNotificationInfo JavaDoc[] notifsInfo = {
77         new MBeanNotificationInfo JavaDoc(types,
78         "javax.management.monitor.MonitorNotification",
79         "Notifications sent by the StringMonitor MBean")};
80
81     /**
82      * String to compare with the observed attribute.
83      * <BR>The default value is an empty character sequence.
84      */

85     private String JavaDoc stringToCompare = "";
86
87     /**
88      * Flag indicating if the string monitor notifies when matching
89      * the string to compare.
90      * <BR>The default value is set to <CODE>false</CODE>.
91      */

92     private boolean notifyMatch = false;
93
94     /**
95      * Flag indicating if the string monitor notifies when differing
96      * from the string to compare.
97      * <BR>The default value is set to <CODE>false</CODE>.
98      */

99     private boolean notifyDiffer = false;
100
101     /**
102      * Derived gauges.
103      * <BR>Each element in this array corresponds to an observed object
104      * in the list.
105      */

106     private String JavaDoc derivedGauge[] = new String JavaDoc[capacityIncrement];
107
108     /**
109      * Derived gauge timestamps.
110      * <BR>Each element in this array corresponds to an observed object
111      * in the list.
112      */

113     private long derivedGaugeTimestamp[] = new long[capacityIncrement];
114
115     /**
116      * This attribute is used to handle the matching/differing mechanism.
117      * <BR>Each element in this array corresponds to an observed object
118      * in the list.
119      */

120     private int status[] = new int[capacityIncrement];
121
122     // Flags needed to implement the matching/differing mechanism.
123
//
124
private static final int MATCHING = 0;
125     private static final int DIFFERING = 1;
126     private static final int MATCHING_OR_DIFFERING = 2;
127
128     /**
129      * Timer.
130      */

131     private transient Timer JavaDoc timer = null;
132
133
134     /*
135      * ------------------------------------------
136      * CONSTRUCTORS
137      * ------------------------------------------
138      */

139
140     /**
141      * Default constructor.
142      */

143     public StringMonitor() {
144     dbgTag = makeDebugTag();
145     }
146
147     /*
148      * ------------------------------------------
149      * PUBLIC METHODS
150      * ------------------------------------------
151      */

152
153     /**
154      * Starts the string monitor.
155      */

156     public synchronized void start() {
157
158         if (isTraceOn()) {
159             trace("start", "start the string monitor");
160         }
161
162     if (isActive) {
163         if (isTraceOn()) {
164         trace("start", "the string monitor is already activated");
165         }
166
167         return;
168     }
169
170     isActive = true;
171
172     // Reset values.
173
//
174
for (int i = 0; i < elementCount; i++) {
175         status[i] = MATCHING_OR_DIFFERING;
176     }
177
178     // Start the AlarmClock.
179
//
180
timer = new Timer JavaDoc();
181     timer.schedule(new StringAlarmClock(this),
182                getGranularityPeriod(), getGranularityPeriod());
183     }
184
185     /**
186      * Stops the string monitor.
187      */

188     /* This method is not synchronized, because if it were there could
189        be a deadlock with a thread that attempted to get the lock on
190        the monitor before being interrupted or noticing that it had
191        been interrupted. */

192     public void stop() {
193
194         if (isTraceOn()) {
195             trace("stop", "stop the string monitor");
196         }
197
198         synchronized(this) {
199         if (!isActive) {
200         if (isTraceOn()) {
201             trace("stop", "the string monitor is already deactivated");
202         }
203
204         return;
205         }
206
207             isActive = false;
208
209             // Stop the AlarmClock.
210
//
211
if (timer != null) {
212         timer.cancel();
213         timer = null;
214             }
215     }
216     }
217
218     // GETTERS AND SETTERS
219
//--------------------
220

221     /**
222      * Sets the granularity period (in milliseconds).
223      * <BR>The default value of the granularity period is 10 seconds.
224      *
225      * @param period The granularity period value.
226      * @exception java.lang.IllegalArgumentException The granularity
227      * period is less than or equal to zero.
228      *
229      * @see Monitor#setGranularityPeriod(long)
230      */

231     public synchronized void setGranularityPeriod(long period)
232         throws IllegalArgumentException JavaDoc {
233         super.setGranularityPeriod(period);
234
235         // Reschedule timer task if timer is already running
236
//
237
if (isActive) {
238         timer.cancel();
239         timer = new Timer JavaDoc();
240         timer.schedule(new StringAlarmClock(this),
241                getGranularityPeriod(), getGranularityPeriod());
242     }
243     }
244
245     /**
246      * Gets the derived gauge of the specified object, if this object is
247      * contained in the set of observed MBeans, or <code>null</code> otherwise.
248      *
249      * @param object the name of the MBean whose derived gauge is required.
250      *
251      * @return The derived gauge of the specified object.
252      *
253      * @since.unbundled JMX 1.2
254      */

255     public synchronized String JavaDoc getDerivedGauge(ObjectName JavaDoc object) {
256         int index = indexOf(object);
257         if (index != -1)
258             return derivedGauge[index];
259         else
260             return null;
261     }
262
263     /**
264      * Gets the derived gauge timestamp of the specified object, if
265      * this object is contained in the set of observed MBeans, or
266      * <code>null</code> otherwise.
267      *
268      * @param object the name of the MBean whose derived gauge
269      * timestamp is required.
270      *
271      * @return The derived gauge timestamp of the specified object.
272      *
273      * @since.unbundled JMX 1.2
274      */

275     public synchronized long getDerivedGaugeTimeStamp(ObjectName JavaDoc object) {
276         int index = indexOf(object);
277         if (index != -1)
278             return derivedGaugeTimestamp[index];
279         else
280             return 0;
281     }
282
283     /**
284      * Returns the derived gauge of the first object in the set of
285      * observed MBeans.
286      *
287      * @return The derived gauge.
288      * @deprecated As of JMX 1.2, replaced by {@link #getDerivedGauge(ObjectName)}
289      */

290     public synchronized String JavaDoc getDerivedGauge() {
291         return derivedGauge[0];
292     }
293
294     /**
295      * Gets the derived gauge timestamp of the first object in the set
296      * of observed MBeans.
297      *
298      * @return The derived gauge timestamp.
299      * @deprecated As of JMX 1.2, replaced by
300      * {@link #getDerivedGaugeTimeStamp(ObjectName)}
301      */

302     @Deprecated JavaDoc
303     public synchronized long getDerivedGaugeTimeStamp() {
304         return derivedGaugeTimestamp[0];
305     }
306
307     /**
308      * Gets the string to compare with the observed attribute common
309      * to all observed MBeans.
310      *
311      * @return The string value.
312      *
313      * @see #setStringToCompare
314      */

315     public synchronized String JavaDoc getStringToCompare() {
316         return stringToCompare;
317     }
318
319     /**
320      * Sets the string to compare with the observed attribute common
321      * to all observed MBeans.
322      *
323      * @param value The string value.
324      * @exception java.lang.IllegalArgumentException The specified
325      * string to compare is null.
326      *
327      * @see #getStringToCompare
328      */

329     public synchronized void setStringToCompare(String JavaDoc value)
330         throws java.lang.IllegalArgumentException JavaDoc {
331
332         if (value == null) {
333         throw new IllegalArgumentException JavaDoc("Null string to compare");
334         }
335
336         stringToCompare = value;
337
338         // Reset values.
339
//
340
for (int i = 0; i < elementCount; i++) {
341           status[i] = MATCHING_OR_DIFFERING;
342         }
343     }
344
345     /**
346      * Gets the matching notification's on/off switch value common to
347      * all observed MBeans.
348      *
349      * @return <CODE>true</CODE> if the string monitor notifies when
350      * matching the string to compare, <CODE>false</CODE> otherwise.
351      *
352      * @see #setNotifyMatch
353      */

354     public synchronized boolean getNotifyMatch() {
355         return notifyMatch;
356     }
357
358     /**
359      * Sets the matching notification's on/off switch value common to
360      * all observed MBeans.
361      *
362      * @param value The matching notification's on/off switch value.
363      *
364      * @see #getNotifyMatch
365      */

366     public synchronized void setNotifyMatch(boolean value) {
367         notifyMatch = value;
368     }
369
370     /**
371      * Gets the differing notification's on/off switch value common to
372      * all observed MBeans.
373      *
374      * @return <CODE>true</CODE> if the string monitor notifies when
375      * differing from the string to compare, <CODE>false</CODE> otherwise.
376      *
377      * @see #setNotifyDiffer
378      */

379     public synchronized boolean getNotifyDiffer() {
380         return notifyDiffer;
381     }
382
383     /**
384      * Sets the differing notification's on/off switch value common to
385      * all observed MBeans.
386      *
387      * @param value The differing notification's on/off switch value.
388      *
389      * @see #getNotifyDiffer
390      */

391     public synchronized void setNotifyDiffer(boolean value) {
392         notifyDiffer = value;
393     }
394
395     /**
396      * Returns a <CODE>NotificationInfo</CODE> object containing the
397      * name of the Java class of the notification
398      * and the notification types sent by the string monitor.
399      */

400     public MBeanNotificationInfo JavaDoc[] getNotificationInfo() {
401         return notifsInfo;
402     }
403
404     /*
405      * ------------------------------------------
406      * PRIVATE METHODS
407      * ------------------------------------------
408      */

409
410     /**
411      * Updates the derived gauge and the derived gauge timestamp attributes
412      * of the observed object at the specified index.
413      *
414      * @param scanString The value of the observed attribute.
415      * @param index The index of the observed object.
416      */

417     private synchronized void updateDerivedGauge(Object JavaDoc scanString,
418                          int index) {
419         derivedGaugeTimestamp[index] = System.currentTimeMillis();
420         derivedGauge[index] = (String JavaDoc)scanString;
421     }
422
423     /**
424      * Updates the notification attributes of the observed object at the
425      * specified index and notifies the listeners only once if the
426      * notifyMatch/notifyDiffer flag is set to <CODE>true</CODE>.
427      * @param index The index of the observed object.
428      */

429     private void updateNotifications(int index) {
430     boolean sendNotify = false;
431     String JavaDoc type = null;
432     long timeStamp = 0;
433     String JavaDoc msg = null;
434     Object JavaDoc derGauge = null;
435     Object JavaDoc trigger = null;
436
437     synchronized(this) {
438         // Send matching notification if notifyMatch is true.
439
// Send differing notification if notifyDiffer is true.
440
//
441
if (status[index] == MATCHING_OR_DIFFERING) {
442         if (derivedGauge[index].equals(stringToCompare)) {
443             if (notifyMatch) {
444             sendNotify = true;
445             type =
446                 MonitorNotification.STRING_TO_COMPARE_VALUE_MATCHED;
447             timeStamp = derivedGaugeTimestamp[index];
448             msg = "";
449             derGauge = derivedGauge[index];
450             trigger = stringToCompare;
451             }
452
453             status[index] = DIFFERING;
454         } else {
455             if (notifyDiffer) {
456             sendNotify = true;
457             type =
458                 MonitorNotification.STRING_TO_COMPARE_VALUE_DIFFERED;
459             timeStamp = derivedGaugeTimestamp[index];
460             msg = "";
461             derGauge = derivedGauge[index];
462             trigger = stringToCompare;
463             }
464             status[index] = MATCHING;
465         }
466         } else {
467         if (status[index] == MATCHING) {
468             if (derivedGauge[index].equals(stringToCompare)) {
469             if (notifyMatch) {
470                 sendNotify = true;
471                 type =
472                 MonitorNotification.STRING_TO_COMPARE_VALUE_MATCHED;
473                 timeStamp = derivedGaugeTimestamp[index];
474                 msg = "";
475                 derGauge = derivedGauge[index];
476                 trigger = stringToCompare;
477
478             }
479             status[index] = DIFFERING;
480             }
481         } else if (status[index] == DIFFERING) {
482             if (!derivedGauge[index].equals(stringToCompare)) {
483             if (notifyDiffer) {
484                 sendNotify = true;
485                 type =
486                 MonitorNotification.STRING_TO_COMPARE_VALUE_DIFFERED;
487                 timeStamp = derivedGaugeTimestamp[index];
488                 msg = "";
489                 derGauge = derivedGauge[index];
490                 trigger = stringToCompare;
491             }
492             status[index] = MATCHING;
493             }
494         }
495         }
496     }
497
498     if (sendNotify) {
499         sendNotification(type, timeStamp, msg, derGauge, trigger, index);
500     }
501     }
502
503     /*
504      * ------------------------------------------
505      * PACKAGE METHODS
506      * ------------------------------------------
507      */

508
509     /**
510      * This method is called by the string monitor each time
511      * the granularity period has been exceeded.
512      * @param index The index of the observed object.
513      */

514     void notifyAlarmClock(int index) {
515     boolean sendNotify = false;
516     String JavaDoc type = null;
517     long timeStamp = 0;
518     String JavaDoc msg = null;
519     Object JavaDoc derGauge = null;
520     Object JavaDoc trigger = null;
521
522         Object JavaDoc scan_string = null;
523         String JavaDoc notif_type = null;
524
525     synchronized(this) {
526         if (!isActive)
527         return;
528
529         // Check if the observed object and observed attribute are valid.
530
//
531

532         // Check that neither the observed object nor the observed
533
// attribute are null. If the observed object or observed
534
// attribute is null, this means that the monitor started
535
// before a complete initialization and nothing is done.
536
//
537
if ((getObservedObject(index) == null) ||
538         (getObservedAttribute() == null))
539         return;
540
541         // Check that the observed object is registered in the
542
// MBean server and that the observed attribute belongs to
543
// the observed object.
544
//
545
try {
546         scan_string = server.getAttribute(getObservedObject(index),
547                           getObservedAttribute());
548         if (scan_string == null)
549             return;
550         } catch (NullPointerException JavaDoc np_ex) {
551         if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
552             return;
553         else {
554             notif_type = MonitorNotification.RUNTIME_ERROR;
555             setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
556             msg =
557             "The string monitor must be registered in " +
558             "the MBean server.";
559         }
560         } catch (InstanceNotFoundException JavaDoc inf_ex) {
561         if (alreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED))
562             return;
563         else {
564             notif_type = MonitorNotification.OBSERVED_OBJECT_ERROR;
565             setAlreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED);
566             msg =
567             "The observed object must be registered in " +
568             "the MBean server.";
569         }
570         } catch (AttributeNotFoundException JavaDoc anf_ex) {
571         if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
572             return;
573         else {
574             notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
575             setAlreadyNotified(index,
576                        OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
577             msg =
578             "The observed attribute must be accessible in " +
579             "the observed object.";
580         }
581         } catch (MBeanException JavaDoc mb_ex) {
582         if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
583             return;
584         else {
585             notif_type = MonitorNotification.RUNTIME_ERROR;
586             setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
587             msg = mb_ex.getMessage();
588         }
589         } catch (ReflectionException JavaDoc ref_ex) {
590         if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
591             return;
592         else {
593             notif_type = MonitorNotification.OBSERVED_ATTRIBUTE_ERROR;
594             setAlreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
595             msg = ref_ex.getMessage();
596         }
597         }
598
599         if (msg == null) {
600         // Check that the observed attribute is of type "String".
601
//
602
if (!(scan_string instanceof String JavaDoc)) {
603             if (alreadyNotified(index,
604                     OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
605             return;
606             else {
607             notif_type =
608                 MonitorNotification.OBSERVED_ATTRIBUTE_TYPE_ERROR;
609             setAlreadyNotified(index,
610                        OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
611             msg =
612                 "The observed attribute type must be " +
613                 "a string type.";
614             }
615         }
616         }
617
618         if (msg == null) {
619
620         // Clear all already notified flags.
621
//
622
resetAllAlreadyNotified(index);
623
624         // Update the derived gauge attributes.
625
//
626
updateDerivedGauge(scan_string, index);
627
628         // Notify the listeners.
629
//
630
updateNotifications(index);
631
632         } else {
633
634         // msg != null, will send the monitor error notification.
635

636         timeStamp = derivedGaugeTimestamp[index];
637                 derGauge = derivedGauge[index];
638
639         // Reset values.
640
//
641
status[index] = MATCHING_OR_DIFFERING;
642         }
643     }
644
645     if (msg != null) {
646         sendNotification(type, timeStamp, msg, derGauge, null, index);
647     }
648     }
649
650     /**
651      * This method is called when adding a new observed object in the vector.
652      * It updates all the string specific arrays.
653      * @param index The index of the observed object.
654      */

655     synchronized void insertSpecificElementAt(int index) {
656         // Update derivedGauge, derivedGaugeTimestamp, and status arrays.
657
//
658

659     if (index != elementCount)
660         throw new Error JavaDoc("Internal error: index != elementCount");
661
662     if (elementCount >= derivedGauge.length) {
663         derivedGauge = expandArray(derivedGauge);
664         derivedGaugeTimestamp = expandArray(derivedGaugeTimestamp);
665         status = expandArray(status);
666     }
667
668     derivedGauge[index] = "";
669     derivedGaugeTimestamp[index] = System.currentTimeMillis();
670     status[index] = MATCHING_OR_DIFFERING;
671     }
672
673     /**
674      * This method is called when removing an observed object from the vector.
675      * It updates all the string specific arrays.
676      * @param index The index of the observed object.
677      */

678     synchronized void removeSpecificElementAt(int index) {
679     if (index < 0 || index >= elementCount)
680         return;
681
682         // Update derivedGauge, derivedGaugeTimestamp, and status arrays.
683
//
684
removeElementAt(derivedGauge, index);
685         removeElementAt(derivedGaugeTimestamp, index);
686         removeElementAt(status, index);
687     }
688
689     /**
690      * StringAlarmClock inner class:
691      * This class provides a simple implementation of an alarm clock MBean.
692      * The aim of this MBean is to set up an alarm which wakes up the
693      * string monitor every granularity period.
694      */

695
696     private static class StringAlarmClock extends TimerTask JavaDoc {
697
698     StringMonitor JavaDoc listener = null;
699
700     /*
701      * ------------------------------------------
702      * CONSTRUCTORS
703      * ------------------------------------------
704      */

705
706     public StringAlarmClock(StringMonitor JavaDoc listener) {
707         this.listener = listener;
708     }
709
710     /*
711      * ------------------------------------------
712      * PUBLIC METHODS
713      * ------------------------------------------
714      */

715
716     /**
717      * This method is called by the StringAlarmClock thread when
718      * it is started.
719      */

720     public void run() {
721         if (listener.isActive) {
722         for (int i = 0; i < listener.elementCount; i++) {
723             listener.notifyAlarmClock(i);
724         }
725         }
726     }
727     }
728 }
729
Popular Tags