OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [javax/] [management/] [StandardMBean.java] - Blame information for rev 772

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 772 jeremybenn
/* StandardMBean.java -- A standard reflection-based management bean.
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
package javax.management;
39
 
40
import java.lang.reflect.Constructor;
41
import java.lang.reflect.InvocationTargetException;
42
import java.lang.reflect.Method;
43
 
44
import java.util.ArrayList;
45
import java.util.HashMap;
46
import java.util.Iterator;
47
import java.util.List;
48
import java.util.Map;
49
 
50
/**
51
 * Provides a dynamic management bean by using reflection on an
52
 * interface and an implementing class.  By default, a bean instance
53
 * is paired up with its interface based on specific naming
54
 * conventions (if the implementation is called X, the interface must
55
 * be XMBean).  Using this class removes the need to use a specific
56
 * naming system to match up the two.  Instead, an instance of this
57
 * bean is created either via explicit construction or subclassing,
58
 * and this provides access to the attributes, constructors and
59
 * operations of the implementation via reflection.  Various hooks are
60
 * provided in order to allow customization of this process.
61
 *
62
 * @author Andrew John Hughes (gnu_andrew@member.fsf.org)
63
 * @since 1.5
64
 */
65
public class StandardMBean
66
  implements DynamicMBean
67
{
68
 
69
  /**
70
   * The interface for this bean.
71
   */
72
  private Class<?> iface;
73
 
74
  /**
75
   * The implementation of the interface.
76
   */
77
  private Object impl;
78
 
79
  /**
80
   * Cached bean information.
81
   */
82
  private MBeanInfo info;
83
 
84
  /**
85
   * Constructs a new {@link StandardMBean} using the specified
86
   * interface and <code>this</code> as the instance.  This should
87
   * be used to create an instance via subclassing.
88
   *
89
   * @param iface the interface this bean implements, or <code>null</code>
90
   *              if the interface should be determined using the naming
91
   *              convention (class X has interface XMBean).
92
   * @throws NotCompliantMBeanException if this class doesn't implement
93
   *                                    the interface or a method appears
94
   *                                    in the interface that doesn't comply
95
   *                                    with the naming conventions.
96
   */
97
  protected StandardMBean(Class<?> iface)
98
    throws NotCompliantMBeanException
99
  {
100
    if (iface == null)
101
      {
102
        String className = getClass().getName();
103
        try
104
          {
105
            iface = Class.forName(className + "MBean");
106
          }
107
        catch (ClassNotFoundException e)
108
          {
109
            for (Class<?> nextIface : getClass().getInterfaces())
110
            {
111
              if (JMX.isMXBeanInterface(nextIface))
112
                {
113
                  iface = nextIface;
114
                  break;
115
                }
116
            }
117
            if (iface == null)
118
              throw (NotCompliantMBeanException)
119
                (new NotCompliantMBeanException("An interface for the class "
120
                                                + className +
121
                                                " was not found.").initCause(e));
122
          }
123
      }
124
    if (!(iface.isInstance(this)))
125
      throw new NotCompliantMBeanException("The instance, " + impl +
126
                                           ", is not an instance of " + iface);
127
    impl = this;
128
    this.iface = iface;
129
  }
130
 
131
  /**
132
   * Constructs a new {@link StandardMBean} using the specified
133
   * interface and the supplied instance as the implementation.
134
   *
135
   * @param impl the implementation.
136
   * @param iface the interface the bean implements, or <code>null</code>
137
   *              if the interface should be determined using the naming
138
   *              convention (class X has interface XMBean).
139
   * @throws IllegalArgumentException if <code>impl</code> is <code>null</code>.
140
   * @throws NotCompliantMBeanException if <code>impl</code> doesn't implement
141
   *                                    the interface or a method appears
142
   *                                    in the interface that doesn't comply
143
   *                                    with the naming conventions.
144
   */
145
  public <T> StandardMBean(T impl, Class<T> iface)
146
    throws NotCompliantMBeanException
147
  {
148
    if (impl == null)
149
      throw new IllegalArgumentException("The specified implementation is null.");
150
    if (iface == null)
151
      {
152
        Class<?> implClass = impl.getClass();
153
        String className = implClass.getName();
154
        try
155
          {
156
            this.iface = Class.forName(className + "MBean", true,
157
                                       implClass.getClassLoader());
158
          }
159
        catch (ClassNotFoundException e)
160
          {
161
            for (Class<?> nextIface : implClass.getInterfaces())
162
            {
163
              if (JMX.isMXBeanInterface(nextIface))
164
                {
165
                  this.iface = nextIface;
166
                  break;
167
                }
168
            }
169
            if (this.iface == null)
170
              throw (NotCompliantMBeanException)
171
                (new NotCompliantMBeanException("An interface for the class " +
172
                                                className +
173
                                                " was not found.").initCause(e));
174
          }
175
      }
176
    else
177
      this.iface = iface;
178
    if (!(this.iface.isInstance(impl)))
179
      throw new NotCompliantMBeanException("The instance, " + impl +
180
                                           ", is not an instance of " + iface);
181
    this.impl = impl;
182
  }
183
 
184
  /**
185
   * Caches the {@link MBeanInfo} instance for this object.  This is a
186
   * customization hook, so that subclasses can choose the caching policy
187
   * used.  The default implementation caches the value in the instance
188
   * itself.  Subclasses may override this so as to not cache the data
189
   * at all, or so as to use a cache shared between multiple beans.
190
   *
191
   * @param info the {@link MBeanInfo} instance to cache, or <code>null</code>
192
   *             if there is no new value to cache.  When the value is not
193
   *             <code>null</code>, the cache should replace the current value
194
   *             with the value supplied here.
195
   * @see #getCachedMBeanInfo()
196
   */
197
  protected void cacheMBeanInfo(MBeanInfo info)
198
  {
199
    if (info != null)
200
      this.info = info;
201
  }
202
 
203
  /**
204
   * Obtains the value of the specified attribute of the
205
   * management bean.  The management bean should perform
206
   * a lookup for the named attribute, and return its value
207
   * by calling the appropriate getter method, if possible.
208
   *
209
   * @param name the name of the attribute to retrieve.
210
   * @return the value of the specified attribute.
211
   * @throws AttributeNotFoundException if the name does not
212
   *                                    correspond to an attribute
213
   *                                    of the bean.
214
   * @throws MBeanException if retrieving the attribute causes
215
   *                        the bean to throw an exception (which
216
   *                        becomes the cause of this exception).
217
   * @throws ReflectionException if an exception occurred in trying
218
   *                             to use the reflection interface
219
   *                             to lookup the attribute.  The
220
   *                             thrown exception is the cause of
221
   *                             this exception.
222
   * @see #setAttribute(String)
223
   */
224
  public Object getAttribute(String name)
225
    throws AttributeNotFoundException, MBeanException,
226
           ReflectionException
227
  {
228
    Method getter;
229
    try
230
      {
231
        getter = iface.getMethod("get" + name);
232
      }
233
    catch (NoSuchMethodException e)
234
      {
235
        try
236
          {
237
            getter = iface.getMethod("is" + name);
238
          }
239
        catch (NoSuchMethodException ex)
240
          {
241
            throw ((AttributeNotFoundException)
242
                   new AttributeNotFoundException("The attribute, " + name +
243
                                                  ", was not found.").initCause(ex));
244
          }
245
      }
246
    Object result;
247
    try
248
      {
249
        result = getter.invoke(impl);
250
      }
251
    catch (IllegalAccessException e)
252
      {
253
        throw new ReflectionException(e, "Failed to retrieve " + name);
254
      }
255
    catch (IllegalArgumentException e)
256
      {
257
        throw new ReflectionException(e, "Failed to retrieve " + name);
258
      }
259
    catch (InvocationTargetException e)
260
      {
261
        throw new MBeanException((Exception) e.getCause(),
262
                                 "The getter of " + name +
263
                                 " threw an exception");
264
      }
265
    return result;
266
  }
267
 
268
  /**
269
   * Obtains the values of each of the specified attributes
270
   * of the management bean.  The returned list includes
271
   * those attributes that were retrieved and their
272
   * corresponding values.
273
   *
274
   * @param names the names of the attributes to retrieve.
275
   * @return a list of the retrieved attributes.
276
   * @see #setAttributes(AttributeList)
277
   */
278
  public AttributeList getAttributes(String[] names)
279
  {
280
    AttributeList list = new AttributeList(names.length);
281
    for (int a = 0; a < names.length; ++a)
282
      {
283
        try
284
          {
285
            Object value = getAttribute(names[a]);
286
            list.add(new Attribute(names[a], value));
287
          }
288
        catch (AttributeNotFoundException e)
289
          {
290
            /* Ignored */
291
          }
292
        catch (ReflectionException e)
293
          {
294
            /* Ignored */
295
          }
296
        catch (MBeanException e)
297
          {
298
            /* Ignored */
299
          }
300
      }
301
    return list;
302
  }
303
 
304
  /**
305
   * Returns the cached {@link MBeanInfo} instance for this object.  This is a
306
   * customization hook, so that subclasses can choose the caching policy
307
   * used.  The default implementation caches the value in the instance
308
   * itself, and returns this value on calls to this method.
309
   *
310
   * @return the cached {@link MBeanInfo} instance, or <code>null</code>
311
   *         if no value is cached.
312
   * @see #cacheMBeanInfo(javax.management.MBeanInfo)
313
   */
314
  protected MBeanInfo getCachedMBeanInfo()
315
  {
316
    return info;
317
  }
318
 
319
  /**
320
   * Returns the class name that will be used in the {@link MBeanInfo}
321
   * instance.  This is a customization hook, so that subclasses can
322
   * provide a custom class name.  By default, this returns the class
323
   * name from the supplied {@link MBeanInfo} instance.
324
   *
325
   * @param info the {@link MBeanInfo} instance constructed via
326
   *             reflection.
327
   * @return the class name to use in the instance.
328
   */
329
  protected String getClassName(MBeanInfo info)
330
  {
331
    return info.getClassName();
332
  }
333
 
334
  /**
335
   * Returns information on the constructors that will be used in
336
   * the {@link MBeanInfo} instance.  This is a customization hook,
337
   * so that subclasses can provide their own information on the
338
   * bean's constructors, if necessary.  By default, this method
339
   * returns <code>null</code> unless the implementation supplied
340
   * is either <code>null</code> or <code>this</code>.  This default
341
   * implementation prevents the use of
342
   * {@link MBeanServer#createMBean} in cases where the bean is
343
   * not created as a subclass of {@link StandardMBean}.
344
   *
345
   * @param constructors the constructor information created via
346
   *                     reflection.
347
   * @param impl the implementation, or <code>null</code> if this
348
   *             should be ignored.
349
   * @return the constructor information to use.
350
   */
351
  protected MBeanConstructorInfo[] getConstructors(MBeanConstructorInfo[]
352
                                                   constructors, Object impl)
353
  {
354
    if (impl == null || impl == this)
355
      return constructors;
356
    return null;
357
  }
358
 
359
  /**
360
   * Returns the description of the attribute that will be used in
361
   * the supplied {@link MBeanAttributeInfo} instance.  This is a
362
   * customization hook, so that subclasses can provide a custom
363
   * description.  By default, this calls
364
   * {@link #getDescription(MBeanFeatureInfo)} with the supplied
365
   * {@link MBeanAttributeInfo} instance.
366
   *
367
   * @param info the {@link MBeanAttributeInfo} instance constructed
368
   *             via reflection.
369
   * @return the description to use in the instance.
370
   */
371
  protected String getDescription(MBeanAttributeInfo info)
372
  {
373
    return getDescription((MBeanFeatureInfo) info);
374
  }
375
 
376
  /**
377
   * Returns the description of the constructor that will be used in
378
   * the supplied {@link MBeanConstructorInfo} instance.  This is a
379
   * customization hook, so that subclasses can provide a custom
380
   * description.  By default, this calls
381
   * {@link #getDescription(MBeanFeatureInfo)} with the supplied
382
   * {@link MBeanConstructorInfo} instance.
383
   *
384
   * @param info the {@link MBeanConstructorInfo} instance constructed
385
   *             via reflection.
386
   * @return the description to use in the instance.
387
   */
388
  protected String getDescription(MBeanConstructorInfo info)
389
  {
390
    return getDescription((MBeanFeatureInfo) info);
391
  }
392
 
393
  /**
394
   * Returns the description of the nth parameter of the constructor
395
   * that will be used in the supplied {@link MBeanParameterInfo}
396
   * instance.  This is a customization hook, so that subclasses
397
   * can provide a custom description.  By default, this calls
398
   * <code>param.getDescription()</code>.
399
   *
400
   * @param info the {@link MBeanConstructorInfo} instance constructed
401
   *             via reflection.
402
   * @param param the {@link MBeanParameterInfo} instance constructed
403
   *             via reflection.
404
   * @param n the number of the parameter, in order to link it to the
405
   *          information on the constructor.
406
   * @return the description to use in the instance.
407
   */
408
  protected String getDescription(MBeanConstructorInfo info,
409
                                  MBeanParameterInfo param, int n)
410
  {
411
    return param.getDescription();
412
  }
413
 
414
  /**
415
   * Returns the description of the supplied feature that
416
   * will be used in the supplied {@link MBeanFeatureInfo}
417
   * instance.  This is a customization hook, so that subclasses
418
   * can provide a custom description.  By default, this calls
419
   * <code>info.getDescription()</code>.  This method is also called
420
   * by default for the more specific description methods for attributes,
421
   * constructors and operations.
422
   *
423
   * @param info the {@link MBeanFeatureInfo} instance constructed
424
   *             via reflection.
425
   * @return the description to use in the instance.
426
   */
427
  protected String getDescription(MBeanFeatureInfo info)
428
  {
429
    return info.getDescription();
430
  }
431
 
432
  /**
433
   * Returns the description of the bean that will be used in the
434
   * supplied {@link MBeanInfo} instance.  This is a customization
435
   * hook, so that subclasses can provide a custom description.  By
436
   * default, this calls <code>info.getDescription()</code>.
437
   *
438
   * @param info the {@link MBeanInfo} instance constructed
439
   *             via reflection.
440
   * @return the description to use in the instance.
441
   */
442
  protected String getDescription(MBeanInfo info)
443
  {
444
    return info.getDescription();
445
  }
446
 
447
  /**
448
   * Returns the description of the operation that will be used in
449
   * the supplied {@link MBeanOperationInfo} instance.  This is a
450
   * customization hook, so that subclasses can provide a custom
451
   * description.  By default, this calls
452
   * {@link #getDescription(MBeanFeatureInfo)} with the supplied
453
   * {@link MBeanOperationInfo} instance.
454
   *
455
   * @param info the {@link MBeanOperationInfo} instance constructed
456
   *             via reflection.
457
   * @return the description to use in the instance.
458
   */
459
  protected String getDescription(MBeanOperationInfo info)
460
  {
461
    return getDescription((MBeanFeatureInfo) info);
462
  }
463
 
464
  /**
465
   * Returns the description of the nth parameter of the operation
466
   * that will be used in the supplied {@link MBeanParameterInfo}
467
   * instance.  This is a customization hook, so that subclasses
468
   * can provide a custom description.  By default, this calls
469
   * <code>param.getDescription()</code>.
470
   *
471
   * @param info the {@link MBeanOperationInfo} instance constructed
472
   *             via reflection.
473
   * @param param the {@link MBeanParameterInfo} instance constructed
474
   *             via reflection.
475
   * @param n the number of the parameter, in order to link it to the
476
   *          information on the operation.
477
   * @return the description to use in the instance.
478
   */
479
  protected String getDescription(MBeanOperationInfo info,
480
                                  MBeanParameterInfo param, int n)
481
  {
482
    return param.getDescription();
483
  }
484
 
485
  /**
486
   * Returns the impact of the operation that will be used in the
487
   * supplied {@link MBeanOperationInfo} instance.  This is a
488
   * customization hook, so that subclasses can provide a custom
489
   * impact flag.  By default, this returns
490
   * <code>info.getImpact()</code>.
491
   *
492
   * @param info the {@link MBeanOperationInfo} instance constructed
493
   *             via reflection.
494
   * @return the impact flag to use in the instance.
495
   */
496
  protected int getImpact(MBeanOperationInfo info)
497
  {
498
    return info.getImpact();
499
  }
500
 
501
  /**
502
   * Returns the instance that implements this bean.
503
   *
504
   * @return the implementation.
505
   */
506
  public Object getImplementation()
507
  {
508
    return impl;
509
  }
510
 
511
  /**
512
   * Returns the class of the instance that implements this bean.
513
   *
514
   * @return the implementation class.
515
   */
516
  public Class<?> getImplementationClass()
517
  {
518
    return impl.getClass();
519
  }
520
 
521
  /**
522
   * <p>
523
   * Returns an information object which lists the attributes
524
   * and actions associated with the management bean.  This
525
   * implementation proceeds as follows:
526
   * </p>
527
   * <ol>
528
   * <li>{@link #getCachedMBeanInfo()} is called to obtain
529
   * the cached instance.  If this returns a non-null value,
530
   * this value is returned.</li>
531
   * <li>If there is no cached value, then the method proceeds
532
   * to create one. During this process, the customization hooks
533
   * detailed in this class are called to allow the values used
534
   * to be overrided:
535
   * <ul>
536
   * <li>For each attribute,
537
   * {@link #getDescription(MBeanAttributeInfo)} is called.</li>
538
   * <li>For each constructor,
539
   * {@link #getDescription(MBeanConstructorInfo)} is called,
540
   * along with {@link #getDescription(MBeanConstructorInfo,
541
   * MBeanParameterInfo, int)} and
542
   * {@link #getParameterName(MBeanConstructorInfo,
543
   * MBeanParameterInfo, int)} for each parameter.</li>
544
   * <li>The constructors may be replaced as a whole by
545
   * a call to
546
   * {@link #getConstructors(MBeanConstructorInfo[], Object)}.</li>
547
   * <li>For each operation,
548
   * {@link #getDescription(MBeanOperationInfo)} and
549
   * {@link #getImpact(MBeanOperationInfo)} are called,
550
   * along with {@link #getDescription(MBeanOperationInfo,
551
   * MBeanParameterInfo, int)} and
552
   * {@link #getParameterName(MBeanOperationInfo,
553
   * MBeanParameterInfo, int)} for each parameter.</li>
554
   * <li>{@link #getClassName(MBeanInfo)} and
555
   * {@link #getDescription(MBeanInfo)} are called to customise
556
   * the basic information about the class.</li>
557
   * </ul>
558
   * </li>
559
   * <li>Finally, {@link #cacheMBeanInfo(MBeanInfo)} is called
560
   * with the created instance before it is returned.</li>
561
   * </ol>
562
   *
563
   * @return a description of the management bean, including
564
   *         all exposed attributes and actions.
565
   */
566
  public MBeanInfo getMBeanInfo()
567
  {
568
    MBeanInfo info = getCachedMBeanInfo();
569
    if (info != null)
570
      return info;
571
    Method[] methods = iface.getMethods();
572
    Map<String,Method[]> attributes = new HashMap<String,Method[]>();
573
    List<MBeanOperationInfo> operations = new ArrayList<MBeanOperationInfo>();
574
    for (int a = 0; a < methods.length; ++a)
575
      {
576
        String name = methods[a].getName();
577
        if (((name.startsWith("get") &&
578
              methods[a].getReturnType() != Void.TYPE) ||
579
             (name.startsWith("is") &&
580
              methods[a].getReturnType() == Boolean.TYPE)) &&
581
            methods[a].getParameterTypes().length == 0)
582
          {
583
            Method[] amethods;
584
            String attrib;
585
            if (name.startsWith("is"))
586
              attrib = name.substring(2);
587
            else
588
              attrib = name.substring(3);
589
            if (attributes.containsKey(attrib))
590
              amethods = (Method[]) attributes.get(attrib);
591
            else
592
              {
593
                amethods = new Method[2];
594
                attributes.put(attrib, amethods);
595
              }
596
            amethods[0] = methods[a];
597
          }
598
        else if (name.startsWith("set") &&
599
                 methods[a].getReturnType() == Void.TYPE &&
600
                 methods[a].getParameterTypes().length == 1)
601
          {
602
            Method[] amethods;
603
            String attrib = name.substring(3);
604
            if (attributes.containsKey(attrib))
605
              amethods = (Method[]) attributes.get(attrib);
606
            else
607
              {
608
                amethods = new Method[2];
609
                attributes.put(attrib, amethods);
610
              }
611
            amethods[1] = methods[a];
612
          }
613
        else
614
          operations.add(new MBeanOperationInfo(methods[a].getName(),
615
                                                methods[a]));
616
      }
617
    List<MBeanAttributeInfo> attribs = new ArrayList<MBeanAttributeInfo>(attributes.size());
618
    for (Map.Entry<String,Method[]> entry : attributes.entrySet())
619
      {
620
        Method[] amethods = entry.getValue();
621
        try
622
          {
623
            attribs.add(new MBeanAttributeInfo(entry.getKey(),
624
                                               entry.getKey(),
625
                                               amethods[0], amethods[1]));
626
          }
627
        catch (IntrospectionException e)
628
          {
629
            /* Shouldn't happen; both shouldn't be null */
630
            throw new IllegalStateException("The two methods passed to " +
631
                                            "the MBeanAttributeInfo " +
632
                                            "constructor for " + entry +
633
                                            "were null.", e);
634
          }
635
      }
636
    MBeanAttributeInfo[] ainfo = new MBeanAttributeInfo[attribs.size()];
637
    for (int a = 0; a < ainfo.length; ++a)
638
      {
639
        MBeanAttributeInfo oldInfo = (MBeanAttributeInfo) attribs.get(a);
640
        String desc = getDescription(oldInfo);
641
        ainfo[a] = new MBeanAttributeInfo(oldInfo.getName(),
642
                                          oldInfo.getType(), desc,
643
                                          oldInfo.isReadable(),
644
                                          oldInfo.isWritable(),
645
                                          oldInfo.isIs());
646
      }
647
    Constructor<?>[] cons = impl.getClass().getConstructors();
648
    MBeanConstructorInfo[] cinfo = new MBeanConstructorInfo[cons.length];
649
    for (int a = 0; a < cinfo.length; ++a)
650
      {
651
        MBeanConstructorInfo oldInfo = new MBeanConstructorInfo(cons[a].getName(),
652
                                                                cons[a]);
653
        String desc = getDescription(oldInfo);
654
        MBeanParameterInfo[] params = oldInfo.getSignature();
655
        MBeanParameterInfo[] pinfo = new MBeanParameterInfo[params.length];
656
        for (int b = 0; b < pinfo.length; ++b)
657
          {
658
            String pdesc = getDescription(oldInfo, params[b], b);
659
            String pname = getParameterName(oldInfo, params[b], b);
660
            pinfo[b] = new MBeanParameterInfo(pname, params[b].getType(),
661
                                              pdesc);
662
          }
663
        cinfo[a] = new MBeanConstructorInfo(oldInfo.getName(), desc,
664
                                            pinfo);
665
      }
666
    cinfo = getConstructors(cinfo, impl);
667
    MBeanOperationInfo[] oinfo = new MBeanOperationInfo[operations.size()];
668
    for (int a = 0; a < oinfo.length; ++a)
669
      {
670
        MBeanOperationInfo oldInfo = (MBeanOperationInfo) operations.get(a);
671
        String desc = getDescription(oldInfo);
672
        int impact = getImpact(oldInfo);
673
        MBeanParameterInfo[] params = oldInfo.getSignature();
674
        MBeanParameterInfo[] pinfo = new MBeanParameterInfo[params.length];
675
        for (int b = 0; b < pinfo.length; ++b)
676
          {
677
            String pdesc = getDescription(oldInfo, params[b], b);
678
            String pname = getParameterName(oldInfo, params[b], b);
679
            pinfo[b] = new MBeanParameterInfo(pname, params[b].getType(),
680
                                              pdesc);
681
          }
682
        oinfo[a] = new MBeanOperationInfo(oldInfo.getName(), desc, pinfo,
683
                                          oldInfo.getReturnType(), impact);
684
      }
685
    info = new MBeanInfo(impl.getClass().getName(), impl.getClass().getName(),
686
                         ainfo, cinfo, oinfo, null);
687
    String cname = getClassName(info);
688
    String desc = getDescription(info);
689
    MBeanNotificationInfo[] ninfo = null;
690
    if (impl instanceof NotificationBroadcaster)
691
      ninfo = ((NotificationBroadcaster) impl).getNotificationInfo();
692
    info = new MBeanInfo(cname, desc, ainfo, cinfo, oinfo, ninfo);
693
    cacheMBeanInfo(info);
694
    return info;
695
  }
696
 
697
  /**
698
   * Returns the interface for this management bean.
699
   *
700
   * @return the management interface.
701
   */
702
  public final Class<?> getMBeanInterface()
703
  {
704
    return iface;
705
  }
706
 
707
  /**
708
   * Returns the name of the nth parameter of the constructor
709
   * that will be used in the supplied {@link MBeanParameterInfo}
710
   * instance.  This is a customization hook, so that subclasses
711
   * can provide a custom name.  By default, this calls
712
   * <code>param.getName()</code>.
713
   *
714
   * @param info the {@link MBeanConstructorInfo} instance constructed
715
   *             via reflection.
716
   * @param param the {@link MBeanParameterInfo} instance constructed
717
   *             via reflection.
718
   * @param n the number of the parameter, in order to link it to the
719
   *          information on the constructor.
720
   * @return the name to use in the instance.
721
   */
722
  protected String getParameterName(MBeanConstructorInfo info,
723
                                    MBeanParameterInfo param, int n)
724
  {
725
    return param.getName();
726
  }
727
 
728
  /**
729
   * Returns the name of the nth parameter of the operation
730
   * that will be used in the supplied {@link MBeanParameterInfo}
731
   * instance.  This is a customization hook, so that subclasses
732
   * can provide a custom name.  By default, this calls
733
   * <code>param.getName()</code>.
734
   *
735
   * @param info the {@link MBeanOperationInfo} instance constructed
736
   *             via reflection.
737
   * @param param the {@link MBeanParameterInfo} instance constructed
738
   *             via reflection.
739
   * @param n the number of the parameter, in order to link it to the
740
   *          information on the operation.
741
   * @return the name to use in the instance.
742
   */
743
  protected String getParameterName(MBeanOperationInfo info,
744
                                    MBeanParameterInfo param, int n)
745
  {
746
    return param.getName();
747
  }
748
 
749
  /**
750
   * Invokes the specified action on the management bean using
751
   * the supplied parameters.  The signature of the action is
752
   * specified by a {@link String} array, which lists the classes
753
   * corresponding to each parameter.  The class loader used to
754
   * load these classes is the same as that used for loading the
755
   * management bean itself.
756
   *
757
   * @param name the name of the action to invoke.
758
   * @param params the parameters used to call the action.
759
   * @param signature the signature of the action.
760
   * @return the return value of the action.
761
   * @throws MBeanException if the action throws an exception.  The
762
   *                        thrown exception is the cause of this
763
   *                        exception.
764
   * @throws ReflectionException if an exception occurred in trying
765
   *                             to use the reflection interface
766
   *                             to invoke the action.  The
767
   *                             thrown exception is the cause of
768
   *                             this exception.
769
   */
770
  public Object invoke(String name, Object[] params, String[] signature)
771
    throws MBeanException, ReflectionException
772
  {
773
    if (name.startsWith("get") || name.startsWith("is") ||
774
        name.startsWith("set"))
775
      throw new ReflectionException(new NoSuchMethodException(),
776
                                    "Invocation of an attribute " +
777
                                    "method is disallowed.");
778
    ClassLoader loader = getClass().getClassLoader();
779
    Class<?>[] sigTypes;
780
    if (signature != null)
781
      {
782
        sigTypes = new Class<?>[signature.length];
783
        for (int a = 0; a < signature.length; ++a)
784
          try
785
            {
786
              sigTypes[a] = Class.forName(signature[a], true, loader);
787
            }
788
          catch (ClassNotFoundException e)
789
            {
790
              throw new ReflectionException(e, "The class, " + signature[a] +
791
                                            ", in the method signature " +
792
                                            "could not be loaded.");
793
            }
794
      }
795
    else
796
      sigTypes = null;
797
    Method method;
798
    try
799
      {
800
        method = iface.getMethod(name, sigTypes);
801
      }
802
    catch (NoSuchMethodException e)
803
      {
804
        throw new ReflectionException(e, "The method, " + name +
805
                                      ", could not be found.");
806
      }
807
    Object result;
808
    try
809
      {
810
        result = method.invoke(impl, params);
811
      }
812
    catch (IllegalAccessException e)
813
      {
814
        throw new ReflectionException(e, "Failed to call " + name);
815
      }
816
    catch (IllegalArgumentException e)
817
      {
818
        throw new ReflectionException(e, "Failed to call " + name);
819
      }
820
    catch (InvocationTargetException e)
821
      {
822
        throw new MBeanException((Exception) e.getCause(), "The method "
823
                                 + name + " threw an exception");
824
      }
825
    return result;
826
  }
827
 
828
  /**
829
   * Sets the value of the specified attribute of the
830
   * management bean.  The management bean should perform
831
   * a lookup for the named attribute, and sets its value
832
   * using the associated setter method, if possible.
833
   *
834
   * @param attribute the attribute to set.
835
   * @throws AttributeNotFoundException if the attribute does not
836
   *                                    correspond to an attribute
837
   *                                    of the bean.
838
   * @throws InvalidAttributeValueException if the value is invalid
839
   *                                        for this particular
840
   *                                        attribute of the bean.
841
   * @throws MBeanException if setting the attribute causes
842
   *                        the bean to throw an exception (which
843
   *                        becomes the cause of this exception).
844
   * @throws ReflectionException if an exception occurred in trying
845
   *                             to use the reflection interface
846
   *                             to lookup the attribute.  The
847
   *                             thrown exception is the cause of
848
   *                             this exception.
849
   * @see #getAttribute(String)
850
   */
851
  public void setAttribute(Attribute attribute)
852
    throws AttributeNotFoundException, InvalidAttributeValueException,
853
           MBeanException, ReflectionException
854
  {
855
    String name = attribute.getName();
856
    String attName = name.substring(0, 1).toUpperCase() + name.substring(1);
857
    Object val = attribute.getValue();
858
    try
859
      {
860
        getMutator(attName, val.getClass()).invoke(impl, new Object[] { val });
861
      }
862
    catch (IllegalAccessException e)
863
      {
864
        throw new ReflectionException(e, "Failed to set " + name);
865
      }
866
    catch (IllegalArgumentException e)
867
      {
868
        throw ((InvalidAttributeValueException)
869
               new InvalidAttributeValueException(attribute.getValue() +
870
                                                  " is an invalid value for " +
871
                                                  name).initCause(e));
872
      }
873
    catch (InvocationTargetException e)
874
      {
875
        throw new MBeanException(e, "The getter of " + name +
876
                                 " threw an exception");
877
      }
878
  }
879
 
880
  /**
881
   * Sets the value of each of the specified attributes
882
   * to that supplied by the {@link Attribute} object.
883
   * The returned list contains the attributes that were
884
   * set and their new values.
885
   *
886
   * @param attributes the attributes to set.
887
   * @return a list of the changed attributes.
888
   * @see #getAttributes(AttributeList)
889
   */
890
  public AttributeList setAttributes(AttributeList attributes)
891
  {
892
    AttributeList list = new AttributeList(attributes.size());
893
    Iterator<Object> it = attributes.iterator();
894
    while (it.hasNext())
895
      {
896
        try
897
          {
898
            Attribute attrib = (Attribute) it.next();
899
            setAttribute(attrib);
900
            list.add(attrib);
901
          }
902
        catch (AttributeNotFoundException e)
903
          {
904
            /* Ignored */
905
          }
906
        catch (InvalidAttributeValueException e)
907
          {
908
            /* Ignored */
909
          }
910
        catch (ReflectionException e)
911
          {
912
            /* Ignored */
913
          }
914
        catch (MBeanException e)
915
          {
916
            /* Ignored */
917
          }
918
      }
919
    return list;
920
  }
921
 
922
  /**
923
   * Replaces the implementation of the interface used by this
924
   * instance with the one specified.  The new implementation
925
   * must be non-null and implement the interface specified on
926
   * construction of this instance.
927
   *
928
   * @throws IllegalArgumentException if <code>impl</code> is <code>null</code>.
929
   * @throws NotCompliantMBeanException if <code>impl</code> doesn't implement
930
   *                                    the interface or a method appears
931
   *                                    in the interface that doesn't comply
932
   *                                    with the naming conventions.
933
   */
934
  public void setImplementation(Object impl)
935
    throws NotCompliantMBeanException
936
  {
937
    if (impl == null)
938
      throw new IllegalArgumentException("The specified implementation is null.");
939
    if (!(iface.isInstance(impl)))
940
      throw new NotCompliantMBeanException("The instance, " + impl +
941
                                           ", is not an instance of " + iface);
942
    this.impl = impl;
943
  }
944
 
945
  /**
946
   * Returns the mutator method for a particular attribute name
947
   * with a parameter type matching that of the given value.
948
   *
949
   * @param name the name of the attribute.
950
   * @param type the type of the parameter.
951
   * @return the appropriate mutator method.
952
   * @throws AttributeNotFoundException if a method can't be found.
953
   */
954
  private Method getMutator(String name, Class<?> type)
955
    throws AttributeNotFoundException
956
  {
957
    String mutator = "set" + name;
958
    Exception ex = null;
959
    try
960
      {
961
        return iface.getMethod(mutator, type);
962
      }
963
    catch (NoSuchMethodException e)
964
      {
965
        /* Ignored; we'll try harder instead */
966
        ex = e;
967
      }
968
    /* Special cases */
969
    if (type == Boolean.class)
970
      try
971
        {
972
          return iface.getMethod(mutator, Boolean.TYPE);
973
        }
974
      catch (NoSuchMethodException e)
975
        {
976
          throw ((AttributeNotFoundException)
977
                 new AttributeNotFoundException("The attribute, " + name +
978
                                                ", was not found.").initCause(e));
979
        }
980
    if (type == Byte.class)
981
      try
982
        {
983
          return iface.getMethod(mutator, Byte.TYPE);
984
        }
985
      catch (NoSuchMethodException e)
986
        {
987
          throw ((AttributeNotFoundException)
988
                 new AttributeNotFoundException("The attribute, " + name +
989
                                                ", was not found.").initCause(e));
990
        }
991
    if (type == Character.class)
992
      try
993
        {
994
          return iface.getMethod(mutator, Character.TYPE);
995
        }
996
      catch (NoSuchMethodException e)
997
        {
998
          throw ((AttributeNotFoundException)
999
                 new AttributeNotFoundException("The attribute, " + name +
1000
                                                ", was not found.").initCause(e));
1001
        }
1002
    if (type == Double.class)
1003
      try
1004
        {
1005
          return iface.getMethod(mutator, Double.TYPE);
1006
        }
1007
      catch (NoSuchMethodException e)
1008
        {
1009
          throw ((AttributeNotFoundException)
1010
                 new AttributeNotFoundException("The attribute, " + name +
1011
                                                ", was not found.").initCause(e));
1012
        }
1013
    if (type == Float.class)
1014
      try
1015
        {
1016
          return iface.getMethod(mutator, Float.TYPE);
1017
        }
1018
      catch (NoSuchMethodException e)
1019
        {
1020
          throw ((AttributeNotFoundException)
1021
                 new AttributeNotFoundException("The attribute, " + name +
1022
                                                ", was not found.").initCause(e));
1023
        }
1024
    if (type == Integer.class)
1025
      try
1026
        {
1027
          return iface.getMethod(mutator, Integer.TYPE);
1028
        }
1029
      catch (NoSuchMethodException e)
1030
        {
1031
          throw ((AttributeNotFoundException)
1032
                 new AttributeNotFoundException("The attribute, " + name +
1033
                                                ", was not found.").initCause(e));
1034
        }
1035
    if (type == Long.class)
1036
      try
1037
        {
1038
          return iface.getMethod(mutator, Long.TYPE);
1039
        }
1040
      catch (NoSuchMethodException e)
1041
        {
1042
          throw ((AttributeNotFoundException)
1043
                 new AttributeNotFoundException("The attribute, " + name +
1044
                                                ", was not found.").initCause(e));
1045
        }
1046
    if (type == Short.class)
1047
      try
1048
        {
1049
          return iface.getMethod(mutator, Short.TYPE);
1050
        }
1051
      catch (NoSuchMethodException e)
1052
        {
1053
          throw ((AttributeNotFoundException)
1054
                 new AttributeNotFoundException("The attribute, " + name +
1055
                                                ", was not found.").initCause(e));
1056
        }
1057
    /* Superclasses and interfaces */
1058
    for (Class<?> i : type.getInterfaces())
1059
      try
1060
        {
1061
          return getMutator(name, i);
1062
        }
1063
      catch (AttributeNotFoundException e)
1064
        {
1065
          ex = e;
1066
        }
1067
    Class<?> sclass = type.getSuperclass();
1068
    if (sclass != null && sclass != Object.class)
1069
      try
1070
        {
1071
          return getMutator(name, sclass);
1072
        }
1073
      catch (AttributeNotFoundException e)
1074
        {
1075
          ex = e;
1076
        }
1077
    /* If we get this far, give up */
1078
    throw ((AttributeNotFoundException)
1079
           new AttributeNotFoundException("The attribute, " + name +
1080
                                          ", was not found.").initCause(ex));
1081
  }
1082
 
1083
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.