1. /*
  2. * @(#)StandardMBean.java 1.21 04/05/03
  3. *
  4. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  5. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
  6. */
  7. package javax.management;
  8. import java.io.PrintWriter;
  9. import java.io.StringWriter;
  10. import java.lang.reflect.UndeclaredThrowableException;
  11. import com.sun.jmx.trace.Trace;
  12. import com.sun.jmx.mbeanserver.MetaData;
  13. import com.sun.jmx.mbeanserver.StandardMetaDataImpl;
  14. /**
  15. * <p>An MBean whose management interface is determined by reflection
  16. * on a Java interface.</p>
  17. *
  18. * <p>This class brings more flexibility to the notion of Management
  19. * Interface in the use of Standard MBeans. Straightforward use of
  20. * the patterns for Standard MBeans described in the JMX Specification
  21. * means that there is a fixed relationship between the implementation
  22. * class of an MBean and its management interface (i.e., if the
  23. * implementation class is Thing, the management interface must be
  24. * ThingMBean). This class makes it possible to keep the convenience
  25. * of specifying the management interface with a Java interface,
  26. * without requiring that there be any naming relationship between the
  27. * implementation and interface classes.</p>
  28. *
  29. * <p>By making a DynamicMBean out of an MBean, this class makes
  30. * it possible to select any interface implemented by the MBean as its
  31. * management interface, provided that it complies with JMX patterns
  32. * (i.e., attributes defined by getter/setter etc...).</p>
  33. *
  34. * <p> This class also provides hooks that make it possible to supply
  35. * custom descriptions and names for the {@link MBeanInfo} returned by
  36. * the DynamicMBean interface.</p>
  37. *
  38. * <p>Using this class, an MBean can be created with any
  39. * implementation class name <i>Impl</i> and with a management
  40. * interface defined (as for current Standard MBeans) by any interface
  41. * <i>Intf</i>, in one of two general ways:</p>
  42. *
  43. * <ul>
  44. *
  45. * <li>Using the public constructor
  46. * {@link #StandardMBean(java.lang.Object, java.lang.Class)
  47. * StandardMBean(impl,interface)}:
  48. * <pre>
  49. * MBeanServer mbs;
  50. * ...
  51. * Impl impl = new Impl(...);
  52. * StandardMBean mbean = new StandardMBean(impl, Intf.class);
  53. * mbs.registerMBean(mbean, objectName);
  54. * </pre></li>
  55. *
  56. * <li>Subclassing StandardMBean:
  57. * <pre>
  58. * public class Impl extends StandardMBean implements Intf {
  59. * public Impl() {
  60. * super(Intf.class);
  61. * }
  62. * // implement methods of Intf
  63. * }
  64. *
  65. * [...]
  66. *
  67. * MBeanServer mbs;
  68. * ....
  69. * Impl impl = new Impl();
  70. * mbs.registerMBean(impl, objectName);
  71. * </pre></li>
  72. *
  73. * </ul>
  74. *
  75. * <p>In either case, the class <i>Impl</i> must implement the
  76. * interface <i>Intf</i>.</p>
  77. *
  78. * <p>Standard MBeans based on the naming relationship between
  79. * implementation and interface classes are of course still
  80. * available.</p>
  81. *
  82. * @since 1.5
  83. * @since.unbundled JMX 1.2
  84. */
  85. public class StandardMBean implements DynamicMBean {
  86. /** The name of this class to be used for tracing */
  87. private final static String dbgTag = "StandardMBean";
  88. /**
  89. * Override StandardMetaDataImpl in order to redefine the caching
  90. * of MBean Information.
  91. **/
  92. private final class StandardMBeanMeta extends StandardMetaDataImpl {
  93. /** Constructor... **/
  94. public StandardMBeanMeta() {
  95. super(false);
  96. }
  97. /**
  98. * We need to override this method because some methods
  99. * from BaseMetaDataImpl rely on MetaData#getMBeanInfo().
  100. * <p>
  101. * The default caching implemented in StandardMetaDataImpl
  102. * will not work if two instances of class <var>c</var> can have
  103. * different management interfaces, which is made possible
  104. * by {@link StandardMBean}
  105. *
  106. * @return StandardMBean.this.getMBeanInfo();
  107. **/
  108. protected MBeanInfo getCachedMBeanInfo(Class beanClass) {
  109. if (beanClass == null) return null;
  110. // Need the synchronized block as long as implementation
  111. // and mbeanInterface are not final.
  112. //
  113. synchronized (StandardMBean.this) {
  114. // Consistency checking: beanClass must be equal
  115. // to StandardMBean.this.getImplementationClass().
  116. //
  117. final Class implementationClass =
  118. StandardMBean.this.getImplementationClass();
  119. if (implementationClass == null) return null;
  120. if (!beanClass.equals(implementationClass)) return null;
  121. // Should always come here (null cases excepted)...
  122. //
  123. return StandardMBean.this.getMBeanInfo();
  124. }
  125. }
  126. /**
  127. * We need to override this method because some methods
  128. * from StandardMetaDataImpl rely on it.
  129. * <p>
  130. * The default caching implemented in StandardMetaDataImpl
  131. * will not work if two instances of class <var>c</var> can have
  132. * different management interfaces, which is made possible
  133. * by {@link StandardMBean}
  134. *
  135. * @return StandardMBean.this.getMBeanInterface();
  136. **/
  137. protected Class getCachedMBeanInterface(Class beanClass) {
  138. // Need the synchronized block as long as implementation
  139. // and mbeanInterface are not final.
  140. //
  141. synchronized (StandardMBean.this) {
  142. // Consistency checking: beanClass must be equal
  143. // to StandardMBean.this.getImplementationClass().
  144. //
  145. final Class implementationClass =
  146. StandardMBean.this.getImplementationClass();
  147. if (implementationClass == null) return null;
  148. if (!beanClass.equals(implementationClass)) return null;
  149. // Should always come here (null cases excepted)...
  150. //
  151. return StandardMBean.this.getMBeanInterface();
  152. }
  153. }
  154. /**
  155. * Need to override this method because default caching implemented
  156. * in StandardMetaDataImpl will not work if two instances of class
  157. * <var>c</var> can have different <var>mbeanInterface</var>.
  158. * <p>
  159. * The default caching mechanism in StandardMetaDataImpl uses
  160. * class static {@link java.util.WeakHashMap WeakHashMaps} - and
  161. * is common to all instance of StandardMetaData - hence to
  162. * all MBeanServer.
  163. * <p>
  164. * As this default mechanism might not always work for
  165. * StandardMBean objects (may have several instances of class
  166. * <var>c</var> with different MBean interfaces), we disable
  167. * this default caching by defining an empty
  168. * <code>cacheMBeanInfo()</code> method.
  169. * <p>
  170. * Caching in our case is no longer performed by the MetaData
  171. * object, but by the StandardMBean object.
  172. **/
  173. protected void cacheMBeanInfo(Class c,Class mbeanInterface,
  174. MBeanInfo mbeanInfo) {
  175. }
  176. }
  177. /**
  178. * The management interface.
  179. **/
  180. private Class mbeanInterface;
  181. /**
  182. * The implementation.
  183. **/
  184. private Object implementation;
  185. /**
  186. * The MetaData object used for invoking reflection.
  187. **/
  188. private final StandardMetaDataImpl meta;
  189. /**
  190. * The cached MBeanInfo.
  191. **/
  192. private MBeanInfo cachedMBeanInfo;
  193. /**
  194. * Make a DynamicMBean out of <var>implementation</var>, using the
  195. * specified <var>mbeanInterface</var> class.
  196. * @param implementation The implementation of this MBean.
  197. * If <code>null</code>, and null implementation is allowed,
  198. * then the implementation is assumed to be <var>this</var>.
  199. * @param mbeanInterface The Management Interface exported by this
  200. * MBean's implementation. If <code>null</code>, then this
  201. * object will use standard JMX design pattern to determine
  202. * the management interface associated with the given
  203. * implementation.
  204. * @param nullImplementationAllowed <code>true</code> if a null
  205. * implementation is allowed. If null implementation is allowed,
  206. * and a null implementation is passed, then the implementation
  207. * is assumed to be <var>this</var>.
  208. * @exception IllegalArgumentException if the given
  209. * <var>implementation</var> is null, and null is not allowed.
  210. * @exception NotCompliantMBeanException if the <var>mbeanInterface</var>
  211. * does not follow JMX design patterns for Management Interfaces, or
  212. * if the given <var>implementation</var> does not implement the
  213. * specified interface.
  214. **/
  215. private StandardMBean(Object implementation, Class mbeanInterface,
  216. boolean nullImplementationAllowed)
  217. throws NotCompliantMBeanException {
  218. if (implementation == null) {
  219. if (nullImplementationAllowed) implementation = this;
  220. else throw new IllegalArgumentException("implementation is null");
  221. }
  222. this.meta = new StandardMBeanMeta();
  223. setImplementation(implementation,mbeanInterface);
  224. }
  225. /**
  226. * <p>Make a DynamicMBean out of the object
  227. * <var>implementation</var>, using the specified
  228. * <var>mbeanInterface</var> class.</p>
  229. *
  230. * @param implementation The implementation of this MBean.
  231. * @param mbeanInterface The Management Interface exported by this
  232. * MBean's implementation. If <code>null</code>, then this
  233. * object will use standard JMX design pattern to determine
  234. * the management interface associated with the given
  235. * implementation.
  236. *
  237. * @exception IllegalArgumentException if the given
  238. * <var>implementation</var> is null.
  239. * @exception NotCompliantMBeanException if the <var>mbeanInterface</var>
  240. * does not follow JMX design patterns for Management Interfaces, or
  241. * if the given <var>implementation</var> does not implement the
  242. * specified interface.
  243. **/
  244. public StandardMBean(Object implementation,Class mbeanInterface)
  245. throws NotCompliantMBeanException {
  246. this(implementation,mbeanInterface,false);
  247. }
  248. /**
  249. * <p>Make a DynamicMBean out of <var>this</var>, using the specified
  250. * <var>mbeanInterface</var> class.</p>
  251. *
  252. * <p>Call {@link #StandardMBean(java.lang.Object, java.lang.Class)
  253. * this(this,mbeanInterface)}.
  254. * This constructor is reserved to subclasses.</p>
  255. *
  256. * @param mbeanInterface The Management Interface exported by this
  257. * MBean.
  258. *
  259. * @exception NotCompliantMBeanException if the <var>mbeanInterface</var>
  260. * does not follow JMX design patterns for Management Interfaces, or
  261. * if <var>this</var> does not implement the specified interface.
  262. **/
  263. protected StandardMBean(Class mbeanInterface)
  264. throws NotCompliantMBeanException {
  265. this(null,mbeanInterface,true);
  266. }
  267. /**
  268. * <p>Replace the implementation object wrapped in this
  269. * object.</p>
  270. *
  271. * @param implementation The new implementation of this MBean.
  272. * The <code>implementation</code> object must implement the MBean
  273. * interface that was supplied when this
  274. * <code>StandardMBean</code> was constructed.
  275. *
  276. * @exception IllegalArgumentException if the given
  277. * <var>implementation</var> is null.
  278. *
  279. * @exception NotCompliantMBeanException if the given
  280. * <var>implementation</var> does not implement the MBean
  281. * interface that was supplied at construction.
  282. *
  283. * @see #getImplementation
  284. **/
  285. public synchronized void setImplementation(Object implementation)
  286. throws NotCompliantMBeanException {
  287. setImplementation(implementation, getMBeanInterface());
  288. }
  289. /**
  290. * Replace the implementation and management interface wrapped in
  291. * this object.
  292. * @param implementation The new implementation of this MBean.
  293. * @param mbeanInterface The Management Interface exported by this
  294. * MBean's implementation. If <code>null</code>, then this
  295. * object will use standard JMX design patterns to determine
  296. * the management interface associated with the given
  297. * implementation.
  298. * @exception IllegalArgumentException if the given
  299. * <var>implementation</var> is null.
  300. * @exception NotCompliantMBeanException if the <var>mbeanInterface</var>
  301. * does not follow JMX design patterns for Management Interfaces, or
  302. * if the given <var>implementation</var> does not implement the
  303. * specified interface.
  304. **/
  305. private synchronized void setImplementation(Object implementation,
  306. Class mbeanInterface)
  307. throws NotCompliantMBeanException {
  308. if (implementation == null)
  309. throw new IllegalArgumentException("implementation is null");
  310. // test compliance
  311. this.meta.testCompliance(implementation.getClass(),mbeanInterface);
  312. // flush the cache...
  313. cacheMBeanInfo(null);
  314. this.implementation = implementation;
  315. this.mbeanInterface = mbeanInterface;
  316. if (this.mbeanInterface == null)
  317. this.mbeanInterface =
  318. meta.getStandardMBeanInterface(implementation.getClass());
  319. }
  320. /**
  321. * Get the implementation of this MBean.
  322. * @return The implementation of this MBean.
  323. *
  324. * @see #setImplementation
  325. **/
  326. public synchronized Object getImplementation() {
  327. return implementation;
  328. }
  329. /**
  330. * Get the Management Interface of this MBean.
  331. * @return The management interface of this MBean.
  332. **/
  333. public final synchronized Class getMBeanInterface() {
  334. return mbeanInterface;
  335. }
  336. /**
  337. * Get the class of the implementation of this MBean.
  338. * @return The class of the implementation of this MBean.
  339. **/
  340. public synchronized Class getImplementationClass() {
  341. if (implementation == null) return null;
  342. return implementation.getClass();
  343. }
  344. // ------------------------------------------------------------------
  345. // From the DynamicMBean interface.
  346. // ------------------------------------------------------------------
  347. public Object getAttribute(String attribute)
  348. throws AttributeNotFoundException,
  349. MBeanException, ReflectionException {
  350. return meta.getAttribute(getImplementation(),attribute);
  351. }
  352. // ------------------------------------------------------------------
  353. // From the DynamicMBean interface.
  354. // ------------------------------------------------------------------
  355. public void setAttribute(Attribute attribute)
  356. throws AttributeNotFoundException,
  357. InvalidAttributeValueException, MBeanException,
  358. ReflectionException {
  359. meta.setAttribute(getImplementation(),attribute);
  360. }
  361. // ------------------------------------------------------------------
  362. // From the DynamicMBean interface.
  363. // ------------------------------------------------------------------
  364. public AttributeList getAttributes(String[] attributes) {
  365. try {
  366. return meta.getAttributes(getImplementation(),attributes);
  367. } catch (ReflectionException x) {
  368. final RuntimeException r =
  369. new UndeclaredThrowableException(x,x.getMessage());
  370. throw new RuntimeOperationsException(r,x.getMessage());
  371. }
  372. }
  373. // ------------------------------------------------------------------
  374. // From the DynamicMBean interface.
  375. // ------------------------------------------------------------------
  376. public AttributeList setAttributes(AttributeList attributes) {
  377. try {
  378. return meta.setAttributes(getImplementation(),attributes);
  379. } catch (ReflectionException x) {
  380. final RuntimeException r =
  381. new UndeclaredThrowableException(x,x.getMessage());
  382. throw new RuntimeOperationsException(r,x.getMessage());
  383. }
  384. }
  385. // ------------------------------------------------------------------
  386. // From the DynamicMBean interface.
  387. // ------------------------------------------------------------------
  388. public Object invoke(String actionName, Object params[],
  389. String signature[])
  390. throws MBeanException, ReflectionException {
  391. return meta.invoke(getImplementation(),actionName,params,signature);
  392. }
  393. /**
  394. * Get the {@link MBeanInfo} for this MBean.
  395. * <p>
  396. * This method implements
  397. * {@link javax.management.DynamicMBean#getMBeanInfo()
  398. * DynamicMBean.getMBeanInfo()}.
  399. * <p>
  400. * This method first calls {@link #getCachedMBeanInfo()} in order to
  401. * retrieve the cached MBeanInfo for this MBean, if any. If the
  402. * MBeanInfo returned by {@link #getCachedMBeanInfo()} is not null,
  403. * then it is returned.<br>
  404. * Otherwise, this method builds a default MBeanInfo for this MBean,
  405. * using the Management Interface specified for this MBean.
  406. * <p>
  407. * While building the MBeanInfo, this method calls the customization
  408. * hooks that make it possible for subclasses to supply their custom
  409. * descriptions, parameter names, etc...<br>
  410. * Finally, it calls {@link #cacheMBeanInfo(javax.management.MBeanInfo)
  411. * cacheMBeanInfo()} in order to cache the new MBeanInfo.
  412. * @return The cached MBeanInfo for that MBean, if not null, or a
  413. * newly built MBeanInfo if none was cached.
  414. **/
  415. public MBeanInfo getMBeanInfo() {
  416. try {
  417. final MBeanInfo cached = getCachedMBeanInfo();
  418. if (cached != null) return (MBeanInfo)cached;
  419. } catch (RuntimeException x) {
  420. debug("getMBeanInfo","failed to get cached MBeanInfo: "+x);
  421. debugX("getMBeanInfo",x);
  422. }
  423. if (isTraceOn()) {
  424. trace("getMBeanInfo", "Building MBeanInfo for "+
  425. getImplementationClass().getName());
  426. }
  427. final MBeanInfo bi;
  428. final Object impl;
  429. try {
  430. synchronized (this) {
  431. impl = getImplementation();
  432. bi = buildStandardMBeanInfo();
  433. }
  434. } catch (NotCompliantMBeanException x) {
  435. final RuntimeException r =
  436. new UndeclaredThrowableException(x,x.getMessage());
  437. throw new RuntimeOperationsException(r,x.getMessage());
  438. }
  439. final String cname = getClassName(bi);
  440. final String text = getDescription(bi);
  441. final MBeanConstructorInfo[] ctors = getConstructors(bi,impl);
  442. final MBeanAttributeInfo[] attrs = getAttributes(bi);
  443. final MBeanOperationInfo[] ops = getOperations(bi);
  444. final MBeanNotificationInfo[] ntfs = getNotifications(bi);
  445. final MBeanInfo nmbi =
  446. new MBeanInfo(cname,text,attrs,ctors,ops,ntfs);
  447. try { cacheMBeanInfo(nmbi); } catch (RuntimeException x) {
  448. debug("cacheMBeanInfo","failed to cache MBeanInfo: "+x);
  449. debugX("cacheMBeanInfo",x);
  450. }
  451. return nmbi;
  452. }
  453. /**
  454. * Customization hook:
  455. * Get the className that will be used in the MBeanInfo returned by
  456. * this MBean.
  457. * <br>
  458. * Subclasses may redefine this method in order to supply their
  459. * custom class name. The default implementation returns
  460. * {@link MBeanInfo#getClassName() info.getClassName()}.
  461. * @param info The default MBeanInfo derived by reflection.
  462. * @return the class name for the new MBeanInfo.
  463. **/
  464. protected String getClassName(MBeanInfo info) {
  465. if (info == null) return getImplementationClass().getName();
  466. return info.getClassName();
  467. }
  468. /**
  469. * Customization hook:
  470. * Get the description that will be used in the MBeanInfo returned by
  471. * this MBean.
  472. * <br>
  473. * Subclasses may redefine this method in order to supply their
  474. * custom MBean description. The default implementation returns
  475. * {@link MBeanInfo#getDescription() info.getDescription()}.
  476. * @param info The default MBeanInfo derived by reflection.
  477. * @return the description for the new MBeanInfo.
  478. **/
  479. protected String getDescription(MBeanInfo info) {
  480. if (info == null) return null;
  481. return info.getDescription();
  482. }
  483. /**
  484. * <p>Customization hook:
  485. * Get the description that will be used in the MBeanFeatureInfo
  486. * returned by this MBean.</p>
  487. *
  488. * <p>Subclasses may redefine this method in order to supply
  489. * their custom description. The default implementation returns
  490. * {@link MBeanFeatureInfo#getDescription()
  491. * info.getDescription()}.</p>
  492. *
  493. * <p>This method is called by
  494. * {@link #getDescription(MBeanAttributeInfo)},
  495. * {@link #getDescription(MBeanOperationInfo)},
  496. * {@link #getDescription(MBeanConstructorInfo)}.</p>
  497. *
  498. * @param info The default MBeanFeatureInfo derived by reflection.
  499. * @return the description for the given MBeanFeatureInfo.
  500. **/
  501. protected String getDescription(MBeanFeatureInfo info) {
  502. if (info == null) return null;
  503. return info.getDescription();
  504. }
  505. /**
  506. * Customization hook:
  507. * Get the description that will be used in the MBeanAttributeInfo
  508. * returned by this MBean.
  509. *
  510. * <p>Subclasses may redefine this method in order to supply their
  511. * custom description. The default implementation returns {@link
  512. * #getDescription(MBeanFeatureInfo)
  513. * getDescription((MBeanFeatureInfo) info)}.
  514. * @param info The default MBeanAttributeInfo derived by reflection.
  515. * @return the description for the given MBeanAttributeInfo.
  516. **/
  517. protected String getDescription(MBeanAttributeInfo info) {
  518. return getDescription((MBeanFeatureInfo)info);
  519. }
  520. /**
  521. * Customization hook:
  522. * Get the description that will be used in the MBeanConstructorInfo
  523. * returned by this MBean.
  524. * <br>
  525. * Subclasses may redefine this method in order to supply their
  526. * custom description.
  527. * The default implementation returns {@link
  528. * #getDescription(MBeanFeatureInfo)
  529. * getDescription((MBeanFeatureInfo) info)}.
  530. * @param info The default MBeanConstructorInfo derived by reflection.
  531. * @return the description for the given MBeanConstructorInfo.
  532. **/
  533. protected String getDescription(MBeanConstructorInfo info) {
  534. return getDescription((MBeanFeatureInfo)info);
  535. }
  536. /**
  537. * Customization hook:
  538. * Get the description that will be used for the <var>sequence</var>
  539. * MBeanParameterInfo of the MBeanConstructorInfo returned by this MBean.
  540. * <br>
  541. * Subclasses may redefine this method in order to supply their
  542. * custom description. The default implementation returns
  543. * {@link MBeanParameterInfo#getDescription() param.getDescription()}.
  544. *
  545. * @param ctor The default MBeanConstructorInfo derived by reflection.
  546. * @param param The default MBeanParameterInfo derived by reflection.
  547. * @param sequence The sequence number of the parameter considered
  548. * ("0" for the first parameter, "1" for the second parameter,
  549. * etc...).
  550. * @return the description for the given MBeanParameterInfo.
  551. **/
  552. protected String getDescription(MBeanConstructorInfo ctor,
  553. MBeanParameterInfo param,
  554. int sequence) {
  555. if (param == null) return null;
  556. return param.getDescription();
  557. }
  558. /**
  559. * Customization hook:
  560. * Get the name that will be used for the <var>sequence</var>
  561. * MBeanParameterInfo of the MBeanConstructorInfo returned by this MBean.
  562. * <br>
  563. * Subclasses may redefine this method in order to supply their
  564. * custom parameter name. The default implementation returns
  565. * {@link MBeanParameterInfo#getName() param.getName()}.
  566. *
  567. * @param ctor The default MBeanConstructorInfo derived by reflection.
  568. * @param param The default MBeanParameterInfo derived by reflection.
  569. * @param sequence The sequence number of the parameter considered
  570. * ("0" for the first parameter, "1" for the second parameter,
  571. * etc...).
  572. * @return the name for the given MBeanParameterInfo.
  573. **/
  574. protected String getParameterName(MBeanConstructorInfo ctor,
  575. MBeanParameterInfo param,
  576. int sequence) {
  577. if (param == null) return null;
  578. return param.getName();
  579. }
  580. /**
  581. * Customization hook:
  582. * Get the description that will be used in the MBeanOperationInfo
  583. * returned by this MBean.
  584. * <br>
  585. * Subclasses may redefine this method in order to supply their
  586. * custom description. The default implementation returns
  587. * {@link #getDescription(MBeanFeatureInfo)
  588. * getDescription((MBeanFeatureInfo) info)}.
  589. * @param info The default MBeanOperationInfo derived by reflection.
  590. * @return the description for the given MBeanOperationInfo.
  591. **/
  592. protected String getDescription(MBeanOperationInfo info) {
  593. return getDescription((MBeanFeatureInfo)info);
  594. }
  595. /**
  596. * Customization hook:
  597. * Get the <var>impact</var> flag of the operation that will be used in
  598. * the MBeanOperationInfo returned by this MBean.
  599. * <br>
  600. * Subclasses may redefine this method in order to supply their
  601. * custom impact flag. The default implementation returns
  602. * {@link MBeanOperationInfo#getImpact() info.getImpact()}.
  603. * @param info The default MBeanOperationInfo derived by reflection.
  604. * @return the impact flag for the given MBeanOperationInfo.
  605. **/
  606. protected int getImpact(MBeanOperationInfo info) {
  607. if (info == null) return MBeanOperationInfo.UNKNOWN;
  608. return info.getImpact();
  609. }
  610. /**
  611. * Customization hook:
  612. * Get the name that will be used for the <var>sequence</var>
  613. * MBeanParameterInfo of the MBeanOperationInfo returned by this MBean.
  614. * <br>
  615. * Subclasses may redefine this method in order to supply their
  616. * custom parameter name. The default implementation returns
  617. * {@link MBeanParameterInfo#getName() param.getName()}.
  618. *
  619. * @param op The default MBeanOperationInfo derived by reflection.
  620. * @param param The default MBeanParameterInfo derived by reflection.
  621. * @param sequence The sequence number of the parameter considered
  622. * ("0" for the first parameter, "1" for the second parameter,
  623. * etc...).
  624. * @return the name to use for the given MBeanParameterInfo.
  625. **/
  626. protected String getParameterName(MBeanOperationInfo op,
  627. MBeanParameterInfo param,
  628. int sequence) {
  629. if (param == null) return null;
  630. return param.getName();
  631. }
  632. /**
  633. * Customization hook:
  634. * Get the description that will be used for the <var>sequence</var>
  635. * MBeanParameterInfo of the MBeanOperationInfo returned by this MBean.
  636. * <br>
  637. * Subclasses may redefine this method in order to supply their
  638. * custom description. The default implementation returns
  639. * {@link MBeanParameterInfo#getDescription() param.getDescription()}.
  640. *
  641. * @param op The default MBeanOperationInfo derived by reflection.
  642. * @param param The default MBeanParameterInfo derived by reflection.
  643. * @param sequence The sequence number of the parameter considered
  644. * ("0" for the first parameter, "1" for the second parameter,
  645. * etc...).
  646. * @return the description for the given MBeanParameterInfo.
  647. **/
  648. protected String getDescription(MBeanOperationInfo op,
  649. MBeanParameterInfo param,
  650. int sequence) {
  651. if (param == null) return null;
  652. return param.getDescription();
  653. }
  654. /**
  655. * Customization hook:
  656. * Get the MBeanConstructorInfo[] that will be used in the MBeanInfo
  657. * returned by this MBean.
  658. * <br>
  659. * By default, this method returns <code>null</code> if the wrapped
  660. * implementation is not <var>this</var>. Indeed, if the wrapped
  661. * implementation is not this object itself, it will not be possible
  662. * to recreate a wrapped implementation by calling the implementation
  663. * constructors through <code>MBeanServer.createMBean(...)</code>.<br>
  664. * Otherwise, if the wrapped implementation is <var>this</var>,
  665. * <var>ctors</var> is returned.
  666. * <br>
  667. * Subclasses may redefine this method in order to modify this
  668. * behavior, if needed.
  669. * @param ctors The default MBeanConstructorInfo[] derived by reflection.
  670. * @param impl The wrapped implementation. If <code>null</code> is
  671. * passed, the wrapped implementation is ignored and
  672. * <var>ctors</var> is returned.
  673. * @return the MBeanConstructorInfo[] for the new MBeanInfo.
  674. **/
  675. protected MBeanConstructorInfo[]
  676. getConstructors(MBeanConstructorInfo[] ctors, Object impl) {
  677. if (ctors == null) return null;
  678. if (impl != null && impl != this) return null;
  679. return ctors;
  680. }
  681. /**
  682. * Customization hook:
  683. * Get the MBeanNotificationInfo[] that will be used in the MBeanInfo
  684. * returned by this MBean.
  685. * <br>
  686. * Subclasses may redefine this method in order to supply their
  687. * custom notifications.
  688. * @param info The default MBeanInfo derived by reflection.
  689. * @return the MBeanNotificationInfo[] for the new MBeanInfo.
  690. **/
  691. // Private because not needed - the StandardMBeanMetaDataImpl allready
  692. // calls getNotificationInfo() on the implementation....
  693. private MBeanNotificationInfo[]
  694. getNotifications(MBeanInfo info) {
  695. if (info == null) return null;
  696. return info.getNotifications();
  697. }
  698. /**
  699. * Customization hook:
  700. * Return the MBeanInfo cached for this object.
  701. *
  702. * <p>Subclasses may redefine this method in order to implement their
  703. * own caching policy. The default implementation stores one
  704. * {@link MBeanInfo} object per instance.
  705. *
  706. * @return The cached MBeanInfo, or null if no MBeanInfo is cached.
  707. *
  708. * @see #cacheMBeanInfo(MBeanInfo)
  709. **/
  710. protected synchronized MBeanInfo getCachedMBeanInfo() {
  711. return cachedMBeanInfo;
  712. }
  713. /**
  714. * Customization hook:
  715. * cache the MBeanInfo built for this object.
  716. *
  717. * <p>Subclasses may redefine this method in order to implement
  718. * their own caching policy. The default implementation stores
  719. * <code>info</code> in this instance. A subclass can define
  720. * other policies, such as not saving <code>info</code> (so it is
  721. * reconstructed every time {@link #getMBeanInfo()} is called) or
  722. * sharing a unique {@link MBeanInfo} object when several
  723. * <code>StandardMBean</code> instances have equal {@link
  724. * MBeanInfo} values.
  725. *
  726. * @param info the new <code>MBeanInfo</code> to cache. Any
  727. * previously cached value is discarded. This parameter may be
  728. * null, in which case there is no new cached value.
  729. **/
  730. protected synchronized void cacheMBeanInfo(MBeanInfo info) {
  731. cachedMBeanInfo = info;
  732. }
  733. // ------------------------------------------------------------------
  734. // Build the defaullt standard MBeanInfo.
  735. // ------------------------------------------------------------------
  736. private synchronized MBeanInfo buildStandardMBeanInfo()
  737. throws NotCompliantMBeanException {
  738. return meta.buildMBeanInfo(getImplementationClass(),
  739. getMBeanInterface());
  740. }
  741. // ------------------------------------------------------------------
  742. // Build the custom MBeanConstructorInfo[]
  743. // ------------------------------------------------------------------
  744. private MBeanConstructorInfo[]
  745. getConstructors(MBeanInfo info,Object impl) {
  746. final MBeanConstructorInfo[] ctors =
  747. getConstructors(info.getConstructors(),impl);
  748. final MBeanConstructorInfo[] nctors;
  749. if (ctors != null) {
  750. final int ctorlen = ctors.length;
  751. nctors = new MBeanConstructorInfo[ctorlen];
  752. for (int i=0; i<ctorlen; i++) {
  753. final MBeanConstructorInfo c = ctors[i];
  754. final MBeanParameterInfo[] params = c.getSignature();
  755. final MBeanParameterInfo[] nps;
  756. if (params != null) {
  757. final int plen = params.length;
  758. nps = new MBeanParameterInfo[plen];
  759. for (int ii=0;ii<plen;ii++) {
  760. MBeanParameterInfo p = params[ii];
  761. final String name = getParameterName(c,p,ii);
  762. final String text = getDescription(c,p,ii);
  763. nps[ii] = new MBeanParameterInfo(name,
  764. p.getType(),
  765. text);
  766. }
  767. } else {
  768. nps = null;
  769. }
  770. nctors[i] = new MBeanConstructorInfo(c.getName(),
  771. getDescription(c),
  772. nps);
  773. }
  774. } else {
  775. nctors = null;
  776. }
  777. return nctors;
  778. }
  779. // ------------------------------------------------------------------
  780. // Build the custom MBeanOperationInfo[]
  781. // ------------------------------------------------------------------
  782. private MBeanOperationInfo[] getOperations(MBeanInfo info) {
  783. final MBeanOperationInfo[] ops = info.getOperations();
  784. final MBeanOperationInfo[] nops;
  785. if (ops != null) {
  786. final int oplen = ops.length;
  787. nops = new MBeanOperationInfo[oplen];
  788. for (int i=0; i<oplen; i++) {
  789. final MBeanOperationInfo o = ops[i];
  790. final MBeanParameterInfo[] params = o.getSignature();
  791. final MBeanParameterInfo[] nps;
  792. if (params != null) {
  793. final int plen = params.length;
  794. nps = new MBeanParameterInfo[plen];
  795. for (int ii=0;ii<plen;ii++) {
  796. MBeanParameterInfo p = params[ii];
  797. final String name = getParameterName(o,p,ii);
  798. final String text = getDescription(o,p,ii);
  799. nps[ii] = new MBeanParameterInfo(name,
  800. p.getType(),
  801. text);
  802. }
  803. } else {
  804. nps = null;
  805. }
  806. nops[i] = new MBeanOperationInfo(o.getName(),
  807. getDescription(o),
  808. nps,
  809. o.getReturnType(),
  810. getImpact(o));
  811. }
  812. } else {
  813. nops = null;
  814. }
  815. return nops;
  816. }
  817. // ------------------------------------------------------------------
  818. // Build the custom MBeanAttributeInfo[]
  819. // ------------------------------------------------------------------
  820. private MBeanAttributeInfo[] getAttributes(MBeanInfo info) {
  821. final MBeanAttributeInfo[] atts = info.getAttributes();
  822. final MBeanAttributeInfo[] natts;
  823. if (atts != null) {
  824. final int attlen = atts.length;
  825. natts = new MBeanAttributeInfo[attlen];
  826. for (int i=0; i<attlen; i++) {
  827. final MBeanAttributeInfo a = atts[i];
  828. natts[i] = new MBeanAttributeInfo(a.getName(),
  829. a.getType(),
  830. getDescription(a),
  831. a.isReadable(),
  832. a.isWritable(),
  833. a.isIs());
  834. }
  835. } else {
  836. natts = null;
  837. }
  838. return natts;
  839. }
  840. // private stuff
  841. private static boolean isTraceOn() {
  842. return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MISC);
  843. }
  844. private static void trace(String clz, String func, String info) {
  845. Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MISC, clz, func, info);
  846. }
  847. private static void trace(String func, String info) {
  848. trace(dbgTag, func, info);
  849. }
  850. private static boolean isDebugOn() {
  851. return Trace.isSelected(Trace.LEVEL_DEBUG, Trace.INFO_MISC);
  852. }
  853. private static void debug(String clz, String func, String info) {
  854. Trace.send(Trace.LEVEL_DEBUG, Trace.INFO_MISC, clz, func, info);
  855. }
  856. private static void debug(String func, String info) {
  857. debug(dbgTag, func, info);
  858. }
  859. private static void debugX(String func,Throwable e) {
  860. if (isDebugOn()) {
  861. final StringWriter s = new StringWriter();
  862. e.printStackTrace(new PrintWriter(s));
  863. final String stack = s.toString();
  864. debug(dbgTag,func,"Exception caught in "+ func+"(): "+e);
  865. debug(dbgTag,func,stack);
  866. // java.lang.System.err.println("**** Exception caught in "+
  867. // func+"(): "+e);
  868. // java.lang.System.err.println(stack);
  869. }
  870. }
  871. }