KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > admin > selfmanagement > event > StatisticMonitor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * StatisticMonitor.java
26  *
27  * Created on July 11, 2005 3:00 PM
28  */

29
30 package com.sun.enterprise.admin.selfmanagement.event;
31
32 import com.sun.jmx.mbeanserver.GetPropertyAction;
33 import java.beans.BeanInfo JavaDoc;
34 import java.beans.Introspector JavaDoc;
35 import java.beans.PropertyDescriptor JavaDoc;
36 import java.io.IOException JavaDoc;
37 import java.lang.reflect.Array JavaDoc;
38 import java.lang.reflect.InvocationTargetException JavaDoc;
39 import java.security.AccessControlContext JavaDoc;
40 import java.security.AccessController JavaDoc;
41 import java.security.PrivilegedAction JavaDoc;
42 import java.util.ArrayList JavaDoc;
43 import java.util.List JavaDoc;
44 import java.util.concurrent.ExecutorService JavaDoc;
45 import java.util.concurrent.Executors JavaDoc;
46 import java.util.concurrent.LinkedBlockingQueue JavaDoc;
47 import java.util.concurrent.ScheduledExecutorService JavaDoc;
48 import java.util.concurrent.ScheduledFuture JavaDoc;
49 import java.util.concurrent.ThreadFactory JavaDoc;
50 import java.util.concurrent.ThreadPoolExecutor JavaDoc;
51 import java.util.concurrent.TimeUnit JavaDoc;
52 import java.util.concurrent.atomic.AtomicInteger JavaDoc;
53 import javax.management.AttributeNotFoundException JavaDoc;
54 import javax.management.InstanceNotFoundException JavaDoc;
55 import javax.management.IntrospectionException JavaDoc;
56 import javax.management.MBeanAttributeInfo JavaDoc;
57 import javax.management.MBeanException JavaDoc;
58 import javax.management.MBeanInfo JavaDoc;
59 import javax.management.MBeanRegistration JavaDoc;
60 import javax.management.MBeanServer JavaDoc;
61 import javax.management.MBeanServerConnection JavaDoc;
62 import javax.management.NotificationBroadcasterSupport JavaDoc;
63 import javax.management.ObjectName JavaDoc;
64 import javax.management.ReflectionException JavaDoc;
65 import com.sun.appserv.management.event.StatisticMonitorNotification;
66 import static com.sun.appserv.management.event.StatisticMonitorNotification.*;
67 import javax.management.openmbean.CompositeData JavaDoc;
68 import java.util.logging.Logger JavaDoc;
69 import java.util.logging.Level JavaDoc;
70 import com.sun.logging.LogDomains;
71
72 /**
73  * Defines the part common to all monitor MBeans.
74  * A statistic monitor MBean monitors values of an attribute common
75  * to a set of observed MBeans. The observed attribute is monitored
76  * at intervals specified by the
77  * granularity period. A gauge value (derived gauge) is derived from the values
78  * of the observed attribute.
79  * Used for JDK version greater than 1.5
80  *
81  * @author Sun Microsystems, Inc
82  */

83 public abstract class StatisticMonitor
84     extends NotificationBroadcasterSupport JavaDoc
85     implements StatisticMonitorMBean, MBeanRegistration JavaDoc {
86
87     /*
88      * ------------------------------------------
89      * PRIVATE VARIABLES
90      * ------------------------------------------
91      */

92
93     /**
94      * List of MBeans to which the attribute to observe belongs.
95      */

96     private List JavaDoc<ObjectName JavaDoc> observedObjects = new ArrayList JavaDoc<ObjectName JavaDoc>();
97
98     /**
99      * Attribute to observe.
100      */

101     private String JavaDoc observedAttribute;
102
103     /**
104      * Monitor granularity period (in milliseconds).
105      * The default value is set to 10 seconds.
106      */

107     private long granularityPeriod = 10000;
108
109     /**
110      * Monitor state.
111      * The default value is set to <CODE>false</CODE>.
112      */

113     private boolean isActive = false;
114
115     /**
116      * Monitor sequence number.
117      * The default value is set to 0.
118      */

119     private long sequenceNumber = 0;
120
121     /**
122      * Complex type attribute flag.
123      * The default value is set to <CODE>false</CODE>.
124      */

125     private boolean isComplexTypeAttribute = false;
126
127     /**
128      * First attribute name extracted from complex type attribute name.
129      */

130     private String JavaDoc firstAttribute;
131
132     /**
133      * Remaining attribute names extracted from complex type attribute name.
134      */

135     private List JavaDoc<String JavaDoc> remainingAttributes = new ArrayList JavaDoc<String JavaDoc>();
136
137     /**
138      * AccessControlContext of the Monitor.start() caller.
139      */

140     private AccessControlContext JavaDoc acc;
141
142     /**
143      * Scheduler Service.
144      */

145     private static final ScheduledExecutorService JavaDoc scheduler =
146         Executors.newSingleThreadScheduledExecutor(
147             new DaemonThreadFactory("Scheduler"));
148
149     /**
150      * Maximum Pool Size
151      */

152     private static final int maximumPoolSize;
153
154     /**
155      * Executor Service.
156      */

157     private static final ExecutorService JavaDoc executor;
158
159     // LOGGER
160
//---------------
161
protected static Logger JavaDoc _logger = LogDomains.getLogger(LogDomains.SELF_MANAGEMENT_LOGGER);
162
163     static {
164         final String JavaDoc maximumPoolSizeSysProp = "jmx.x.monitor.maximum.pool.size";
165         final String JavaDoc maximumPoolSizeStr = (String JavaDoc) AccessController.doPrivileged(
166             new GetPropertyAction(maximumPoolSizeSysProp));
167         if (maximumPoolSizeStr == null ||
168             maximumPoolSizeStr.trim().length() == 0) {
169             maximumPoolSize = 10;
170         } else {
171             int maximumPoolSizeTmp = 10;
172             try {
173                 maximumPoolSizeTmp = Integer.parseInt(maximumPoolSizeStr);
174             } catch (NumberFormatException JavaDoc e) {
175                 if ( _logger.isLoggable(Level.WARNING) ) {
176                     _logger.log(Level.WARNING,"Wrong value for " + maximumPoolSizeSysProp + " system property: " + e);
177                     _logger.log(Level.WARNING,maximumPoolSizeSysProp + " defaults to 10.");
178                 }
179                     maximumPoolSizeTmp = 10;
180             }
181             if (maximumPoolSizeTmp < 1) {
182                 maximumPoolSize = 1;
183             } else {
184                 maximumPoolSize = maximumPoolSizeTmp;
185             }
186         }
187         executor = new ThreadPoolExecutor JavaDoc(
188                 maximumPoolSize,
189                 maximumPoolSize,
190                 60L,
191                 TimeUnit.SECONDS,
192                 new LinkedBlockingQueue JavaDoc<Runnable JavaDoc>(),
193                 new DaemonThreadFactory("Executor"));
194 // See bug 6255405: JMX monitors should remove idle threads
195
// ((ThreadPoolExecutor)executor).allowCoreThreadTimeOut(true);
196
}
197
198     /**
199      * Monitor task to be executed by the Executor Service.
200      */

201     private MonitorTask monitorTask = new MonitorTask();
202
203     /**
204      * Scheduler task to be executed by the Scheduler Service.
205      */

206     private Runnable JavaDoc schedulerTask = new SchedulerTask(monitorTask);
207
208     /**
209      * ScheduledFuture associated to the current scheduler task.
210      */

211     private ScheduledFuture JavaDoc<?> schedulerFuture;
212
213     /*
214      * ------------------------------------------
215      * PROTECTED VARIABLES
216      * ------------------------------------------
217      */

218
219     /**
220      * The amount by which the capacity of the monitor arrays are
221      * automatically incremented when their size becomes greater than
222      * their capacity.
223      */

224     protected final static int capacityIncrement = 16;
225
226     /**
227      * The number of valid components in the vector of observed objects.
228      *
229      * @since.unbundled JMX 1.2
230      */

231     protected int elementCount = 0;
232
233     /**
234      * Monitor errors that have already been notified.
235      * @deprecated equivalent to {@link #alreadyNotifieds}[0].
236      */

237     @Deprecated JavaDoc
238     protected int alreadyNotified = 0;
239
240     /**
241      * <p>Selected monitor errors that have already been notified.</p>
242      *
243      * <p>Each element in this array corresponds to an observed object
244      * in the vector. It contains a bit mask of the flags {@link
245      * #OBSERVED_OBJECT_ERROR_NOTIFIED} etc, indicating whether the
246      * corresponding notification has already been sent for the MBean
247      * being monitored.</p>
248      *
249      * @since.unbundled JMX 1.2
250      */

251     protected int alreadyNotifieds[] = new int[capacityIncrement];
252
253     /**
254      * Reference to the MBean server. This reference is null when the
255      * monitor MBean is not registered in an MBean server. This
256      * reference is initialized before the monitor MBean is registered
257      * in the MBean server.
258      * @see #preRegister(MBeanServer server, ObjectName name)
259      */

260     protected MBeanServer JavaDoc server;
261
262     // Flags defining possible monitor errors.
263
//
264

265     /**
266      * This flag is used to reset the {@link #alreadyNotifieds
267      * alreadyNotifieds} monitor attribute.
268      */

269     protected static final int RESET_FLAGS_ALREADY_NOTIFIED = 0;
270
271     /**
272      * Flag denoting that a notification has occurred after changing
273      * the observed object. This flag is used to check that the new
274      * observed object is registered in the MBean server at the time
275      * of the first notification.
276      */

277     protected static final int OBSERVED_OBJECT_ERROR_NOTIFIED = 1;
278
279     /**
280      * Flag denoting that a notification has occurred after changing
281      * the observed attribute. This flag is used to check that the
282      * new observed attribute belongs to the observed object at the
283      * time of the first notification.
284      */

285     protected static final int OBSERVED_ATTRIBUTE_ERROR_NOTIFIED = 2;
286
287     /**
288      * Flag denoting that a notification has occurred after changing
289      * the observed object or the observed attribute. This flag is
290      * used to check that the observed attribute type is correct
291      * (depending on the monitor in use) at the time of the first
292      * notification.
293      */

294     protected static final int OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED = 4;
295
296     /**
297      * Flag denoting that a notification has occurred after changing
298      * the observed object or the observed attribute. This flag is
299      * used to notify any exception (except the cases described above)
300      * when trying to get the value of the observed attribute at the
301      * time of the first notification.
302      */

303     protected static final int RUNTIME_ERROR_NOTIFIED = 8;
304
305     /*
306      * ------------------------------------------
307      * PACKAGE VARIABLES
308      * ------------------------------------------
309      */

310
311     /**
312      * Flag denoting that a notification has occured after changing
313      * the threshold. This flag is used to notify any exception
314      * related to invalid thresholds settings.
315      */

316     static final int THRESHOLD_ERROR_NOTIFIED = 16;
317
318     /**
319      * Derived gauges.
320      *
321      * <BR>Each element in this array corresponds to an observed
322      * object in the list.
323      */

324     Object JavaDoc derivedGauge[] = new Object JavaDoc[capacityIncrement];
325
326     /**
327      * Derived gauges' timestamps.
328      *
329      * <BR>Each element in this array corresponds to an observed
330      * object in the list.
331      */

332     long derivedGaugeTimestamp[] = new long[capacityIncrement];
333
334     /**
335      * Enumeration used to keep trace of the derived gauge type
336      * in counter and gauge monitors.
337      */

338     enum NumericalType { BYTE, SHORT, INTEGER, LONG, FLOAT, DOUBLE };
339
340     /**
341      * Constant used to initialize all the numeric values.
342      */

343     static final Integer JavaDoc INTEGER_ZERO = new Integer JavaDoc(0);
344
345     /*
346      * ------------------------------------------
347      * PUBLIC METHODS
348      * ------------------------------------------
349      */

350
351     /**
352      * Allows the statistic monitor MBean to perform any operations it needs
353      * before being registered in the MBean server.
354      * <P>
355      * Initializes the reference to the MBean server.
356      *
357      * @param server The MBean server in which the statistic monitor MBean will
358      * be registered.
359      * @param name The object name of the statistic monitor MBean.
360      *
361      * @return The name of the statistic monitor MBean registered.
362      *
363      * @exception Exception
364      */

365     public ObjectName JavaDoc preRegister(MBeanServer JavaDoc server, ObjectName JavaDoc name)
366         throws Exception JavaDoc {
367         if ( _logger.isLoggable(Level.FINER) )
368              _logger.log(Level.FINER,"Initialize reference on the MBean Server");
369         this.server = server;
370         return name;
371     }
372
373     /**
374      * Allows the statistic monitor MBean to perform any operations needed after
375      * having been registered in the MBean server or after the
376      * registration has failed.
377      * <P>
378      * Not used in this context.
379      */

380     public void postRegister (Boolean JavaDoc registrationDone) {
381     }
382
383     /**
384      * Allows the statistic monitor MBean to perform any operations it needs
385      * before being unregistered by the MBean server.
386      * <P>
387      * Stops the statistic monitor.
388      *
389      * @exception Exception
390      */

391     public void preDeregister() throws Exception JavaDoc {
392         if ( _logger.isLoggable(Level.FINER) )
393              _logger.log(Level.FINER,"Stop the statistic monitor");
394         // Stop the StatisticMonitor.
395
//
396
stop();
397     }
398
399     /**
400      * Allows the statistic monitor MBean to perform any operations needed after
401      * having been unregistered by the MBean server.
402      * <P>
403      * Not used in this context.
404      */

405     public void postDeregister() {
406     }
407
408     /**
409      * Starts the statistic monitor.
410      */

411     public abstract void start();
412
413     /**
414      * Stops the statistic monitor.
415      */

416     public abstract void stop();
417
418     // GETTERS AND SETTERS
419
//--------------------
420

421     /**
422      * Returns the object name of the first object in the set of observed
423      * MBeans, or <code>null</code> if there is no such object.
424      *
425      * @return The object being observed.
426      *
427      * @see #setObservedObject(ObjectName)
428      *
429      * @deprecated As of JMX 1.2, replaced by {@link #getObservedObjects}
430      */

431     @Deprecated JavaDoc
432     public synchronized ObjectName JavaDoc getObservedObject() {
433         if (observedObjects.isEmpty()) {
434             return null;
435         } else {
436             return observedObjects.get(0);
437         }
438     }
439
440     /**
441      * Removes all objects from the set of observed objects, and then adds the
442      * specified object.
443      *
444      * @param object The object to observe.
445      * @exception IllegalArgumentException The specified
446      * object is null.
447      *
448      * @see #getObservedObject()
449      *
450      * @deprecated As of JMX 1.2, replaced by {@link #addObservedObject}
451      */

452     @Deprecated JavaDoc
453     public synchronized void setObservedObject(ObjectName JavaDoc object)
454         throws IllegalArgumentException JavaDoc {
455         while (!observedObjects.isEmpty()) {
456             removeObservedObject(observedObjects.get(0));
457         }
458         addObservedObject(object);
459     }
460
461     /**
462      * Adds the specified object in the set of observed MBeans, if this object
463      * is not already present.
464      *
465      * @param object The object to observe.
466      * @exception IllegalArgumentException The specified object is null.
467      *
468      * @since.unbundled JMX 1.2
469      */

470     public synchronized void addObservedObject(ObjectName JavaDoc object)
471         throws IllegalArgumentException JavaDoc {
472
473         if (object == null) {
474             throw new IllegalArgumentException JavaDoc("Null observed object");
475         }
476
477         // Check that the specified object is not already contained.
478
//
479
if (observedObjects.contains(object)) {
480             return;
481         }
482
483         // Add the specified object in the list.
484
//
485
observedObjects.add(object);
486
487         // Update arrays.
488
//
489
if (elementCount >= alreadyNotifieds.length) {
490             alreadyNotifieds = expandArray(alreadyNotifieds);
491             derivedGauge = expandArray(derivedGauge);
492             derivedGaugeTimestamp = expandArray(derivedGaugeTimestamp);
493         }
494         alreadyNotifieds[elementCount] = RESET_FLAGS_ALREADY_NOTIFIED;
495         updateDeprecatedAlreadyNotified();
496         derivedGauge[elementCount] = null;
497         derivedGaugeTimestamp[elementCount] = System.currentTimeMillis();
498
499         // Update other specific arrays.
500
//
501
insertSpecificElementAt(elementCount);
502
503         // Update elementCount.
504
//
505
elementCount++;
506     }
507
508     /**
509      * Removes the specified object from the set of observed MBeans.
510      *
511      * @param object The object to remove.
512      *
513      * @since.unbundled JMX 1.2
514      */

515     public synchronized void removeObservedObject(ObjectName JavaDoc object) {
516         // Check for null object.
517
//
518
if (object == null)
519             return;
520
521         int index = observedObjects.indexOf(object);
522         if (index >= 0) {
523             observedObjects.remove(index);
524             
525             // Update arrays.
526
//
527
removeElementAt(alreadyNotifieds, index);
528             updateDeprecatedAlreadyNotified();
529             removeElementAt(derivedGauge, index);
530             removeElementAt(derivedGaugeTimestamp, index);
531             
532             // Update other specific arrays.
533
//
534
removeSpecificElementAt(index);
535             
536             // Update elementCount.
537
//
538
elementCount--;
539         }
540     }
541
542     /**
543      * Tests whether the specified object is in the set of observed MBeans.
544      *
545      * @param object The object to check.
546      * @return <CODE>true</CODE> if the specified object is present,
547      * <CODE>false</CODE> otherwise.
548      *
549      * @since.unbundled JMX 1.2
550      */

551     public synchronized boolean containsObservedObject(ObjectName JavaDoc object) {
552         return observedObjects.contains(object);
553     }
554
555     /**
556      * Returns an array containing the objects being observed.
557      *
558      * @return The objects being observed.
559      *
560      * @since.unbundled JMX 1.2
561      */

562     public synchronized ObjectName JavaDoc[] getObservedObjects() {
563         return observedObjects.toArray(new ObjectName JavaDoc[0]);
564     }
565
566     /**
567      * Gets the attribute being observed.
568      * <BR>The observed attribute is not initialized by default (set to null).
569      *
570      * @return The attribute being observed.
571      *
572      * @see #setObservedAttribute
573      */

574     public String JavaDoc getObservedAttribute() {
575         return observedAttribute;
576     }
577
578     /**
579      * Sets the attribute to observe.
580      * <BR>The observed attribute is not initialized by default (set to null).
581      *
582      * @param attribute The attribute to observe.
583      * @exception IllegalArgumentException The specified
584      * attribute is null.
585      *
586      * @see #getObservedAttribute
587      */

588     public void setObservedAttribute(String JavaDoc attribute)
589         throws IllegalArgumentException JavaDoc {
590
591         if (attribute == null) {
592             throw new IllegalArgumentException JavaDoc("Null observed attribute");
593         }
594
595         // Update alreadyNotified array.
596
//
597
synchronized(this) {
598             observedAttribute = attribute;
599
600             // Reset the complex type attribute information
601
// such that it is recalculated again.
602
//
603
firstAttribute = null;
604             remainingAttributes.clear();
605             isComplexTypeAttribute = false;
606
607             for (int i = 0; i < elementCount; i++) {
608                 resetAlreadyNotified(i,
609                                      OBSERVED_ATTRIBUTE_ERROR_NOTIFIED |
610                                      OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
611             }
612         }
613     }
614
615     /**
616      * Gets the granularity period (in milliseconds).
617      * <BR>The default value of the granularity period is 10 seconds.
618      *
619      * @return The granularity period value.
620      *
621      * @see #setGranularityPeriod
622      */

623     public synchronized long getGranularityPeriod() {
624         return granularityPeriod;
625     }
626
627     /**
628      * Sets the granularity period (in milliseconds).
629      * <BR>The default value of the granularity period is 10 seconds.
630      *
631      * @param period The granularity period value.
632      * @exception IllegalArgumentException The granularity
633      * period is less than or equal to zero.
634      *
635      * @see #getGranularityPeriod
636      */

637     public synchronized void setGranularityPeriod(long period)
638             throws IllegalArgumentException JavaDoc {
639
640         if (period <= 0) {
641             throw new IllegalArgumentException JavaDoc("Nonpositive granularity " +
642                                                "period");
643         }
644         granularityPeriod = period;
645         
646         // Reschedule the scheduler task if the statistic monitor is active.
647
//
648
if (isActive()) {
649             schedulerFuture.cancel(false);
650             schedulerFuture = scheduler.schedule(schedulerTask,
651                                                  period,
652                                                  TimeUnit.MILLISECONDS);
653         }
654     }
655
656     /**
657      * Tests whether the statistic monitor MBean is active. A statistic monitor MBean is
658      * marked active when the {@link #start start} method is called.
659      * It becomes inactive when the {@link #stop stop} method is
660      * called.
661      *
662      * @return <CODE>true</CODE> if the statistic monitor MBean is active,
663      * <CODE>false</CODE> otherwise.
664      */

665     /* This method must be synchronized so that the monitoring thread will
666        correctly see modifications to the isActive variable. See the MonitorTask
667        action executed by the Scheduled Executor Service. */

668     public synchronized boolean isActive() {
669         return isActive;
670     }
671
672     /*
673      * ------------------------------------------
674      * PACKAGE METHODS
675      * ------------------------------------------
676      */

677
678     /**
679      * Starts the statistic monitor.
680      */

681     void doStart() {
682         if ( _logger.isLoggable(Level.FINER) )
683              _logger.log(Level.FINER,"Start the statistic monitor");
684
685         synchronized(this) {
686             if (isActive()) {
687                 if ( _logger.isLoggable(Level.WARNING) )
688                     _logger.log(Level.WARNING,"The StatisticMonitor is already active");
689                 return;
690             }
691
692             isActive = true;
693
694             // Reset the complex type attribute information
695
// such that it is recalculated again.
696
//
697
firstAttribute = null;
698             remainingAttributes.clear();
699             isComplexTypeAttribute = false;
700
701             // Cache the AccessControlContext of the Monitor.start() caller.
702
// The monitor tasks will be executed within this context.
703
//
704
acc = AccessController.getContext();
705
706             // Start the scheduler.
707
//
708
schedulerFuture = scheduler.schedule(schedulerTask,
709                                                  getGranularityPeriod(),
710                                                  TimeUnit.MILLISECONDS);
711         }
712     }
713
714     /**
715      * Stops the statistic monitor.
716      */

717     void doStop() {
718         if ( _logger.isLoggable(Level.FINER) )
719              _logger.log(Level.FINER,"Stop the StatisticMonitor");
720
721         synchronized(this) {
722             if (!isActive()) {
723                 if ( _logger.isLoggable(Level.WARNING) )
724                     _logger.log(Level.WARNING,"StatisticMonitor is not active");
725                 return;
726             }
727
728             isActive = false;
729
730             // Cancel the scheduler task associated with the scheduler.
731
//
732
schedulerFuture.cancel(false);
733
734             // Reset the AccessControlContext.
735
//
736
acc = null;
737
738             // Reset the complex type attribute information
739
// such that it is recalculated again.
740
//
741
firstAttribute = null;
742             remainingAttributes.clear();
743             isComplexTypeAttribute = false;
744         }
745     }
746
747     /**
748      * Gets the derived gauge of the specified object, if this object is
749      * contained in the set of observed MBeans, or <code>null</code> otherwise.
750      *
751      * @param object the name of the object whose derived gauge is to
752      * be returned.
753      *
754      * @return The derived gauge of the specified object.
755      *
756      * @since 6.0
757      */

758     synchronized Object JavaDoc getDerivedGauge(ObjectName JavaDoc object) {
759         int index = indexOf(object);
760         if (index != -1) {
761             return derivedGauge[index];
762         }
763         else
764             return null;
765     }
766
767     /**
768      * Gets the derived gauge timestamp of the specified object, if
769      * this object is contained in the set of observed MBeans, or
770      * <code>null</code> otherwise.
771      *
772      * @param object the name of the object whose derived gauge
773      * timestamp is to be returned.
774      *
775      * @return The derived gauge timestamp of the specified object.
776      *
777      * @since.unbundled JMX 1.2
778      */

779     synchronized long getDerivedGaugeTimeStamp(ObjectName JavaDoc object) {
780         int index = indexOf(object);
781         if (index != -1)
782             return derivedGaugeTimestamp[index];
783         else
784             return 0;
785     }
786
787     Object JavaDoc getAttribute(MBeanServerConnection JavaDoc mbsc,
788                         ObjectName JavaDoc object,
789                         String JavaDoc attribute)
790         throws AttributeNotFoundException JavaDoc,
791                InstanceNotFoundException JavaDoc,
792                MBeanException JavaDoc,
793                ReflectionException JavaDoc,
794                IOException JavaDoc {
795         // Check for complex type attribute
796
//
797
if (firstAttribute == null) {
798             if (attribute.indexOf('.') != -1) {
799                 MBeanInfo JavaDoc mbi;
800                 try {
801                     mbi = mbsc.getMBeanInfo(object);
802                 } catch (IntrospectionException JavaDoc e) {
803                     throw new IllegalArgumentException JavaDoc(e);
804                 }
805                 MBeanAttributeInfo JavaDoc mbaiArray[] = mbi.getAttributes();
806                 for (MBeanAttributeInfo JavaDoc mbai : mbaiArray) {
807                     if (attribute.equals(mbai.getName())) {
808                         firstAttribute = attribute;
809                         break;
810                     }
811                 }
812                 if (firstAttribute == null) {
813                     String JavaDoc tokens[] = attribute.split("\\.", -1);
814                     firstAttribute = tokens[0];
815                     for (int i = 1; i < tokens.length; i++)
816                         remainingAttributes.add(tokens[i]);
817                     isComplexTypeAttribute = true;
818                 }
819             } else {
820                 firstAttribute = attribute;
821             }
822         }
823         return mbsc.getAttribute(object, firstAttribute);
824     }
825
826     Comparable JavaDoc<?> getComparableFromAttribute(ObjectName JavaDoc object,
827                                              String JavaDoc attribute,
828                                              Object JavaDoc value)
829         throws AttributeNotFoundException JavaDoc {
830         if (isComplexTypeAttribute) {
831             Object JavaDoc v = value;
832             for (String JavaDoc attr : remainingAttributes)
833                 v = introspect(object, attr, v);
834             return (Comparable JavaDoc<?>) v;
835         } else {
836             return (Comparable JavaDoc<?>) value;
837         }
838     }
839
840     Object JavaDoc introspect(ObjectName JavaDoc object,
841                       String JavaDoc attribute,
842                       Object JavaDoc value)
843         throws AttributeNotFoundException JavaDoc {
844         try {
845             if (value.getClass().isArray() && attribute.equals("length")) {
846                 return Array.getLength(value);
847             } else if (value instanceof CompositeData JavaDoc) {
848                 return ((CompositeData JavaDoc) value).get(attribute);
849             } else {
850                 // Java Beans introspection
851
//
852
BeanInfo JavaDoc bi = Introspector.getBeanInfo(value.getClass());
853                 PropertyDescriptor JavaDoc[] pds = bi.getPropertyDescriptors();
854                 for (PropertyDescriptor JavaDoc pd : pds)
855                     if (pd.getName().equals(attribute)) {
856                         return pd.getReadMethod().invoke(value);
857                     }
858                 throw new AttributeNotFoundException JavaDoc(
859                     "Could not find the getter method for the property " +
860                     attribute + " using the Java Beans introspector");
861             }
862         } catch (InvocationTargetException JavaDoc e) {
863             throw new IllegalArgumentException JavaDoc(e);
864         } catch (AttributeNotFoundException JavaDoc e) {
865             throw e;
866         } catch (Exception JavaDoc e) {
867             throw (AttributeNotFoundException JavaDoc)
868                 new AttributeNotFoundException JavaDoc(e.getMessage()).initCause(e);
869         }
870     }
871
872     boolean isComparableTypeValid(ObjectName JavaDoc object,
873                                   String JavaDoc attribute,
874                                   Comparable JavaDoc<?> value) {
875         return true;
876     }
877
878     String JavaDoc buildErrorNotification(ObjectName JavaDoc object,
879                                   String JavaDoc attribute,
880                                   Comparable JavaDoc<?> value) {
881         return null;
882     }
883
884     void onErrorNotification(StatisticMonitorNotification notification) {
885     }
886
887     Comparable JavaDoc<?> getDerivedGaugeFromComparable(ObjectName JavaDoc object,
888                                                 String JavaDoc attribute,
889                                                 Comparable JavaDoc<?> value) {
890         return (Comparable JavaDoc<?>) value;
891     }
892
893     StatisticMonitorNotification buildAlarmNotification(ObjectName JavaDoc object,
894                                                String JavaDoc attribute,
895                                                Comparable JavaDoc<?> value){
896         return null;
897     }
898
899     boolean isThresholdTypeValid(ObjectName JavaDoc object,
900                                  String JavaDoc attribute,
901                                  Comparable JavaDoc<?> value) {
902         return true;
903     }
904
905     static Class JavaDoc<? extends Number JavaDoc> classForType(NumericalType type) {
906         switch (type) {
907             case BYTE:
908                 return Byte JavaDoc.class;
909             case SHORT:
910                 return Short JavaDoc.class;
911             case INTEGER:
912                 return Integer JavaDoc.class;
913             case LONG:
914                 return Long JavaDoc.class;
915             case FLOAT:
916                 return Float JavaDoc.class;
917             case DOUBLE:
918                 return Double JavaDoc.class;
919             default:
920                 throw new IllegalArgumentException JavaDoc(
921                     "Unsupported numerical type");
922         }
923     }
924
925     static boolean isValidForType(Object JavaDoc value, Class JavaDoc<? extends Number JavaDoc> c) {
926         return ((value == INTEGER_ZERO) || c.isInstance(value));
927     }
928
929     /**
930      * Gets the {@link ObjectName} of the object at the specified
931      * index in the list of observed MBeans.
932      * @return The observed object at the specified index.
933      * @exception ArrayIndexOutOfBoundsException If the index is invalid.
934      */

935     synchronized ObjectName JavaDoc getObservedObject(int index)
936         throws ArrayIndexOutOfBoundsException JavaDoc {
937         return observedObjects.get(index);
938     }
939
940     /**
941      * Update the deprecated {@link #alreadyNotified} field.
942      */

943     synchronized void updateDeprecatedAlreadyNotified() {
944         if (elementCount > 0)
945             alreadyNotified = alreadyNotifieds[0];
946         else
947             alreadyNotified = 0;
948     }
949
950     /**
951      * Set the given bits in the given element of {@link #alreadyNotifieds}.
952      * Ensure the deprecated {@link #alreadyNotified} field is updated
953      * if appropriate.
954      */

955     synchronized void setAlreadyNotified(int index, int mask) {
956         alreadyNotifieds[index] |= mask;
957         if (index == 0)
958             updateDeprecatedAlreadyNotified();
959     }
960
961     /**
962      * Reset the given bits in the given element of {@link #alreadyNotifieds}.
963      * Ensure the deprecated {@link #alreadyNotified} field is updated
964      * if appropriate.
965      */

966     synchronized void resetAlreadyNotified(int index, int mask) {
967         alreadyNotifieds[index] &= ~mask;
968         if (index == 0)
969             updateDeprecatedAlreadyNotified();
970     }
971
972     synchronized boolean alreadyNotified(int index, int mask) {
973         return ((alreadyNotifieds[index] & mask) != 0);
974     }
975
976     /**
977      * Reset all bits in the given element of {@link #alreadyNotifieds}.
978      * Ensure the deprecated {@link #alreadyNotified} field is updated
979      * if appropriate.
980      */

981     synchronized void resetAllAlreadyNotified(int index) {
982         alreadyNotifieds[index] = RESET_FLAGS_ALREADY_NOTIFIED;
983         if (index == 0)
984             updateDeprecatedAlreadyNotified();
985     }
986
987     /**
988      * Expands the specified int array.
989      */

990     int[] expandArray(int[] array) {
991         int[] newArray = new int[array.length + capacityIncrement];
992         System.arraycopy(array, 0, newArray, 0, array.length);
993         return newArray;
994     }
995
996     /**
997      * Expands the specified long array.
998      */

999     long[] expandArray(long[] array) {
1000        long[] newArray = new long[array.length + capacityIncrement];
1001        System.arraycopy(array, 0, newArray, 0, array.length);
1002        return newArray;
1003    }
1004
1005    /**
1006     * Expands the specified boolean array.
1007     */

1008    boolean[] expandArray(boolean[] array) {
1009        boolean[] newArray = new boolean[array.length + capacityIncrement];
1010        System.arraycopy(array, 0, newArray, 0, array.length);
1011        return newArray;
1012    }
1013
1014    /**
1015     * Expands the specified Number array.
1016     */

1017    Number JavaDoc[] expandArray(Number JavaDoc[] array) {
1018        Number JavaDoc[] newArray = new Number JavaDoc[array.length + capacityIncrement];
1019        System.arraycopy(array, 0, newArray, 0, array.length);
1020        return newArray;
1021    }
1022
1023    /**
1024     * Expands the specified String array.
1025     */

1026    String JavaDoc[] expandArray(String JavaDoc[] array) {
1027        String JavaDoc[] newArray = new String JavaDoc[array.length + capacityIncrement];
1028        System.arraycopy(array, 0, newArray, 0, array.length);
1029        return newArray;
1030    }
1031
1032    /**
1033     * Expands the specified NumericalType array.
1034     */

1035    NumericalType[] expandArray(NumericalType[] array) {
1036        NumericalType[] newArray =
1037            new NumericalType[array.length + capacityIncrement];
1038        System.arraycopy(array, 0, newArray, 0, array.length);
1039        return newArray;
1040    }
1041
1042    /**
1043     * Expands the specified Object array.
1044     */

1045    Object JavaDoc[] expandArray(Object JavaDoc[] array) {
1046        Object JavaDoc[] newArray = new Object JavaDoc[array.length + capacityIncrement];
1047        System.arraycopy(array, 0, newArray, 0, array.length);
1048        return newArray;
1049    }
1050
1051    /**
1052     * Removes the component at the specified index from the specified
1053     * int array.
1054     */

1055    synchronized void removeElementAt(int[] array, int index) {
1056        if (index < 0 || index >= elementCount)
1057            return;
1058        int j = elementCount - index - 1;
1059        if (j > 0) {
1060            System.arraycopy(array, index + 1, array, index, j);
1061        }
1062    }
1063
1064    /**
1065     * Removes the component at the specified index from the specified
1066     * long array.
1067     */

1068    synchronized void removeElementAt(long[] array, int index) {
1069        if (index < 0 || index >= elementCount)
1070            return;
1071        int j = elementCount - index - 1;
1072        if (j > 0) {
1073            System.arraycopy(array, index + 1, array, index, j);
1074        }
1075    }
1076
1077    /**
1078     * Removes the component at the specified index from the specified
1079     * boolean array.
1080     */

1081    synchronized void removeElementAt(boolean[] array, int index) {
1082        if (index < 0 || index >= elementCount)
1083            return;
1084        int j = elementCount - index - 1;
1085        if (j > 0) {
1086            System.arraycopy(array, index + 1, array, index, j);
1087        }
1088    }
1089
1090    /**
1091     * Removes the component at the specified index from the specified
1092     * Object array.
1093     */

1094    synchronized void removeElementAt(Object JavaDoc[] array, int index) {
1095        if (index < 0 || index >= elementCount)
1096            return;
1097        int j = elementCount - index - 1;
1098        if (j > 0) {
1099            System.arraycopy(array, index + 1, array, index, j);
1100        }
1101        array[elementCount - 1] = null;
1102    }
1103
1104    /**
1105     * Searches for the first occurence of the given argument, testing
1106     * for equality using the equals method.
1107     */

1108    synchronized int indexOf(ObjectName JavaDoc object) {
1109        return observedObjects.indexOf(object);
1110    }
1111
1112    /**
1113     * This method is overridden by the specific monitor classes
1114     * (Counter, Gauge and String). It updates all the specific
1115     * arrays after adding a new observed object in the list.
1116     *
1117     * The method is not abstract so that this class can be subclassed
1118     * by classes outside this package.
1119     */

1120    void insertSpecificElementAt(int index) {}
1121
1122    /**
1123     * This method is overridden by the specific monitor classes
1124     * (Counter, Gauge and String). It updates all the specific
1125     * arrays after removing an observed object from the vector.
1126     *
1127     * The method is not abstract so that this class can be subclassed
1128     * by classes outside this package.
1129     */

1130    void removeSpecificElementAt(int index) {}
1131
1132    /*
1133     * ------------------------------------------
1134     * PRIVATE METHODS
1135     * ------------------------------------------
1136     */

1137
1138    /**
1139     * This method is used by the monitor MBean to create and send a
1140     * monitor notification to all the listeners registered for this
1141     * kind of notification.
1142     *
1143     * @param type The notification type.
1144     * @param timeStamp The notification emission date.
1145     * @param msg The notification message.
1146     * @param derGauge The derived gauge.
1147     * @param trigger The threshold/string (depending on the monitor
1148     * type) that triggered off the notification.
1149     * @param object The ObjectName of the observed object that triggered
1150     * off the notification.
1151     * @param onError Flag indicating if this monitor notification is
1152     * an error notification or an alarm notification.
1153     */

1154    private void sendNotification(String JavaDoc type, long timeStamp, String JavaDoc msg,
1155                                  Object JavaDoc derGauge, Object JavaDoc trigger,
1156                                  ObjectName JavaDoc object, boolean onError) {
1157        if ( _logger.isLoggable(Level.FINER) )
1158             _logger.log(Level.FINER,"send notification: " +
1159                  "\n\tNotification observed object = " + object +
1160                  "\n\tNotification observed attribute = " + observedAttribute +
1161                  "\n\tNotification derived gauge = " + derGauge);
1162
1163        long seqno;
1164        synchronized (this) {
1165            seqno = sequenceNumber++;
1166        }
1167
1168        StatisticMonitorNotification mn =
1169            new StatisticMonitorNotification(type,
1170                                    this,
1171                                    seqno,
1172                                    timeStamp,
1173                                    msg,
1174                                    object,
1175                                    observedAttribute,
1176                                    derGauge,
1177                                    trigger);
1178        if (onError)
1179            onErrorNotification(mn);
1180        sendNotification(mn);
1181    }
1182
1183    /**
1184     * This method is called by the monitor each time
1185     * the granularity period has been exceeded.
1186     * @param index The index of the observed object.
1187     */

1188    private void monitor(int index) {
1189
1190        String JavaDoc notifType = null;
1191        String JavaDoc msg = null;
1192        Object JavaDoc derGauge = null;
1193        Object JavaDoc trigger = null;
1194        ObjectName JavaDoc object = null;
1195        Comparable JavaDoc<?> value = null;
1196        StatisticMonitorNotification alarm = null;
1197
1198        synchronized(this) {
1199            if (!isActive())
1200                return;
1201
1202            // Check that neither the observed object nor the
1203
// observed attribute are null. If the observed
1204
// object or observed attribute is null, this means
1205
// that the monitor started before a complete
1206
// initialization and nothing is done.
1207
//
1208
object = getObservedObject(index);
1209            String JavaDoc attribute = getObservedAttribute();
1210            if (object == null || attribute == null) {
1211                return;
1212            }
1213
1214            // Check that the observed object is registered in the
1215
// MBean server and that the observed attribute
1216
// belongs to the observed object.
1217
//
1218
Object JavaDoc attributeValue = null;
1219            try {
1220                attributeValue = getAttribute(server, object, attribute);
1221                if (attributeValue == null)
1222                    if (alreadyNotified(index,
1223                                        OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
1224                        return;
1225                    else {
1226                        notifType = OBSERVED_ATTRIBUTE_TYPE_ERROR;
1227                        setAlreadyNotified(
1228                                  index,
1229                                  OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
1230                        msg = "The observed attribute value is null.";
1231                        if ( _logger.isLoggable(Level.WARNING) )
1232                            _logger.log(Level.WARNING,msg);
1233                    }
1234            } catch (NullPointerException JavaDoc np_ex) {
1235                if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1236                    return;
1237                else {
1238                    notifType = RUNTIME_ERROR;
1239                    setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1240                    msg =
1241                        "The monitor must be registered in the MBean " +
1242                        "server or an MBeanServerConnection must be " +
1243                        "explicitly supplied.";
1244                    if ( _logger.isLoggable(Level.WARNING) ) {
1245                        _logger.log(Level.WARNING,msg);
1246                        _logger.log(Level.WARNING, np_ex.toString());
1247                    }
1248                }
1249            } catch (InstanceNotFoundException JavaDoc inf_ex) {
1250                if (alreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED))
1251                    return;
1252                else {
1253                    notifType = OBSERVED_OBJECT_ERROR;
1254                    setAlreadyNotified(index, OBSERVED_OBJECT_ERROR_NOTIFIED);
1255                    msg =
1256                        "The observed object must be accessible in " +
1257                        "the MBeanServerConnection.";
1258                    if ( _logger.isLoggable(Level.WARNING) ) {
1259                        _logger.log(Level.WARNING,msg);
1260                        _logger.log(Level.WARNING, inf_ex.toString());
1261                    }
1262                }
1263            } catch (AttributeNotFoundException JavaDoc anf_ex) {
1264                if (alreadyNotified(index, OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
1265                    return;
1266                else {
1267                    notifType = OBSERVED_ATTRIBUTE_ERROR;
1268                    setAlreadyNotified(index,
1269                                       OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
1270                    msg =
1271                        "The observed attribute must be accessible in " +
1272                        "the observed object.";
1273                    if ( _logger.isLoggable(Level.WARNING) ) {
1274                        _logger.log(Level.WARNING,msg);
1275                        _logger.log(Level.WARNING, anf_ex.toString());
1276                    }
1277
1278                }
1279            } catch (MBeanException JavaDoc mb_ex) {
1280                if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1281                    return;
1282                else {
1283                    notifType = RUNTIME_ERROR;
1284                    setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1285                    msg = mb_ex.getMessage();
1286                    if ( _logger.isLoggable(Level.WARNING) ) {
1287                        _logger.log(Level.WARNING,msg);
1288                        _logger.log(Level.WARNING, mb_ex.toString());
1289                    }
1290                }
1291            } catch (ReflectionException JavaDoc ref_ex) {
1292                if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED)) {
1293                    return;
1294                } else {
1295                    notifType = RUNTIME_ERROR;
1296                    setAlreadyNotified(index,
1297                                       RUNTIME_ERROR_NOTIFIED);
1298                    msg = ref_ex.getMessage();
1299                    if ( _logger.isLoggable(Level.WARNING) ) {
1300                        _logger.log(Level.WARNING,msg);
1301                        _logger.log(Level.WARNING, ref_ex.toString());
1302                    }
1303                }
1304            } catch (IOException JavaDoc io_ex) {
1305                if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1306                    return;
1307                else {
1308                    notifType = RUNTIME_ERROR;
1309                    setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1310                    msg = io_ex.getMessage();
1311                    if ( _logger.isLoggable(Level.WARNING) ) {
1312                        _logger.log(Level.WARNING,msg);
1313                        _logger.log(Level.WARNING, io_ex.toString());
1314                    }
1315                }
1316            } catch (RuntimeException JavaDoc rt_ex) {
1317                if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1318                    return;
1319                else {
1320                    notifType = RUNTIME_ERROR;
1321                    setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1322                    msg = rt_ex.getMessage();
1323                    if ( _logger.isLoggable(Level.WARNING) ) {
1324                        _logger.log(Level.WARNING,msg);
1325                        _logger.log(Level.WARNING, rt_ex.toString());
1326                    }
1327                }
1328            }
1329
1330            // Derive a Comparable object from the ObservedAttribute value
1331
// if the type of the ObservedAttribute value is a complex type.
1332
//
1333
if (msg == null) {
1334                try {
1335                    value = getComparableFromAttribute(object,
1336                                                       attribute,
1337                                                       attributeValue);
1338                } catch (AttributeNotFoundException JavaDoc e) {
1339                    if (alreadyNotified(index,
1340                                        OBSERVED_ATTRIBUTE_ERROR_NOTIFIED))
1341                        return;
1342                    else {
1343                        notifType = OBSERVED_ATTRIBUTE_ERROR;
1344                        setAlreadyNotified(index,
1345                                           OBSERVED_ATTRIBUTE_ERROR_NOTIFIED);
1346                        msg =
1347                            "The observed attribute must be accessible in " +
1348                            "the observed object.";
1349                        if ( _logger.isLoggable(Level.WARNING) ) {
1350                            _logger.log(Level.WARNING,msg);
1351                            _logger.log(Level.WARNING, e.toString());
1352                        }
1353
1354                    }
1355                } catch (RuntimeException JavaDoc e) {
1356                    if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1357                        return;
1358                    else {
1359                        notifType = RUNTIME_ERROR;
1360                        setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1361                        msg = e.getMessage();
1362                        if ( _logger.isLoggable(Level.WARNING) ) {
1363                            _logger.log(Level.WARNING,msg);
1364                            _logger.log(Level.WARNING, e.toString());
1365                        }
1366                    }
1367                }
1368            }
1369
1370            // Check that the observed attribute type is supported by this
1371
// monitor.
1372
//
1373
if (msg == null) {
1374                if (!isComparableTypeValid(object, attribute, value)) {
1375                    if (alreadyNotified(index,
1376                                        OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED))
1377                        return;
1378                    else {
1379                        notifType = OBSERVED_ATTRIBUTE_TYPE_ERROR;
1380                        setAlreadyNotified(
1381                                  index,
1382                                  OBSERVED_ATTRIBUTE_TYPE_ERROR_NOTIFIED);
1383                        msg = "The observed attribute type is not valid.";
1384                        if ( _logger.isLoggable(Level.WARNING) ) {
1385                            _logger.log(Level.WARNING,msg);
1386                        }
1387                    }
1388                }
1389            }
1390
1391            // Check that threshold type is supported by this monitor.
1392
//
1393
if (msg == null) {
1394                if (!isThresholdTypeValid(object, attribute, value)) {
1395                    if (alreadyNotified(index, THRESHOLD_ERROR_NOTIFIED))
1396                        return;
1397                    else {
1398                        notifType = THRESHOLD_ERROR;
1399                        setAlreadyNotified(index, THRESHOLD_ERROR_NOTIFIED);
1400                        msg = "The threshold type is not valid.";
1401                        if ( _logger.isLoggable(Level.WARNING) ) {
1402                            _logger.log(Level.WARNING,msg);
1403                        }
1404                    }
1405                }
1406            }
1407
1408            // Let someone subclassing the monitor to perform additional
1409
// monitor consistency checks and report errors if necessary.
1410
//
1411
if (msg == null) {
1412                msg = buildErrorNotification(object, attribute, value);
1413                if (msg != null) {
1414                    if (alreadyNotified(index, RUNTIME_ERROR_NOTIFIED))
1415                        return;
1416                    else {
1417                        notifType = RUNTIME_ERROR;
1418                        setAlreadyNotified(index, RUNTIME_ERROR_NOTIFIED);
1419                        if ( _logger.isLoggable(Level.WARNING) ) {
1420                            _logger.log(Level.WARNING,msg);
1421                        }
1422                    }
1423                }
1424            }
1425
1426            // If no errors were found then clear all error flags and
1427
// let the monitor decide if a notification must be sent.
1428
//
1429
if (msg == null) {
1430                // Clear all already notified flags.
1431
//
1432
resetAllAlreadyNotified(index);
1433
1434                // Get derived gauge from comparable value.
1435
//
1436
derGauge = getDerivedGaugeFromComparable(object,
1437                                                         attribute,
1438                                                         value);
1439                derivedGauge[index] = derGauge;
1440                derivedGaugeTimestamp[index] = System.currentTimeMillis();
1441
1442                // Check if an alarm must be fired.
1443
//
1444
alarm = buildAlarmNotification(object,
1445                                               attribute,
1446                                               (Comparable JavaDoc<?>) derGauge);
1447            }
1448        }
1449
1450        // Notify monitor errors
1451
//
1452
if (msg != null)
1453            sendNotification(notifType,
1454                             System.currentTimeMillis(),
1455                             msg,
1456                             derGauge,
1457                             trigger,
1458                             object,
1459                             true);
1460
1461        // Notify monitor alarms
1462
//
1463
if (alarm != null && alarm.getType() != null) {
1464            sendNotification(alarm.getType(),
1465                             System.currentTimeMillis(),
1466                             alarm.getMessage(),
1467                             derGauge,
1468                             alarm.getTrigger(),
1469                             object,
1470                             false);
1471        }
1472    }
1473
1474    /**
1475     * SchedulerTask nested class: This class implements the Runnable interface.
1476     *
1477     * The SchedulerTask is executed periodically with a given fixed delay by
1478     * the Scheduled Executor Service.
1479     */

1480    private static class SchedulerTask implements Runnable JavaDoc {
1481
1482        private Runnable JavaDoc task = null;
1483
1484        /*
1485         * ------------------------------------------
1486         * CONSTRUCTORS
1487         * ------------------------------------------
1488         */

1489
1490        public SchedulerTask(Runnable JavaDoc task) {
1491            this.task = task;
1492        }
1493
1494        /*
1495         * ------------------------------------------
1496         * PUBLIC METHODS
1497         * ------------------------------------------
1498         */

1499
1500        public void run() {
1501            executor.submit(task);
1502        }
1503    }
1504
1505    /**
1506     * MonitorTask nested class: This class implements the Runnable interface.
1507     *
1508     * The MonitorTask is executed periodically with a given fixed delay by the
1509     * Scheduled Executor Service.
1510     */

1511    private class MonitorTask implements Runnable JavaDoc {
1512
1513        /*
1514         * ------------------------------------------
1515         * CONSTRUCTORS
1516         * ------------------------------------------
1517         */

1518
1519        public MonitorTask() {
1520        }
1521
1522        /*
1523         * ------------------------------------------
1524         * PUBLIC METHODS
1525         * ------------------------------------------
1526         */

1527
1528        public void run() {
1529            synchronized(StatisticMonitor.this) {
1530                AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
1531                    public Object JavaDoc run() {
1532                        if (StatisticMonitor.this.isActive())
1533                            for (int i = 0; i < StatisticMonitor.this.elementCount; i++)
1534                                StatisticMonitor.this.monitor(i);
1535                        return null;
1536                    }
1537                }, StatisticMonitor.this.acc);
1538                StatisticMonitor.this.schedulerFuture =
1539                    scheduler.schedule(StatisticMonitor.this.schedulerTask,
1540                                       StatisticMonitor.this.getGranularityPeriod(),
1541                                       TimeUnit.MILLISECONDS);
1542            }
1543        }
1544    }
1545
1546    /**
1547     * Daemon thread factory used by the monitor executors.
1548     * <P>
1549     * This factory creates all new threads used by an Executor in
1550     * the same ThreadGroup. If there is a SecurityManager, it uses
1551     * the group of System.getSecurityManager(), else the group of
1552     * the thread instantiating this DaemonThreadFactory. Each new
1553     * thread is created as a daemon thread with priority
1554     * Thread.NORM_PRIORITY. New threads have names accessible via
1555     * Thread.getName() of "JMX Monitor <pool-name> Pool [Thread-M]",
1556     * where M is the sequence number of the thread created by this
1557     * factory.
1558     */

1559    private static class DaemonThreadFactory implements ThreadFactory JavaDoc {
1560        final ThreadGroup JavaDoc group;
1561        final AtomicInteger JavaDoc threadNumber = new AtomicInteger JavaDoc(1);
1562        final String JavaDoc namePrefix;
1563        final String JavaDoc nameSuffix = "]";
1564
1565        public DaemonThreadFactory(String JavaDoc poolName) {
1566            SecurityManager JavaDoc s = System.getSecurityManager();
1567            group = (s != null) ? s.getThreadGroup() :
1568                                  Thread.currentThread().getThreadGroup();
1569            namePrefix = "JMX Monitor " + poolName + " Pool [Thread-";
1570        }
1571
1572        public Thread JavaDoc newThread(Runnable JavaDoc r) {
1573            Thread JavaDoc t = new Thread JavaDoc(group,
1574                                  r,
1575                                  namePrefix +
1576                                  threadNumber.getAndIncrement() +
1577                                  nameSuffix,
1578                                  0);
1579            t.setDaemon(true);
1580            if (t.getPriority() != Thread.NORM_PRIORITY)
1581                t.setPriority(Thread.NORM_PRIORITY);
1582            return t;
1583        }
1584    }
1585}
1586
Popular Tags