EMMA Coverage Report (generated Thu Aug 04 11:43:22 MEST 2005)
[all classes][org.jsesoft.mmbi]

COVERAGE SUMMARY FOR SOURCE FILE [ModelMBeanInstrumentor.java]

nameclass, %method, %block, %line, %
ModelMBeanInstrumentor.java100% (1/1)100% (24/24)99%  (1167/1177)100% (231.7/232)

COVERAGE BREAKDOWN BY CLASS AND METHOD

nameclass, %method, %block, %line, %
     
class ModelMBeanInstrumentor100% (1/1)100% (24/24)99%  (1167/1177)100% (231.7/232)
getJMXAnnotation (Annotation []): JMX 100% (1/1)92%  (24/26)98%  (3.9/4)
instrument (Object, String): NamedModelMBean 100% (1/1)93%  (94/101)99%  (20.9/21)
<static initializer> 100% (1/1)95%  (19/20)99%  (5/5)
ModelMBeanInstrumentor (): void 100% (1/1)100% (4/4)100% (2/2)
ModelMBeanInstrumentor (Class): void 100% (1/1)100% (9/9)100% (4/4)
getAttributeInfos (): ModelMBeanAttributeInfo [] 100% (1/1)100% (11/11)100% (3/3)
getConstructorInfos (): ModelMBeanConstructorInfo [] 100% (1/1)100% (11/11)100% (3/3)
getDescriptor (JMX, FeatureDescriptor, String, String, String, String): Descr... 100% (1/1)100% (135/135)100% (34/34)
getGetter (Class, Field): Method 100% (1/1)100% (95/95)100% (11/11)
getInspector (): ReflectionInspector 100% (1/1)100% (3/3)100% (1/1)
getMBeanInfo (): ModelMBeanInfo 100% (1/1)100% (33/33)100% (3/3)
getMethodDescriptor (MethodDescriptor [], Method): MethodDescriptor 100% (1/1)100% (25/25)100% (4/4)
getNotificationInfos (): ModelMBeanNotificationInfo [] 100% (1/1)100% (11/11)100% (3/3)
getOperationInfos (): ModelMBeanOperationInfo [] 100% (1/1)100% (11/11)100% (3/3)
getParameterInfos (Class [], Annotation [][], ParameterDescriptor []): MBeanP... 100% (1/1)100% (83/83)100% (16/16)
getPropertyDescriptor (PropertyDescriptor [], Field): PropertyDescriptor 100% (1/1)100% (26/26)100% (4/4)
getSetter (Class, Field): Method 100% (1/1)100% (72/72)100% (12/12)
handleJMXNotificationAnnotations (Annotation []): void 100% (1/1)100% (84/84)100% (15/15)
inspect (Class): boolean 100% (1/1)100% (51/51)100% (11/11)
inspectConstructor (Class, Constructor): boolean 100% (1/1)100% (77/77)100% (15/15)
inspectField (Class, Field): boolean 100% (1/1)100% (109/109)100% (27/27)
inspectMethod (Class, Method): boolean 100% (1/1)100% (169/169)100% (28/28)
instrument (Object): NamedModelMBean 100% (1/1)100% (5/5)100% (1/1)
postInspect (Class): void 100% (1/1)100% (6/6)100% (2/2)

1/**
2 * Class <code>ModelMBeanIntegrator<code>.
3 */
4package org.jsesoft.mmbi;
5 
6import java.lang.annotation.Annotation;
7import java.lang.reflect.Constructor;
8import java.lang.reflect.Field;
9import java.lang.reflect.InvocationTargetException;
10import java.lang.reflect.Method;
11import java.lang.reflect.Modifier;
12import java.beans.*;
13import java.util.Vector;
14import javax.management.Descriptor;
15import javax.management.MBeanException;
16import javax.management.MBeanOperationInfo;
17import javax.management.MBeanParameterInfo;
18import javax.management.MBeanServer;
19import javax.management.ObjectName;
20import javax.management.modelmbean.DescriptorSupport;
21import javax.management.modelmbean.ModelMBeanAttributeInfo;
22import javax.management.modelmbean.ModelMBeanConstructorInfo;
23import javax.management.modelmbean.ModelMBeanInfo;
24import javax.management.modelmbean.ModelMBeanInfoSupport;
25import javax.management.modelmbean.ModelMBeanOperationInfo;
26import javax.management.modelmbean.XMLParseException;
27import javax.management.modelmbean.ModelMBeanNotificationInfo;
28 
29import org.jsesoft.ri.InspectorSupport;
30import org.jsesoft.ri.ReflectionInspector;
31 
32/**
33 * Instruments (an registers) an arbitrary object as Model MBean.
34 *
35 * <p>
36 * This class provides JMX Model MBean instrumentation and registration
37 * for objects of arbitrary classes. It is implemented as a strategy for the
38 * {@link org.jsesoft.ri.ReflectionInspector <code>ReflectionInspector</code>}
39 * class.
40 * </p>
41 * <p>
42 * <b>Example:</b>
43 * <code>
44 * <pre>
45 * ModelMBeanInstrumentor instrumentor = new ModelMBeanInstrumentor();
46 * SampleResource resource = new SampleResource();
47 * NamedModelMBean mbean = instrumentor.instrument( resource, "sampleResource" );
48 * System.out.println( "Stop JConsole " + mbean.getName().getCanonicalName() );
49 * MBeanServer server =
50 *     java.lang.management.ManagementFactory.getPlatformMBeanServer();
51 * int count = 300;
52 * while( ! resource.isStopped() ) {
53 *     Thread.sleep( 100 );
54 *     count--;
55 *     if( (count <= 0) &amp;&amp;  (! resource.isControlled()) ) {
56 *         resource.setStopped( true );
57 *     }
58 * }
59 * server.unregisterMBean( mbean.getName() );
60 * </pre>
61 * </code>
62 * </p>
63 *
64 * @author JSESoft
65 * @version $Revision: 1.6 $
66 */
67public class ModelMBeanInstrumentor
68    extends InspectorSupport
69{
70    /** The mbean's descriptor. */
71    private Descriptor mbeanDescriptor;
72    /** The mbean's ModelMBeanInfo. */
73    private ModelMBeanInfo mbeanInfo;
74    /** The actually insepted classes JavaBean BeanInfo */
75    BeanInfo beanInfo;
76    /** The mbean's construcotr infos. */
77    private Vector<ModelMBeanConstructorInfo> constructorInfos;
78    /** The mbean's operation infos. */
79    private Vector<ModelMBeanOperationInfo> operationInfos;
80    /** The mbean's attribuye infos. */
81    private Vector<ModelMBeanAttributeInfo> attributeInfos;
82    /** The mbean's attribuye infos. */
83    private Vector<ModelMBeanNotificationInfo> notificationInfos;
84    /** A type specifier for Vector.toArray() */
85    private static final ModelMBeanConstructorInfo[] constructors
86        = new ModelMBeanConstructorInfo[0];
87    /** A type specifier for Vector.toArray() */
88    private static final ModelMBeanOperationInfo[] operations
89        = new ModelMBeanOperationInfo[0];
90    /** A type specifier for Vector.toArray() */
91    private static final ModelMBeanAttributeInfo[] attributes
92        = new ModelMBeanAttributeInfo[0];
93    /** A type specifier for Vector.toArray() */
94    private static final ModelMBeanNotificationInfo[] notifications
95        = new ModelMBeanNotificationInfo[0];
96    /** The class where to stop reflection recursion. */
97    private Class sentinel;
98    /** Whether or not to produce debug info. */
99    private static final boolean debug = true;
100    /** The mbean itself. */
101    private NamedModelMBean mbean = null;
102    /** The inspector uesed. */
103    private ReflectionInspector inspector;
104 
105    /**
106     * Constructs an instance with <code>Object.class</code>
107     * as sentinel.
108     *
109     * @see #ModelMBeanInstrumentor(Class)
110     */
111    public ModelMBeanInstrumentor()
112    {
113        this( Object.class );
114    }
115 
116    /**
117     * Constructs an instance with the specified class as sentinel.
118     *
119     * <p>
120     * Traversal of the reflection tree is recusrsive with respect
121     * to inheritance. The <b>sentinel</b> specifies where recursion stops.
122     * Default is <code>Object.class</code> (see
123     * {@link #ModelMBeanInstrumentor() non-parameter constructor}).
124     * </p>
125     * @param sentinel Class where recursive traversal stops
126     */
127    public ModelMBeanInstrumentor( Class sentinel )
128    {
129        super();
130        this.sentinel = sentinel;
131    }
132 
133    /**
134     * Creates a <code>ModelMBean</code> for a managed resource.
135     *
136     * @param managedResource the resource to be managed as Model MBean
137     * @return the created NamedModelMBean
138     * @throws Exception if instrumentation fails
139     */
140    public NamedModelMBean instrument( Object managedResource )
141        throws Exception
142    {
143        return instrument( managedResource, null );
144    }
145 
146    /**
147     * Creates a <code>ModelMBean</code> for a managed resource
148     * and registers it as JMX MBean.
149     *
150     * <p>
151     * This function is the workhorse of this class. It
152     * <ol>
153     * <li>
154     * It creates a {@link NamedModelMBean <code>NamedModelMBean</code>}
155     * instance.
156     * </li>
157     * <li>
158     * It internally creates an
159     * {@link org.jsesoft.ri.ReflectionInspector ReflectionInspector} for
160     * traversing the reflection tree.
161     * </li>
162     * <li>
163     * It inspects the managed resource.
164     * </li>
165     * <li>
166     * if the <code>nickName</code> parameter is null, thats it. Otherqwise
167     * </li>
168     * <li>
169     * It creates an object name like this
170     * <code>
171     * <pre>
172     * classnameOfManagedResource:id=nickName-hashCode
173     * </pre>
174     * </code>
175     * </li>
176     * <li>
177     * registers the MBean at the platform MBean server
178     * </li>
179     * <li>
180     * sets the instance of the mbean
181     * </li>
182     * </ol>
183     * </p>
184     *
185     * @param managedResource the resource to be managed as Model MBean
186     * @param nickName part of the object name (if null then don't register)
187     * @return the created NamedModelMBean
188     * @throws Exception if instrumentation fails
189     */
190    public NamedModelMBean instrument( Object managedResource, String nickName )
191        throws Exception
192    {
193        mbeanInfo = null;
194        attributeInfos = null;
195        constructorInfos = null;
196        operationInfos = null;
197        notificationInfos = null;
198        mbean = new NamedModelMBean();
199        mbean.setManagedResource( managedResource, "ObjectReference" );
200        inspector = new ReflectionInspector();
201        beanInfo =
202            Introspector.getBeanInfo( managedResource.getClass(), sentinel );
203        inspector.setInspectee( managedResource.getClass() );
204        inspector.setStrategy( this );
205        boolean reply = inspector.inspect();
206        assert reply:"inspection failed";
207        if( nickName == null ) {
208            return mbean;
209        }
210        StringBuilder name =
211            new StringBuilder( managedResource.getClass().getName() );
212        name.append( ":id=" ).append( nickName ).append( "-" ).append( managedResource.
213            hashCode() );
214        ObjectName objectName = new ObjectName( name.toString() );
215        MBeanServer server = java.lang.management.ManagementFactory.
216                             getPlatformMBeanServer();
217        mbean.setInstance( server.registerMBean( mbean, objectName ) );
218        return mbean;
219    }
220 
221    /**
222     * This override sets the mbean's MBeanInfo after inspection.
223     *
224     * <p>
225     * <b>Note:</b> This function is not intended to be called
226     * by customers. Instead, it is called by the inspector.
227     * </p>
228     * @param inspected the inspected class
229     * @throws Exception if inspection fails
230     */
231    @Override public void postInspect( Class inspected )
232        throws Exception
233    {
234        mbean.setModelMBeanInfo( getMBeanInfo() );
235    }
236 
237    /**
238     * This override creates a JMX descriptor for the inspected class.
239     *
240     * <p>
241     * <b>Note:</b> This function is not intended to be called
242     * by customers. Instead, it is called by the inspector.
243     * </p>
244     * @param inspected the inspected class
245     * @throws Exception if inspection fails
246     * @return true if inspection complete
247     */
248    @Override public boolean inspect( Class inspected )
249        throws Exception
250    {
251        if( inspected.equals( sentinel ) ) {
252            return true;
253        }
254        BeanInfo oldBeanInfo = beanInfo;
255        beanInfo = Introspector.getBeanInfo( inspected, sentinel );
256        handleJMXNotificationAnnotations( inspected.getAnnotations() );
257        JMX annotation =
258            ( JMX )inspected.getAnnotation( org.jsesoft.mmbi.JMX.class );
259 
260        Descriptor descriptor =
261            getDescriptor(
262            annotation,
263            beanInfo.getBeanDescriptor(),
264            inspected.getName(),
265            inspected.getSimpleName(),
266            inspected.getCanonicalName(),
267            "MBean" );
268        mbeanDescriptor = descriptor;
269        if( debug ) {
270            System.out.println( ( ( DescriptorSupport )descriptor ).toXMLString() );
271        }
272        beanInfo = oldBeanInfo;
273        return false;
274    }
275 
276    /**
277     * This override creates a constructor info for the inspected constructor.
278     *
279     * <p>
280     * <b>Note:</b> This function is not intended to be called
281     * by customers. Instead, it is called by the inspector.
282     * </p>
283     * @param inspected the inspected class
284     * @param constructor the inspected constructor
285     * @throws Exception if inspection fails
286     * @return true if inspection complete
287     */
288    @Override
289        public boolean inspectConstructor( Class inspected, Constructor constructor )
290        throws Exception
291    {
292        if( !Modifier.isPublic( constructor.getModifiers() ) ) {
293            return false;
294        }
295        handleJMXNotificationAnnotations( constructor.getAnnotations() );
296        JMX annotation =
297            constructor.getAnnotation( org.jsesoft.mmbi.JMX.class );
298        if( ( annotation != null )
299            && ( annotation.hide() ) ) {
300            return false;
301        }
302        MBeanParameterInfo[] parameterInfos =
303            getParameterInfos(
304            constructor.getParameterTypes(),
305            constructor.getParameterAnnotations(),
306            null );
307        String name = constructor.getName();
308        Descriptor descriptor =
309            getDescriptor(
310            annotation,
311            null,
312            name,
313            name,
314            name,
315            "operation" );
316        descriptor.setField( "role", "constructor" );
317        if( constructorInfos == null ) {
318            constructorInfos = new Vector<ModelMBeanConstructorInfo>();
319        }
320        constructorInfos.add(
321            new ModelMBeanConstructorInfo(
322            ( String )descriptor.getFieldValue( "name" ),
323            ( String )descriptor.getFieldValue( "description" ),
324            parameterInfos,
325            descriptor ) );
326        if( debug ) {
327            System.out.println( ( ( DescriptorSupport )descriptor ).toXMLString() );
328        }
329        return false;
330    }
331 
332    /**
333     * This override creates a operation info for the inspected method.
334     *
335     * <p>
336     * <b>Note:</b> This function is not intended to be called
337     * by customers. Instead, it is called by the inspector.
338     * </p>
339     * @param inspected the inspected class
340     * @param operation the inspected method
341     * @throws Exception if inspection fails
342     * @return true if inspection complete
343     */
344    @Override public boolean inspectMethod( Class inspected, Method operation )
345        throws Exception
346    {
347        if( !Modifier.isPublic( operation.getModifiers() ) ) {
348            return false;
349        }
350        handleJMXNotificationAnnotations( operation.getAnnotations() );
351        JMX annotation =
352            operation.getAnnotation( org.jsesoft.mmbi.JMX.class );
353        if( ( annotation != null )
354            && ( annotation.hide() ) ) {
355            return false;
356        }
357        MethodDescriptor methodDescriptor =
358            getMethodDescriptor(
359            beanInfo.getMethodDescriptors(),
360            operation );
361        ParameterDescriptor[] parameterDescriptors =
362            ( methodDescriptor == null ) ? null
363            : methodDescriptor.getParameterDescriptors();
364        MBeanParameterInfo[] parameterInfos =
365            getParameterInfos(
366            operation.getParameterTypes(),
367            operation.getParameterAnnotations(),
368            parameterDescriptors );
369        String name = operation.getName();
370        Descriptor descriptor =
371            getDescriptor(
372            annotation,
373            methodDescriptor,
374            name,
375            name,
376            name,
377            "operation" );
378        descriptor.setField( "class", inspected.getName() );
379        descriptor.setField( "displayName", descriptor.getFieldValue( "name" ) );
380        if( ( operation.getName().startsWith( "get" )
381            && ( operation.getParameterTypes().length == 0 )
382            && ( operation.getReturnType() != null ) )
383            || ( operation.getName().startsWith( "is" )
384            && ( operation.getParameterTypes().length == 0 )
385            && boolean.class.equals( operation.getReturnType() ) ) ) {
386            descriptor.setField( "role", "getter" );
387        } else
388        if( operation.getName().startsWith( "set" )
389            && ( void.class.equals( operation.getReturnType() ) )
390            && ( operation.getParameterTypes().length == 1 ) ) {
391            descriptor.setField( "role", "setter" );
392        } else {
393            descriptor.setField( "role", "operation" );
394        }
395        int impact =
396            ( annotation == null ) ? MBeanOperationInfo.ACTION_INFO : annotation.impact();
397        if( impact == MBeanOperationInfo.UNKNOWN ) {
398            impact = MBeanOperationInfo.ACTION_INFO;
399        }
400        if( operationInfos == null ) {
401            operationInfos = new Vector<ModelMBeanOperationInfo>();
402        }
403        operationInfos.add(
404            new ModelMBeanOperationInfo(
405            ( String )descriptor.getFieldValue( "name" ),
406            ( String )descriptor.getFieldValue( "description" ),
407            parameterInfos,
408            operation.getReturnType().getName(),
409            impact,
410            descriptor ) );
411        if( debug ) {
412            System.out.println( ( ( DescriptorSupport )descriptor ).toXMLString() );
413        }
414 
415        return false;
416    }
417 
418    private MBeanParameterInfo[] getParameterInfos(
419        Class<? >[] types,
420        Annotation[][] annotations,
421        ParameterDescriptor[] features )
422        throws
423        NoSuchMethodException,
424        InvocationTargetException,
425        IllegalAccessException
426    {
427        if( types.length == 0 ) {
428            return new MBeanParameterInfo[0];
429        }
430        MBeanParameterInfo[] parameterInfos
431            = new MBeanParameterInfo[types.length];
432        for( int iX = 0; iX < types.length; iX++ ) {
433            Class<? > type = types[iX];
434            JMX annotation = getJMXAnnotation( annotations[iX] );
435            String name = ( features == null ) ? null : features[iX].getName();
436            if( name == null ) {
437                name = "p" + iX;
438            }
439            String description =
440                ( features == null ) ? null : features[iX].getShortDescription();
441            if( description == null ) {
442                description = ( annotation == null ) ? "" : annotation.description();
443            }
444            if( "".equals( description ) ) {
445                description = name;
446            }
447            parameterInfos[iX] =
448                new MBeanParameterInfo( name, type.getName(), description );
449        }
450        return parameterInfos;
451    }
452 
453    /**
454     * Gets the JavaBeans method descriptor for the method.
455     *
456     * @param features the BeanInfo MethodDescriptors
457     * @param method the Method
458     * @return the MethodDescriptor, null if none
459     */
460    public MethodDescriptor getMethodDescriptor( MethodDescriptor[] features,
461        Method method )
462    {
463        for( MethodDescriptor feature : features ) {
464            if( feature.getMethod().equals( method ) ) {
465                return feature;
466            }
467        }
468        return null;
469    }
470 
471    /**
472     * This override creates a attribute info for the inspected field.
473     *
474     * <p>
475     * <b>Note:</b> This function is not intended to be called
476     * by customers. Instead, it is called by the inspector.
477     * </p>
478     * @param inspected the inspected class
479     * @param field the inspected field
480     * @throws Exception if inspection fails
481     * @return true if inspection complete
482     */
483    @Override public boolean inspectField( Class inspected, Field field )
484        throws Exception
485    {
486        JMX annotation =
487            field.getAnnotation( org.jsesoft.mmbi.JMX.class );
488        if( ( annotation != null )
489            && ( annotation.hide() ) ) {
490            return false;
491        }
492        PropertyDescriptor propertyDescriptor =
493            getPropertyDescriptor( beanInfo.getPropertyDescriptors(), field );
494        Method getter = null;
495        if( propertyDescriptor != null ) {
496            getter = propertyDescriptor.getReadMethod();
497        }
498        if( getter == null ) {
499            getter = getGetter( inspected, field );
500        }
501        Method setter = null;
502        if( propertyDescriptor != null ) {
503            setter = propertyDescriptor.getWriteMethod();
504        }
505        if( setter == null ) {
506            setter = getSetter( inspected, field );
507        }
508        if( ( setter == null ) && ( getter == null ) ) {
509            return false;
510        }
511        String name = field.getName();
512        Descriptor descriptor =
513            getDescriptor(
514            annotation,
515            propertyDescriptor,
516            name,
517            name,
518            name,
519            "attribute" );
520        if( getter != null ) {
521            descriptor.setField( "getMethod", getter.getName() );
522        }
523        if( setter != null ) {
524            descriptor.setField( "setMethod", setter.getName() );
525        }
526        if( attributeInfos == null ) {
527            attributeInfos = new Vector<ModelMBeanAttributeInfo>();
528        }
529        attributeInfos.add(
530            new ModelMBeanAttributeInfo(
531            ( String )descriptor.getFieldValue( "name" ),
532            ( String )descriptor.getFieldValue( "description" ),
533            getter,
534            setter,
535            descriptor ) );
536        if( debug ) {
537            System.out.println( ( ( DescriptorSupport )descriptor ).toXMLString() );
538        }
539        return false;
540    }
541 
542    /**
543     * Gets the BeanInfe PropertyDescriptor for the field.
544     *
545     * @param features the BeanInfo PropertyDescriptors
546     * @param field the Field
547     * @return the PropertyDescriptor, null if none
548     */
549    public PropertyDescriptor getPropertyDescriptor(
550        PropertyDescriptor[] features,
551        Field field )
552    {
553        for( PropertyDescriptor feature : features ) {
554            if( feature.getName().equals( field.getName() ) ) {
555                return feature;
556            }
557        }
558        return null;
559    }
560 
561    /**
562     * Inquires the getter method for a field.
563     *
564     * @param inspected the inspected Class
565     * @param field the inspected Field
566     * @return getter, null if none defined
567     */
568    public static Method getGetter( Class inspected, Field field )
569    {
570        String name = field.getName();
571        String upper =
572            Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 );
573        Method methods[] = inspected.getDeclaredMethods();
574        for( Method method : methods ) {
575            if( !Modifier.isPublic( method.getModifiers() ) ) {
576                continue;
577            }
578            if( boolean.class.equals( field.getType() )
579                && boolean.class.equals( method.getReturnType() )
580                && ( method.getParameterTypes().length == 0 )
581                && ( "is" + upper ).equals( method.getName() ) ) {
582                return method;
583            }
584            if( field.getType().equals( method.getReturnType() )
585                && ( method.getParameterTypes().length == 0 )
586                && ( "get" + upper ).equals( method.getName() ) ) {
587                return method;
588            }
589        }
590        return null;
591    }
592 
593    /**
594     * Inquires the setter method for a field.
595     *
596     * @param inspected the inspected Class
597     * @param field the inspected Field
598     * @return setter, null if none defined
599     */
600    public static Method getSetter( Class inspected, Field field )
601    {
602        String name = field.getName();
603        String upper =
604            Character.toUpperCase( name.charAt( 0 ) ) + name.substring( 1 );
605        Method methods[] = inspected.getDeclaredMethods();
606        for( Method method : methods ) {
607            if( !Modifier.isPublic( method.getModifiers() ) ) {
608                continue;
609            }
610            Class[] types = method.getParameterTypes();
611            if( types.length != 1 ) {
612                continue;
613            }
614            if( field.getType().equals( types[0] )
615                && ( "set" + upper ).equals( method.getName() ) ) {
616                return method;
617            }
618        }
619        return null;
620    }
621 
622    /**
623     * Inquires the JMX annotation.
624     *
625     * @param annotations the annotations to be looked up for the JMX annotation
626     * @return JMX
627     */
628    public static JMX getJMXAnnotation( Annotation[] annotations )
629    {
630        for( Annotation annotation : annotations ) {
631            if( annotation.annotationType().isAssignableFrom(
632                org.jsesoft.mmbi.JMX.class ) ) {
633                return( JMX )annotation;
634            }
635        }
636        return null;
637    }
638 
639    /**
640     * Handles the JMXNotification annotations.
641     *
642     * @param annotations the annotations to be looked up for the JMX annotation
643     * @throws Exception if descriptor cannot be created
644     */
645    public void handleJMXNotificationAnnotations( Annotation[] annotations )
646        throws Exception
647    {
648        for( Annotation annotation : annotations ) {
649            if( annotation.annotationType().isAssignableFrom(
650                org.jsesoft.mmbi.JMXNotification.class ) ) {
651                JMXNotification notification = ( JMXNotification )annotation;
652                String[] types = notification.types();
653                Descriptor descriptor;
654                descriptor = new DescriptorSupport();
655                descriptor.setField( "name", notification.name() );
656                descriptor.setField( "displayName", notification.displayName() );
657                descriptor.setField( "description", notification.description() );
658                descriptor.setField( "severity", notification.severity() );
659                descriptor.setField( "descriptorType", "notification" );
660                if( notificationInfos == null ) {
661                    notificationInfos = new Vector<ModelMBeanNotificationInfo>();
662                }
663                notificationInfos.add(
664                    new ModelMBeanNotificationInfo(
665                    notification.types(),
666                    notification.name(),
667                    notification.description(),
668                    descriptor ) );
669                if( debug ) {
670                    System.out.println( ( ( DescriptorSupport )descriptor ).toXMLString() );
671                }
672            }
673        }
674    }
675 
676    /**
677     * Creates a JMX descriptor from the specified information.
678     *
679     * <p>
680     * Default information can be overruled by annotation information
681     * </p>
682     * <p>
683     * <b>Note:</b> Though this was designed as a helper function,
684     * it might be useful for customers, too.
685     * </p>
686     *
687     * @param annotation the JMX annotation containing overriding info
688     * @param feature the Javabeans feature descriptor containing overriding info
689     * @param defaultName the default name
690     * @param defaultDisplayName the default display name
691     * @param defaultDescription the default description
692     * @param descriptorType the type of the descriptor to create
693     * @return the created descriptor
694     * @throws MBeanException if descriptor cannot be created
695     * @throws XMLParseException if the annotation's XML is not valid
696     */
697    public static Descriptor getDescriptor(
698        JMX annotation,
699        FeatureDescriptor feature,
700        String defaultName,
701        String defaultDisplayName,
702        String defaultDescription,
703        String descriptorType )
704        throws
705        MBeanException,
706        XMLParseException
707    {
708        Descriptor descriptor;
709        if( annotation != null ) {
710            String xml = annotation.xml();
711            if( "".equals( xml ) ) {
712                descriptor = new DescriptorSupport();
713                descriptor.setField( "name", defaultName );
714            } else {
715                descriptor = new DescriptorSupport( xml );
716            }
717        } else {
718            descriptor = new DescriptorSupport();
719            descriptor.setField( "name", defaultName );
720        }
721        descriptor.setField( "descriptorType", descriptorType );
722        String name = ( String )descriptor.getFieldValue( "name" );
723        if( ( feature != null ) && ( feature.getName() != null ) ) {
724            name = feature.getName();
725        }
726        if( ( annotation != null )
727            && ( !"".equals( annotation.name() ) ) ) {
728            name = annotation.name();
729        }
730        String displayName = ( String )descriptor.getFieldValue( "displayName" );
731        if( ( feature != null ) && ( feature.getDisplayName() != null ) ) {
732            displayName = feature.getDisplayName();
733        }
734        if( ( annotation != null )
735            && ( !"".equals( annotation.displayName() ) ) ) {
736            displayName = annotation.displayName();
737        }
738        if( ( displayName == null ) || "".equals( displayName ) ) {
739            displayName = defaultDisplayName;
740        }
741        String description = ( String )descriptor.getFieldValue( "description" );
742        if( ( feature != null ) && ( feature.getShortDescription() != null ) ) {
743            description = feature.getShortDescription();
744        }
745        if( ( annotation != null )
746            && ( !"".equals( annotation.description() ) ) ) {
747            description = annotation.description();
748        }
749        if( ( description == null ) || "".equals( description ) ) {
750            description = defaultDescription;
751        }
752        descriptor.setField( "name", name );
753        descriptor.setField( "displayName", displayName );
754        descriptor.setField( "description", description );
755        return descriptor;
756    }
757 
758    /**
759     * Gets the created constructor infos.
760     *
761     * @return ModelMBeanConstructorInfo[]
762     */
763    public ModelMBeanConstructorInfo[] getConstructorInfos()
764    {
765        if( constructorInfos == null ) {
766            return null;
767        }
768        return constructorInfos.toArray( constructors );
769    }
770 
771    /**
772     * Gets the created operation info.
773     *
774     * @return ModelMBeanOperationInfo[]
775     */
776    public ModelMBeanOperationInfo[] getOperationInfos()
777    {
778        if( operationInfos == null ) {
779            return null;
780        }
781        return operationInfos.toArray( operations );
782    }
783 
784    /**
785     * Gets the created attribute info.
786     *
787     * @return ModelMBeanAttributeInfo[]
788     */
789    public ModelMBeanAttributeInfo[] getAttributeInfos()
790    {
791        if( attributeInfos == null ) {
792            return null;
793        }
794        return attributeInfos.toArray( attributes );
795    }
796 
797    /**
798     * Gets the created attribute info.
799     *
800     * @return ModelMBeanAttributeInfo[]
801     */
802    public ModelMBeanNotificationInfo[] getNotificationInfos()
803    {
804        if( notificationInfos == null ) {
805            return null;
806        }
807        return notificationInfos.toArray( notifications );
808    }
809 
810    /**
811     * Gets the created MBeanInfo.
812     *
813     * <p>
814     * This function creates the MBean Info, if not already done.
815     * </p>
816     * @return ModelMBeanInfo
817     */
818    public ModelMBeanInfo getMBeanInfo()
819    {
820        if( mbeanInfo != null ) {
821            return mbeanInfo;
822        }
823        return mbeanInfo =
824            new ModelMBeanInfoSupport(
825            ( String )mbeanDescriptor.getFieldValue( "name" ),
826            ( String )mbeanDescriptor.getFieldValue( "description" ),
827            getAttributeInfos(),
828            getConstructorInfos(),
829            getOperationInfos(),
830            getNotificationInfos(),
831            mbeanDescriptor );
832    }
833 
834    /**
835     * Inquires the inspector used for reflection traversal.
836     *
837     * @return the used <code>ReflectionInspector</code>
838     */
839    public ReflectionInspector getInspector()
840    {
841        return inspector;
842    }
843}

[all classes][org.jsesoft.mmbi]
EMMA 2.0.5312 (C) Vladimir Roubtsov