KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > enterprise > management > monitor > MonitoringStatsImplBase


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 package com.sun.enterprise.management.monitor;
25
26 import java.util.Map JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.Set JavaDoc;
29 import java.util.HashSet JavaDoc;
30 import java.util.Iterator JavaDoc;
31 import java.util.Collections JavaDoc;
32 import java.io.Serializable JavaDoc;
33
34 import java.lang.reflect.Method JavaDoc;
35 import java.lang.reflect.Proxy JavaDoc;
36 import java.lang.reflect.InvocationHandler JavaDoc;
37
38 import javax.management.ObjectName JavaDoc;
39 import javax.management.MBeanInfo JavaDoc;
40 import javax.management.MBeanAttributeInfo JavaDoc;
41 import javax.management.AttributeNotFoundException JavaDoc;
42 import javax.management.openmbean.CompositeDataSupport JavaDoc;
43 import javax.management.openmbean.OpenDataException JavaDoc;
44 import javax.management.InstanceNotFoundException JavaDoc;
45
46 import javax.management.j2ee.statistics.Statistic JavaDoc;
47 import javax.management.j2ee.statistics.*;
48 import com.sun.appserv.management.j2ee.statistics.StatsImpl;
49
50 import com.sun.appserv.management.base.AMXDebug;
51
52 import com.sun.appserv.management.monitor.MonitoringStats;
53
54 import com.sun.appserv.management.util.j2ee.J2EEUtil;
55 import com.sun.appserv.management.util.misc.ClassUtil;
56 import com.sun.appserv.management.util.jmx.JMXUtil;
57 import com.sun.appserv.management.util.misc.MapUtil;
58 import com.sun.appserv.management.util.misc.GSetUtil;
59 import com.sun.appserv.management.util.misc.StringUtil;
60 import com.sun.appserv.management.util.misc.ExceptionUtil;
61 import com.sun.appserv.management.util.misc.ArrayUtil;
62 import com.sun.appserv.management.j2ee.statistics.MapStatistic;
63 import com.sun.appserv.management.j2ee.statistics.MapStatisticImpl;
64 import com.sun.appserv.management.j2ee.statistics.StatisticImpl;
65 import com.sun.appserv.management.j2ee.statistics.StatisticFactory;
66
67 import com.sun.appserv.management.util.jmx.AttributeNameMapper;
68 import com.sun.appserv.management.util.jmx.AttributeNameMapperImpl;
69
70 import com.sun.enterprise.management.support.Delegate;
71 import com.sun.enterprise.management.support.DelegateToMBeanDelegate;
72
73 /**
74     Base implementation class for Monitoring MBeans that provide Stats.
75 */

76 public abstract class MonitoringStatsImplBase extends MonitoringImplBase
77 {
78     private MBeanInfo JavaDoc mMBeanInfo;
79     private final AttributeNameMapper mFieldNameMapper;
80     private final AttributeNameMapper mStatisticNameMapper;
81     
82     private Set JavaDoc<String JavaDoc> mStatisticNames;
83     
84         public
85     MonitoringStatsImplBase( final String JavaDoc j2eeType, final Delegate delegate )
86     {
87         super( j2eeType, delegate );
88         
89         mMBeanInfo = null;
90         
91         mFieldNameMapper = new AttributeNameMapperImpl();
92         mStatisticNameMapper = new AttributeNameMapperImpl();
93         
94         mStatisticNames = null;
95     }
96
97         public
98     MonitoringStatsImplBase( final String JavaDoc j2eeType )
99     {
100         this( j2eeType, null );
101     }
102
103     /**
104         The interface available in underlying "old" MBean.
105      */

106     private static interface OldMonitoringMBean
107     {
108         public String JavaDoc[] getStatisticNames();
109         public Statistic JavaDoc[] getStatistics();
110     }
111     
112     /**
113         Get the underlying Delegate. Note that this proxy
114         may not actually implement all the routines in MonitoringStats;
115         we use only a few however, so that is OK.
116      */

117         protected OldMonitoringMBean
118     getMonitoringMBeanDelegate()
119     {
120         return (OldMonitoringMBean)getDelegateProxy(OldMonitoringMBean.class);
121     }
122     
123     /**
124         The prefix of a getter method.
125      */

126     private static final String JavaDoc GET = "get";
127     
128     /**
129         The delimiter between a Statistic name and its field value when
130         exposed as an Attribute.
131      */

132     private static final String JavaDoc STATISTIC_DELIM = "_";
133     
134     
135     static private final Set JavaDoc<String JavaDoc> IGNORE_MISSING_SUFFIXES =
136         Collections.unmodifiableSet( GSetUtil.newSet( new String JavaDoc[]
137         {
138             "current", "count", "description", "name",
139             "lowwatermark", "highwatermark", "unit",
140             "lastsampletime", "starttime",
141             "lowerbound", "upperbound",
142             "maxtime", "mintime", "totaltime", "average",
143             
144             "children",
145         }));
146         
147     /**
148         We don't map any of the Attributes derived from statistics.
149      */

150         protected void
151     handleMissingOriginals( final Set JavaDoc<String JavaDoc> missingOriginals )
152     {
153         final Set JavaDoc<String JavaDoc> stillMissing = new HashSet JavaDoc<String JavaDoc>();
154         
155         for( final String JavaDoc name : missingOriginals )
156         {
157             final int idx = name.lastIndexOf( '-' );
158             final String JavaDoc suffix = name.substring( idx + 1, name.length() );
159             
160             if ( ! IGNORE_MISSING_SUFFIXES.contains( suffix ) )
161             {
162                 stillMissing.add( name );
163             }
164         }
165         
166         super.handleMissingOriginals( stillMissing );
167     }
168     
169     
170         protected final AttributeNameMapper
171     getFieldNameMapper()
172     {
173         return( mFieldNameMapper );
174     }
175         protected final AttributeNameMapper
176     getStatisticNameMapper()
177     {
178         return( mStatisticNameMapper );
179     }
180
181
182     protected final static String JavaDoc[] STD_FIELDS = new String JavaDoc[]
183     {
184         // none, by default
185
};
186     
187     /**
188         Initialize the field-name mapping for any names that required
189         special conversion.
190      */

191         protected void
192     initFieldNameMapper()
193     {
194         final AttributeNameMapper m = getFieldNameMapper();
195         
196         assert( (STD_FIELDS.length % 2) == 0 );
197         for( int i = 0; i < STD_FIELDS.length - 1; ++i )
198         {
199             m.addMapping( STD_FIELDS[ i ], STD_FIELDS[ i + 1 ] );
200         }
201     }
202     
203     
204     protected final static String JavaDoc[] STD_STATISTICS = new String JavaDoc[]
205     {
206         "id", "ID",
207         "Id", "ID",
208     };
209     
210     /**
211         Initialize the Statistic-name mapping for any names that required
212         special conversion.
213      */

214         protected void
215     initStatisticNameMapper()
216     {
217         final AttributeNameMapper m = getStatisticNameMapper();
218         
219         final String JavaDoc[] mappings = STD_STATISTICS;
220         
221         for( int i = 0; i < mappings.length -1; ++i )
222         {
223             m.addMapping( mappings[ i ], mappings[ i + 1 ] );
224         }
225     }
226     
227     /**
228         Get an Attribute value by looking for a corresponding Statistic.
229         
230         @param statisticName as seen in the MBeanInfo of this MBean
231         @param fieldName as seen in the MBeanInfo of this MBean
232      */

233         protected Object JavaDoc
234     getAttributeFromStatistic(
235         final String JavaDoc statisticName,
236         final String JavaDoc fieldName )
237         throws AttributeNotFoundException JavaDoc
238     {
239         try
240         {
241             final Statistic JavaDoc s = getStatistic( statisticName );
242             assert( s instanceof MapStatistic );
243             
244             final String JavaDoc methodName = JMXUtil.GET + fieldName;
245             final Method JavaDoc m = s.getClass().getMethod( methodName, (Class JavaDoc[])null);
246             
247             //final MapStatisticImpl ms = new MapStatisticImpl( s );
248
final Object JavaDoc result = m.invoke( s, (Object JavaDoc[])null );
249             return( result );
250         }
251         catch( Exception JavaDoc e )
252         {
253             debug( "getAttributeFromStatistic: exception getting statistic " +
254                 statisticName + e + "\n" +
255                 ExceptionUtil.getStackTrace( ExceptionUtil.getRootCause( e ) ) );
256             throw new AttributeNotFoundException JavaDoc( statisticName );
257         }
258     }
259     
260     /**
261         Handle getting of artificial Attributes which are derived from Statistics.
262         
263         @param name the Attribute name
264      */

265         protected Object JavaDoc
266     getAttributeManually( final String JavaDoc name )
267         throws AttributeNotFoundException JavaDoc
268     {
269         final int idx = name.indexOf( STATISTIC_DELIM );
270         
271         Object JavaDoc result = null;
272         
273         if ( idx > 0 )
274         {
275             // Attribute name is of the form <statistic-name>_<field-name>
276
final String JavaDoc statisticName = name.substring( 0, idx );
277             final String JavaDoc fieldName = name.substring( idx + 1, name.length() );
278             
279             result = getAttributeFromStatistic( statisticName, fieldName );
280         }
281         else
282         {
283             result = super.getAttributeManually( name );
284         }
285         
286         return( result );
287     }
288     
289     /**
290         A bug in the underlying MBeans is present.
291      */

292     private static final boolean BUG_STATISTIC_NAMES = true;
293     
294     
295         private String JavaDoc[]
296     originalToDerivedStatisticNames( final String JavaDoc[] names )
297     {
298         final String JavaDoc[] derived = new String JavaDoc[ names.length ];
299         
300         for( int i = 0; i < names.length; ++i )
301         {
302             derived[ i ] = originalToDerivedStatisticName( names[ i ] );
303         }
304         
305         return( derived );
306     }
307     
308     
309         private void
310     checkUnderlyingMBean()
311     {
312         assert( BUG_STATISTIC_NAMES );
313                 
314         if ( BUG_STATISTIC_NAMES /* && ! getJ2EEType().equals( "X-BeanMethodMonitor" ) */ )
315         {
316             final Delegate delegate = getDelegate();
317             
318             if ( delegate == null) return;
319             
320             final String JavaDoc[] claimedNames = getMonitoringMBeanDelegate().getStatisticNames();
321             if ( claimedNames == null )
322             {
323                 throw new RuntimeException JavaDoc( "Delegate " +
324                     " used by AMX MBean " + getObjectName() +
325                     " returned null StatisticNames array" );
326             }
327             else if ( claimedNames.length == 0 )
328             {
329                 throw new RuntimeException JavaDoc( "Delegate " +
330                     " used by AMX MBean " + getObjectName() +
331                     " returned empty StatisticNames array" );
332             }
333
334             final Statistic JavaDoc[] statistics = getMonitoringMBeanDelegate().getStatistics();
335             if ( statistics == null )
336             {
337                 throw new RuntimeException JavaDoc( "Delegate " +
338                     " used by AMX MBean " + getObjectName() +
339                     " returned null Statistics array" );
340             }
341             else if ( statistics.length == 0 )
342             {
343                 throw new RuntimeException JavaDoc( "Delegate " +
344                     " used by AMX MBean " + getObjectName() +
345                     " returned empty Statistics array" );
346             }
347                
348             try
349             {
350                 final Set JavaDoc<String JavaDoc> actualSet = new HashSet JavaDoc<String JavaDoc>();
351                 
352                 final String JavaDoc[] namesFromGetStatistics = new String JavaDoc[ statistics.length ];
353                 
354                 for( int i = 0; i < statistics.length; ++i )
355                 {
356                     final String JavaDoc name = StringUtil.upperCaseFirstLetter( statistics[ i ].getName() );
357                     namesFromGetStatistics[ i ] = name;
358                     
359                     if ( ! actualSet.contains( name ) )
360                     {
361                         actualSet.add( name );
362                     }
363                     else
364                     {
365                         logWarning( "MBean delegate " +
366                             " for " + getObjectName() +
367                             " returns Statistic with duplicate name: " + name +
368                             " from getStatistics() call.\n" );
369                     }
370                 }
371                 
372                 final Set JavaDoc<String JavaDoc> claimedSet = GSetUtil.newStringSet( claimedNames );
373                 if ( ! claimedSet.equals( actualSet ) )
374                 {
375                     final Set JavaDoc<String JavaDoc> missing = new HashSet JavaDoc<String JavaDoc>( claimedSet );
376                     missing.removeAll( actualSet );
377                     
378                     // assume workarounds are in place
379
final String JavaDoc msg = "\nMBean delegate " + " for " + getObjectName() +
380                         " does not provide Statistic(s): " + missing + " from getStatistics() call, " +
381                     "\ngetStatisticNames() = " + toString( claimedSet ) +
382                     "\nnames from getStatistics() = " + toString( namesFromGetStatistics ) + "\n";
383                     
384                     AMXDebug.getInstance().getOutput(
385                         "MonitoringStatsImplBase.checkUnderlyingMBean" ).println( msg );
386                     logFine( msg );
387                 }
388             }
389             catch( Exception JavaDoc e )
390             {
391                 final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( e );
392                 logWarning( "MBean delegate " +
393                     " doesn't work, used by AMX MBean: " +
394                     getObjectName() + "\n" +
395                     rootCause.getClass().getName() + "\n" +
396                     ExceptionUtil.getStackTrace( rootCause ) );
397             }
398         }
399     }
400     
401     
402         private final String JavaDoc[]
403     initStatisticNames()
404     {
405         String JavaDoc[] names = null;
406         
407         if ( BUG_STATISTIC_NAMES )
408         {
409             names = getStats().getStatisticNames();
410             if ( names == null || names.length == 0 )
411             {
412                 throw new RuntimeException JavaDoc( "Stats are null or empty for: " + getObjectName());
413             }
414         }
415         else
416         {
417             names = originalToDerivedStatisticNames( getMonitoringMBeanDelegate().getStatisticNames() );
418         }
419         
420         return( names );
421     }
422     
423     /**
424         Gets the names of all the Statistics.
425         @return a String[] of statistic names
426     */

427         public String JavaDoc[]
428     getStatisticNames()
429     {
430         return( GSetUtil.toStringArray( mStatisticNames ) );
431     }
432
433         public CompositeDataSupport JavaDoc
434     getOpenStatistic(String JavaDoc name)
435     {
436         final Statistic JavaDoc statistic = getStatistic( name );
437         
438         try
439         {
440             return J2EEUtil.statisticToCompositeData(statistic);
441         }
442         catch(OpenDataException JavaDoc e)
443         {
444             throw new RuntimeException JavaDoc(e);
445         }
446     }
447
448         public CompositeDataSupport JavaDoc[]
449     getOpenStatistics( final String JavaDoc[] names)
450     {
451         final CompositeDataSupport JavaDoc[] result = new CompositeDataSupport JavaDoc[names.length];
452         
453         for(int i = 0; i < names.length; i++)
454         {
455             result[ i ] = getOpenStatistic( names[ i ] );
456         }
457         return result;
458     }
459
460         public CompositeDataSupport JavaDoc
461     getOpenStats()
462     {
463         final Stats stats = getStats();
464         
465         CompositeDataSupport JavaDoc result = null;
466         // can't make a CompositeDataSupport if there are no Statistics
467
if ( stats.getStatisticNames().length != 0 )
468         {
469             try
470             {
471                 result = J2EEUtil.statsToCompositeData( stats );
472             }
473             catch(OpenDataException JavaDoc e)
474             {
475                 throw new RuntimeException JavaDoc(e);
476             }
477         }
478         else
479         {
480             logWarning( "No Statistics available for: " + getObjectName() );
481         }
482         
483         return( result );
484     }
485
486         public Statistic JavaDoc
487     getStatistic( final String JavaDoc name)
488     {
489         final Stats stats = getStats();
490         
491         return stats.getStatistic( name );
492     }
493
494         public Statistic JavaDoc[]
495     getStatistics(final String JavaDoc[] desiredNames)
496     {
497         final Stats stats = getStats();
498         final Statistic JavaDoc[] result = new Statistic JavaDoc[ desiredNames.length ];
499         
500         for( int i = 0; i < desiredNames.length; ++i )
501         {
502             final Statistic JavaDoc statistic = stats.getStatistic( desiredNames[ i ] );
503             
504             // OK to return null if not found--see Javadoc
505
result[ i ] = statistic;
506         }
507         
508         return( result );
509     }
510
511     /**
512         Convert a Statistic-name from its underlying name to the one we expose.
513         
514         @param underlyingName
515      */

516         protected String JavaDoc
517     originalToDerivedStatisticName( final String JavaDoc underlyingName )
518     {
519         String JavaDoc result = getStatisticNameMapper().originalToDerived( underlyingName );
520         result = StringUtil.upperCaseFirstLetter( result );
521         
522         return( result );
523     }
524     
525         protected String JavaDoc
526     derivedToOriginalStatisticName( final String JavaDoc derivedName )
527     {
528         return( getStatisticNameMapper().derivedToOriginal( derivedName ) );
529     }
530     
531         protected final Statistic JavaDoc[]
532     getStatisticsFromDelegate()
533     {
534         if ( getDelegate() == null )
535         {
536             throw new NullPointerException JavaDoc();
537         }
538         return( getStatisticsFromDelegate( getDelegate() ) );
539     }
540
541         protected final Statistic JavaDoc[]
542     checkDuplicateStatistics(
543         final Delegate d,
544         final Statistic JavaDoc[] statistics)
545     {
546         // check to see if any names are duplicated
547
final Set JavaDoc<String JavaDoc> actualNames = new HashSet JavaDoc<String JavaDoc>();
548         for ( int i = 0; i < statistics.length; ++i )
549         {
550             final String JavaDoc name = statistics[ i ].getName();
551             
552             if ( actualNames.contains( name ) )
553             {
554                 throw new RuntimeException JavaDoc(
555                     "MonitoringStatsImplBase.checkDuplicateStatistics: " +
556                     getObjectName() +
557                         "Statistic " + StringUtil.quote( name ) + " is duplicated in getStatistics(): " +
558                         " as supplied from Delegate of " + StringUtil.quote( getObjectName() )+
559                         ", please see bug #6179364" );
560             }
561             else
562             {
563                 actualNames.add( name );
564             }
565         }
566         
567         if ( actualNames.size() != statistics.length )
568         {
569             final String JavaDoc[] claimedNames = (String JavaDoc[])d.invoke( "getStatisticNames", null, null );
570         
571             final Set JavaDoc<String JavaDoc> missingNames = GSetUtil.newStringSet( claimedNames );
572             missingNames.removeAll( actualNames );
573             
574             throw new RuntimeException JavaDoc(
575                 "MonitoringStatsImplBase.getStatisticsFromDelegateRaw: " + missingNames.size() +
576                 " Statistic names as found in Statistics from getStatistics() are missing: {" +
577                 toString( missingNames ) +
578                 "} from Delegate of " + StringUtil.quote( getObjectName() ) + ", please see bug #6179364" );
579         }
580         
581         return( statistics );
582     }
583
584         protected Statistic JavaDoc[]
585     getStatisticsFromDelegateRaw( final Delegate d )
586     {
587         try
588         {
589             final Statistic JavaDoc[] statistics = (Statistic JavaDoc[])d.invoke( "getStatistics", null, null );
590             
591             checkDuplicateStatistics( d, statistics );
592             
593             return( statistics );
594         }
595         catch( Exception JavaDoc e )
596         {
597             final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( e );
598             
599             logWarning( "MonitoringStatsImplBase: the com.sun.appserv Delegate MBean for AMX MBean " +
600                 getObjectName() + " threw an exception: " + rootCause +
601             ", stack = \n" + ExceptionUtil.getStackTrace( rootCause ) );
602         }
603         return new Statistic JavaDoc[0];
604     }
605
606
607     private void
608     debug( String JavaDoc s )
609     {
610         System.out.println( s );
611     }
612     
613     
614     /**
615         Get all Statistics from the delegate (our only available call API).
616         Statistic names are translated appropriately.
617      */

618         protected Statistic JavaDoc[]
619     getStatisticsFromDelegate( final Delegate d )
620     {
621         try
622         {
623             final Statistic JavaDoc[] statistics = getStatisticsFromDelegateRaw( d );
624             
625             // translate the names to be the ones we expose in MBeanInfo
626
for( int i = 0; i < statistics.length; ++i )
627             {
628                 final Statistic JavaDoc origStatistic = statistics[ i ];
629             
630                 final MapStatistic m = new MapStatisticImpl( origStatistic );
631                 
632                 final String JavaDoc convertedName = originalToDerivedStatisticName( origStatistic.getName() );
633                 if ( ! convertedName.equals( origStatistic.getName() ) )
634                 {
635                     m.setName( convertedName );
636                 }
637                 
638                 final Class JavaDoc<? extends Statistic JavaDoc> theClass =
639                     StatisticFactory.getInterface( origStatistic );
640                 assert( theClass != null );
641                 
642                 // this will create one which implements the requisite interfaces
643
statistics[ i ] = StatisticFactory.create( theClass, m.asMap() );
644                 
645                 assert( theClass.isAssignableFrom( statistics[ i ].getClass() ));
646             }
647             
648             return( statistics );
649         }
650         catch (Exception JavaDoc e)
651         {
652             final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( e );
653             
654             if ( ! ( rootCause instanceof InstanceNotFoundException JavaDoc ) )
655             {
656                 // don't rethrow--will make MBeanServer unuseable as it has a bug if we throw
657
// an exception of of getMBeanInfo() which halts any further processing of the query
658
//NOTE: WARNING_CHANGED_TO_FINE
659
logWarning( "Can't get Statistics from delegate for " + getObjectName() +
660                     "\n" + rootCause.getMessage() + "\n" + ExceptionUtil.getStackTrace( rootCause ) );
661             }
662             throw new RuntimeException JavaDoc( e );
663         }
664     }
665     
666     // default interface implemented by Stats that we return
667
private final Class JavaDoc[] STATS_IMPL_INTERFACES = new Class JavaDoc[]
668     {
669         Serializable JavaDoc.class,
670         Stats.class,
671     };
672     
673     /**
674         Get the specific type of Stats interface (if any) that should be implemented
675         by a Stats returned from getStats().
676         
677         @return an interface, or null if the interface is generic Stats
678      */

679     protected abstract Class JavaDoc getStatsInterface();
680     
681     
682         protected StatsImpl
683     createStatsImpl()
684     {
685         return new StatsImpl( getStatisticsFromDelegate() );
686     }
687     
688     /*
689         protected void
690     serializeTest( final Object toSerialize )
691         throws java.io.IOException, ClassNotFoundException
692     {
693         final java.io.ByteArrayOutputStream os = new java.io.ByteArrayOutputStream( 2048 );
694         
695         final java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream( os );
696         
697         oos.writeObject( toSerialize );
698         oos.close();
699         
700         final byte[] bytes = os.toByteArray();
701         
702         final java.io.ObjectInputStream is = new java.io.ObjectInputStream( new java.io.ByteArrayInputStream( bytes ) );
703         
704         final Object result = is.readObject();
705         
706         if ( ! result.equals( toSerialize ) )
707         {
708             assert( false ):
709                 "statistics not equal: " + toSerialize + " != " + result;
710         }
711     }
712     */

713     
714     
715         public String JavaDoc
716     getStatsInterfaceName()
717     {
718         return( getStatsInterface().getName() );
719     }
720     
721         public Stats
722     getStats()
723     {
724         final Class JavaDoc statsInterface = getStatsInterface();
725         assert( statsInterface == null || Stats.class.isAssignableFrom( statsInterface ) );
726         
727         Class JavaDoc[] implementedInterfaces = null;
728         if ( statsInterface == null )
729         {
730             implementedInterfaces = STATS_IMPL_INTERFACES;
731             logInfo( "getStats: no Stats interface found for " + getObjectName() );
732         }
733         else
734         {
735             implementedInterfaces = (Class JavaDoc[])
736                 ArrayUtil.newArray( STATS_IMPL_INTERFACES, statsInterface );
737         }
738         
739         final StatsImpl impl = createStatsImpl();
740         final ClassLoader JavaDoc classLoader = this.getClass().getClassLoader();
741         
742         final Stats stats = (Stats)
743             Proxy.newProxyInstance( classLoader, implementedInterfaces, impl );
744     
745     
746     /*try
747     {
748         serializeTest( stats );
749     } catch( Throwable t )
750     {
751         System.out.println( "getStats: Stats proxy serialization FAILED for " + getObjectName() );
752         ExceptionUtil.getRootCause( t ).printStackTrace();
753     }
754     */

755         
756         return( stats );
757     }
758
759     
760         public final boolean
761     refresh()
762     {
763         mMBeanInfo = null;
764         clearAttributeInfos();
765         
766         return( true );
767     }
768     
769     /**
770         Given a Statistic-name and a field-name, create an Attribute name.
771         
772         @param statisticName Statistic-name
773         @param fieldName
774         @return a name suitable for an Attribute
775      */

776         private String JavaDoc
777     makeAttributeName(
778         final String JavaDoc statisticName,
779         final String JavaDoc fieldName )
780     {
781         final String JavaDoc attributeName = statisticName + STATISTIC_DELIM + fieldName;
782
783         return( attributeName );
784     }
785     
786     /**
787         JSR 77 defines these fields as having type "long", so we must define them that
788         way as well, in spite of the underlying bug in the old monitoring MBeans, which
789         declares them all as Strings.
790      */

791     private static final Set JavaDoc<String JavaDoc> LONG_FIELDS = GSetUtil.newUnmodifiableStringSet(
792          "Count", "LastSampleTime", "StartTime", "LowerBound", "UpperBound",
793          "HighWaterMark", "LowWaterMark", "MaxTime", "MinTime", "TotalTime" );
794     
795     /**
796         Determine the Java class of a field.
797      */

798         private Class JavaDoc
799     determineFieldType(
800         final String JavaDoc fieldName,
801         final Object JavaDoc value )
802     {
803         Class JavaDoc theClass = String JavaDoc.class;
804         
805         if ( value != null )
806         {
807             theClass = ClassUtil.ObjectClassToPrimitiveClass( value.getClass() );
808         }
809         else if ( LONG_FIELDS.contains( fieldName ) )
810         {
811             theClass = long.class;
812         }
813         
814         return( theClass );
815     }
816     
817     /**
818         Convert a single Statistic to MBeanAttributeInfo.
819         
820         @return a Map, keyed by the Attribute name, value of MBeanAttributeInfo
821      */

822         private Map JavaDoc<String JavaDoc,MBeanAttributeInfo JavaDoc>
823     statisticToMBeanAttributeInfos( final Statistic JavaDoc s )
824     {
825         final Map JavaDoc<String JavaDoc,Object JavaDoc> src = new MapStatisticImpl( s ).asMap();
826         
827         final String JavaDoc statisticName = s.getName();
828         
829         final Map JavaDoc<String JavaDoc,MBeanAttributeInfo JavaDoc> result = new HashMap JavaDoc<String JavaDoc,MBeanAttributeInfo JavaDoc>();
830         for( final String JavaDoc fieldName : src.keySet() )
831         {
832             final Object JavaDoc value = src.get( fieldName );
833             // if the value is null, always make it a String
834
final String JavaDoc type = determineFieldType( fieldName, value ).getName();
835             
836             final String JavaDoc attributeName = makeAttributeName( statisticName, fieldName );
837             
838             final MBeanAttributeInfo JavaDoc attributeInfo = new MBeanAttributeInfo JavaDoc( attributeName, type, "",
839                                                 true, false, false );
840             result.put( attributeName, attributeInfo );
841         }
842         return( result );
843     }
844     
845     /**
846         Create MBeanInfo by taking default MBeanInfo and adding Attributes to it corresponding
847         to all available Statistics.
848      */

849         private synchronized MBeanInfo JavaDoc
850     createMBeanInfo()
851     {
852         final MBeanInfo JavaDoc baseMBeanInfo = super.getMBeanInfo();
853         
854         MBeanInfo JavaDoc mbeanInfo = baseMBeanInfo;
855         
856         if ( getMBeanServer() != null && getDelegate() != null )
857         {
858             assert( getDelegate() != null ) : "null delegate for: " + getObjectName();
859             
860             final Map JavaDoc<String JavaDoc,MBeanAttributeInfo JavaDoc>
861                 newAttrs = new HashMap JavaDoc<String JavaDoc,MBeanAttributeInfo JavaDoc>();
862             
863             final Statistic JavaDoc[] statistics = getStats().getStatistics();
864             for( int i = 0; i < statistics.length; ++i )
865             {
866                 final Map JavaDoc<String JavaDoc,MBeanAttributeInfo JavaDoc> attrInfos =
867                     statisticToMBeanAttributeInfos( statistics[ i ] );
868                 
869                 newAttrs.putAll( attrInfos );
870             }
871             
872             final MBeanAttributeInfo JavaDoc[] dynamicAttrInfos =
873                 new MBeanAttributeInfo JavaDoc[ newAttrs.keySet().size() ];
874             newAttrs.values().toArray( dynamicAttrInfos );
875             
876             final MBeanAttributeInfo JavaDoc[] attrInfos =
877                 JMXUtil.mergeMBeanAttributeInfos( dynamicAttrInfos, baseMBeanInfo.getAttributes() );
878             
879             mbeanInfo = JMXUtil.newMBeanInfo( baseMBeanInfo, attrInfos );
880         }
881         
882         return( mbeanInfo );
883     }
884     
885         protected ObjectName JavaDoc
886     preRegisterHook( final ObjectName JavaDoc objectName )
887     {
888         initFieldNameMapper();
889         initStatisticNameMapper();
890         
891         // ensure that it gets generated anew now that we are registered and can access everything
892
refresh();
893         
894         assert( MonitoringStats.class.isAssignableFrom( getInterface() ) ) :
895             "MBean extends MonitoringStatsImpl but does not have MonitoringStats interface: " + getObjectName();
896         
897         if ( BUG_STATISTIC_NAMES )
898         {
899             checkUnderlyingMBean();
900         }
901         
902         mStatisticNames = GSetUtil.newUnmodifiableStringSet( initStatisticNames() );
903         
904         return objectName;
905     }
906     
907     private static final MBeanInfo JavaDoc EMPTY_MBEAN_INFO =
908         new MBeanInfo JavaDoc( "Empty", "Failed to create MBeanInfo", null, null, null, null);
909         
910         public synchronized MBeanInfo JavaDoc
911     getMBeanInfo()
912     {
913         if ( mMBeanInfo == null )
914         {
915             try
916             {
917                 mMBeanInfo = createMBeanInfo();
918             }
919             catch( Throwable JavaDoc t )
920             {
921                 // if we throw an exception, it will kill the MBeanServer's ability
922
// to function
923
final Throwable JavaDoc rootCause = ExceptionUtil.getRootCause( t );
924                 
925                 // when an old mbean gets unregistered, this object does too,
926
// but the MBeanServer calls getMBeanInfo() before unregistering us,
927
// putting this MBean in the awkward position of supplying MBeanInfo
928
// from a delegate that has disappeared.
929
if ( ! ( rootCause instanceof InstanceNotFoundException JavaDoc) )
930                 {
931                     getMBeanLogger().warning( "can't create MBeanInfo for: " + getObjectName() +
932                         "\n" + rootCause.getClass() + ": " + rootCause.getMessage() + ":\n" +
933                         ExceptionUtil.getStackTrace( rootCause ) );
934                 }
935                 
936                 mMBeanInfo = EMPTY_MBEAN_INFO;
937             }
938         }
939         
940         return( mMBeanInfo );
941     }
942 }
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
Popular Tags