1. /*
  2. * @(#)file ModelMBeanOperationInfo.java
  3. * @(#)author IBM Corp.
  4. * @(#)version 1.35
  5. * @(#)lastedit 03/12/19
  6. */
  7. /*
  8. * Copyright IBM Corp. 1999-2000. All rights reserved.
  9. *
  10. * The program is provided "as is" without any warranty express or implied,
  11. * including the warranty of non-infringement and the implied warranties of
  12. * merchantibility and fitness for a particular purpose. IBM will not be
  13. * liable for any damages suffered by you or any third party claim against
  14. * you regarding the Program.
  15. *
  16. * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
  17. * This software is the proprietary information of Sun Microsystems, Inc.
  18. * Use is subject to license terms.
  19. *
  20. * Copyright 2004 Sun Microsystems, Inc. Tous droits reserves.
  21. * Ce logiciel est propriete de Sun Microsystems, Inc.
  22. * Distribue par des licences qui en restreignent l'utilisation.
  23. *
  24. */
  25. package javax.management.modelmbean;
  26. import java.io.IOException;
  27. import java.io.ObjectInputStream;
  28. import java.io.ObjectOutputStream;
  29. import java.io.ObjectStreamField;
  30. import java.security.AccessController;
  31. import java.security.PrivilegedAction;
  32. import javax.management.Descriptor;
  33. import javax.management.DescriptorAccess;
  34. import javax.management.*;
  35. import java.lang.reflect.*;
  36. import com.sun.jmx.mbeanserver.GetPropertyAction;
  37. import com.sun.jmx.trace.Trace;
  38. /**
  39. * The ModelMBeanOperationInfo object describes a management operation of the ModelMBean.
  40. * It is a subclass of MBeanOperationInfo with the addition of an associated Descriptor
  41. * and an implementation of the DescriptorAccess interface.
  42. * <P>
  43. * <PRE>
  44. * The fields in the descriptor are defined, but not limited to, the following:
  45. * name : operation name
  46. * descriptorType : must be "operation"
  47. * class : class where method is defined (fully qualified)
  48. * role : must be "operation", "getter", or "setter
  49. * targetObject : object on which to execute this method
  50. * targetType : type of object reference for targetObject. Can be: ObjectReference | Handle | EJBHandle | IOR | RMIReference.
  51. * value : cached value for operation
  52. * currencyTimeLimit : how long cached value is valid
  53. * lastUpdatedTimeStamp : when cached value was set
  54. * visibility : 1-4 where 1: always visible 4: rarely visible
  55. * presentationString : xml formatted string to describe how to present operation
  56. * </PRE>
  57. * The default descriptor will have name, descriptorType, displayName and role fields set.
  58. *
  59. * <p><b>Note:</b> because of inconsistencies in previous versions of
  60. * this specification, it is recommended not to use negative or zero
  61. * values for <code>currencyTimeLimit</code>. To indicate that a
  62. * cached value is never valid, omit the
  63. * <code>currencyTimeLimit</code> field. To indicate that it is
  64. * always valid, use a very large number for this field.</p>
  65. *
  66. * @since 1.5
  67. */
  68. public class ModelMBeanOperationInfo extends MBeanOperationInfo
  69. implements DescriptorAccess
  70. {
  71. // Serialization compatibility stuff:
  72. // Two serial forms are supported in this class. The selected form depends
  73. // on system property "jmx.serial.form":
  74. // - "1.0" for JMX 1.0
  75. // - any other value for JMX 1.1 and higher
  76. //
  77. // Serial version for old serial form
  78. private static final long oldSerialVersionUID = 9087646304346171239L;
  79. //
  80. // Serial version for new serial form
  81. private static final long newSerialVersionUID = 6532732096650090465L;
  82. //
  83. // Serializable fields in old serial form
  84. private static final ObjectStreamField[] oldSerialPersistentFields =
  85. {
  86. new ObjectStreamField("operationDescriptor", Descriptor.class),
  87. new ObjectStreamField("currClass", String.class)
  88. };
  89. //
  90. // Serializable fields in new serial form
  91. private static final ObjectStreamField[] newSerialPersistentFields =
  92. {
  93. new ObjectStreamField("operationDescriptor", Descriptor.class)
  94. };
  95. //
  96. // Actual serial version and serial form
  97. private static final long serialVersionUID;
  98. /**
  99. * @serialField operationDescriptor Descriptor The descriptor containing the appropriate metadata for this instance
  100. */
  101. private static final ObjectStreamField[] serialPersistentFields;
  102. private static boolean compat = false;
  103. static {
  104. try {
  105. PrivilegedAction act = new GetPropertyAction("jmx.serial.form");
  106. String form = (String) AccessController.doPrivileged(act);
  107. compat = (form != null && form.equals("1.0"));
  108. } catch (Exception e) {
  109. // OK: No compat with 1.0
  110. }
  111. if (compat) {
  112. serialPersistentFields = oldSerialPersistentFields;
  113. serialVersionUID = oldSerialVersionUID;
  114. } else {
  115. serialPersistentFields = newSerialPersistentFields;
  116. serialVersionUID = newSerialVersionUID;
  117. }
  118. }
  119. //
  120. // END Serialization compatibility stuff
  121. /**
  122. * @serial The descriptor containing the appropriate metadata for this instance
  123. */
  124. private Descriptor operationDescriptor = createDefaultDescriptor();
  125. private static final String currClass = "ModelMBeanOperationInfo";
  126. /**
  127. * Constructs a ModelMBeanOperationInfo object with a default
  128. * descriptor.
  129. *
  130. * @param operationMethod The java.lang.reflect.Method object
  131. * describing the MBean operation.
  132. * @param description A human readable description of the operation.
  133. */
  134. public ModelMBeanOperationInfo(String description,
  135. Method operationMethod)
  136. {
  137. super(description, operationMethod);
  138. // create default descriptor
  139. if (tracing())
  140. {
  141. trace("ModelMBeanOperationInfo(String,Method)","Executed");
  142. }
  143. operationDescriptor = createDefaultDescriptor();
  144. }
  145. /**
  146. * Constructs a ModelMBeanOperationInfo object.
  147. *
  148. * @param operationMethod The java.lang.reflect.Method object
  149. * describing the MBean operation.
  150. * @param description A human readable description of the
  151. * operation.
  152. * @param descriptor An instance of Descriptor containing the
  153. * appropriate metadata for this instance of the
  154. * ModelMBeanOperationInfo. If it is null a default
  155. * descriptor will be created. If the descriptor does not
  156. * contain the fields "displayName" or "role" these fields are
  157. * added in the descriptor with their default values.
  158. *
  159. * @exception RuntimeOperationsException Wraps an
  160. * IllegalArgumentException. The descriptor is invalid, or
  161. * descriptor field "name" is not equal to operation name, or
  162. * descriptor field "DescriptorType" is not equal to
  163. * "operation", or descriptor field "role" is not equal to
  164. * "operation".
  165. *
  166. */
  167. public ModelMBeanOperationInfo(String description,
  168. Method operationMethod,
  169. Descriptor descriptor)
  170. {
  171. super(description, operationMethod);
  172. if (tracing())
  173. {
  174. trace("ModelMBeanOperationInfo(String,Method,Descriptor)","Executed");
  175. }
  176. if (descriptor == null)
  177. {
  178. if (tracing())
  179. {
  180. trace("ModelMBeanOperationInfo()","Received null for new descriptor value, setting descriptor to default values");
  181. }
  182. operationDescriptor = createDefaultDescriptor();
  183. } else
  184. {
  185. if (isValid(descriptor))
  186. {
  187. operationDescriptor = (Descriptor) descriptor.clone();
  188. } else
  189. {
  190. operationDescriptor = createDefaultDescriptor();
  191. throw new RuntimeOperationsException(new IllegalArgumentException("Invalid descriptor passed in parameter"), ("Exception occured in ModelMBeanOperationInfo constructor"));
  192. }
  193. }
  194. }
  195. /**
  196. * Constructs a ModelMBeanOperationInfo object with a default descriptor.
  197. *
  198. * @param name The name of the method.
  199. * @param description A human readable description of the operation.
  200. * @param signature MBeanParameterInfo objects describing the parameters(arguments) of the method.
  201. * @param type The type of the method's return value.
  202. * @param impact The impact of the method, one of INFO, ACTION, ACTION_INFO, UNKNOWN.
  203. */
  204. public ModelMBeanOperationInfo(String name,
  205. String description,
  206. MBeanParameterInfo[] signature,
  207. String type,
  208. int impact)
  209. {
  210. super(name, description, signature, type, impact);
  211. // create default descriptor
  212. if (tracing())
  213. {
  214. trace("ModelMBeanOperationInfo(String,String,MBeanParameterInfo[],String,int)","Executed");
  215. }
  216. operationDescriptor = createDefaultDescriptor();
  217. }
  218. /**
  219. * Constructs a ModelMBeanOperationInfo object.
  220. *
  221. * @param name The name of the method.
  222. * @param description A human readable description of the operation.
  223. * @param signature MBeanParameterInfo objects describing the parameters(arguments) of the method.
  224. * @param type The type of the method's return value.
  225. * @param impact The impact of the method, one of INFO, ACTION, ACTION_INFO, UNKNOWN.
  226. * @param descriptor An instance of Descriptor containing the appropriate metadata.
  227. * for this instance of the MBeanOperationInfo.If it is null then a default descriptor will be created.
  228. * If the descriptor does not contain the fields
  229. * "displayName" or "role" these fields are added in the descriptor with their default values.
  230. *
  231. * @exception RuntimeOperationsException Wraps an IllegalArgumentException. The descriptor is invalid, or descriptor field "name"
  232. * is not equal to operation name, or descriptor field "DescriptorType" is not equal to "operation", or descriptor field "role" is not equal to
  233. * "operation".
  234. */
  235. public ModelMBeanOperationInfo(String name,
  236. String description,
  237. MBeanParameterInfo[] signature,
  238. String type,
  239. int impact,
  240. Descriptor descriptor)
  241. {
  242. super(name, description, signature, type, impact);
  243. if (tracing())
  244. {
  245. trace("ModelMBeanOperationInfo(String,String,MBeanParameterInfo[],String,int,Descriptor)","Executed");
  246. }
  247. if (descriptor == null)
  248. {
  249. if (tracing())
  250. {
  251. trace("ModelMBeanOperationInfo()","Received null for new descriptor value, setting descriptor to default values");
  252. }
  253. operationDescriptor = createDefaultDescriptor();
  254. } else
  255. {
  256. if (isValid(descriptor))
  257. {
  258. operationDescriptor = (Descriptor) descriptor.clone();
  259. } else
  260. {
  261. operationDescriptor = createDefaultDescriptor();
  262. throw new RuntimeOperationsException(new IllegalArgumentException("Invalid descriptor passed in parameter"), ("Exception occured in ModelMBeanOperationInfo constructor"));
  263. }
  264. }
  265. }
  266. /**
  267. * Constructs a new ModelMBeanOperationInfo object from this ModelMBeanOperation Object.
  268. *
  269. * @param inInfo the ModelMBeanOperationInfo to be duplicated
  270. *
  271. */
  272. public ModelMBeanOperationInfo(ModelMBeanOperationInfo inInfo)
  273. {
  274. super(inInfo.getName(),
  275. inInfo.getDescription(),
  276. inInfo.getSignature(),
  277. inInfo.getReturnType(),
  278. inInfo.getImpact());
  279. if (tracing())
  280. {
  281. trace("ModelMBeanOperationInfo(ModelMBeanOperationInfo)","Executed");
  282. }
  283. Descriptor newDesc = inInfo.getDescriptor();
  284. if (newDesc == null)
  285. {
  286. operationDescriptor = createDefaultDescriptor();
  287. } else
  288. {
  289. if (isValid(newDesc))
  290. {
  291. operationDescriptor = (Descriptor) newDesc.clone();
  292. } else
  293. {
  294. operationDescriptor = createDefaultDescriptor();
  295. throw new RuntimeOperationsException(new IllegalArgumentException("Invalid descriptor passed in parameter"), ("Exception occured in ModelMBeanOperationInfo constructor"));
  296. }
  297. }
  298. }
  299. /**
  300. * Creates and returns a new ModelMBeanOperationInfo which is a duplicate of this ModelMBeanOperationInfo.
  301. *
  302. */
  303. public Object clone ()
  304. {
  305. if (tracing())
  306. {
  307. trace("ModelMBeanOperationInfo.clone()","Executed");
  308. }
  309. return(new ModelMBeanOperationInfo(this)) ;
  310. }
  311. /**
  312. * Returns a copy of the associated Descriptor of the
  313. * ModelMBeanOperationInfo.
  314. *
  315. * @return Descriptor associated with the
  316. * ModelMBeanOperationInfo object.
  317. *
  318. * @see #setDescriptor
  319. */
  320. public Descriptor getDescriptor()
  321. {
  322. if (tracing())
  323. {
  324. trace("ModelMBeanOperationInfo.getDescriptor()","Executed");
  325. }
  326. if (operationDescriptor == null)
  327. {
  328. operationDescriptor = createDefaultDescriptor();
  329. }
  330. return((Descriptor) operationDescriptor.clone());
  331. }
  332. /**
  333. * Sets associated Descriptor (full replace) for the
  334. * ModelMBeanOperationInfo If the new Descriptor is null, then
  335. * the associated Descriptor reverts to a default descriptor.
  336. * The Descriptor is validated before it is assigned. If the
  337. * new Descriptor is invalid, then a
  338. * RuntimeOperationsException wrapping an
  339. * IllegalArgumentException is thrown.
  340. *
  341. * @param inDescriptor replaces the Descriptor associated with the
  342. * ModelMBeanOperation.
  343. *
  344. * @exception RuntimeOperationsException Wraps an
  345. * IllegalArgumentException for invalid Descriptor.
  346. *
  347. * @see #getDescriptor
  348. */
  349. public void setDescriptor(Descriptor inDescriptor)
  350. {
  351. if (tracing())
  352. {
  353. trace("ModelMBeanOperationInfo.setDescriptor(Descriptor)","Executed");
  354. }
  355. if (inDescriptor == null)
  356. {
  357. if (tracing())
  358. {
  359. trace("ModelMBeanOperationInfo.setDescriptor()","Received null for new descriptor value, setting descriptor to default values");
  360. }
  361. operationDescriptor = createDefaultDescriptor();
  362. } else
  363. {
  364. if (isValid(inDescriptor))
  365. {
  366. operationDescriptor = (Descriptor) inDescriptor.clone();
  367. } else
  368. {
  369. throw new RuntimeOperationsException(new IllegalArgumentException("Invalid descriptor passed in parameter"), ("Exception occured in ModelMBeanOperationInfo setDescriptor"));
  370. }
  371. }
  372. }
  373. /**
  374. * Returns a string containing the entire contents of the ModelMBeanOperationInfo in human readable form.
  375. */
  376. public String toString()
  377. {
  378. if (tracing())
  379. {
  380. trace("ModelMBeanConstructorInfo.toString()","Executed");
  381. }
  382. String retStr =
  383. "ModelMBeanOperationInfo: " + this.getName() +
  384. " ; Description: " + this.getDescription() +
  385. " ; Descriptor: " + this.getDescriptor() +
  386. " ; ReturnType: " + this.getReturnType() +
  387. " ; Signature: ";
  388. MBeanParameterInfo[] pTypes = this.getSignature();
  389. for (int i=0; i < pTypes.length; i++)
  390. {
  391. retStr = retStr.concat((pTypes[i]).getType() + ", ");
  392. }
  393. return retStr;
  394. }
  395. /**
  396. * Creates default descriptor for operation as follows:
  397. * descriptorType=operation,role=operation, name=this.getName(),displayname=this.getName().
  398. */
  399. private Descriptor createDefaultDescriptor()
  400. {
  401. if (tracing())
  402. {
  403. trace("ModelMBeanOperationInfo.createDefaultDescriptor()","Executed");
  404. }
  405. return new DescriptorSupport(new String[] {"descriptorType=operation",
  406. ("name=" + this.getName()),
  407. "role=operation",
  408. ("displayname=" + this.getName())});
  409. }
  410. /**
  411. * Tests that the descriptor is valid and adds appropriate
  412. * default fields not already specified. Field values must be
  413. * correct for field names. descriptorType field must be
  414. * "operation". We do not check the targetType because a
  415. * custom implementation of ModelMBean could recognize
  416. * additional types beyond the "standard" ones. The following
  417. * fields will be defaulted if they are not already set:
  418. * role=operation,displayName=this.getName()
  419. */
  420. private boolean isValid(Descriptor inDesc)
  421. {
  422. boolean results = true;
  423. String badField = "none";
  424. // if name != this.getName
  425. // if (descriptorType != operation)
  426. // look for displayName, persistPolicy, visibility and add in
  427. if (inDesc == null)
  428. {
  429. results = false;
  430. }
  431. else if (!inDesc.isValid())
  432. { // checks for empty descriptors, null,
  433. // checks for empty name and descriptorType
  434. // and valid values for fields.
  435. results = false;
  436. } else
  437. {
  438. if (! ((String)inDesc.getFieldValue("name")).equalsIgnoreCase(this.getName()))
  439. {
  440. results = false;
  441. }
  442. if (! ((String)inDesc.getFieldValue("descriptorType")).equalsIgnoreCase("operation"))
  443. {
  444. results = false;
  445. }
  446. Object roleValue = inDesc.getFieldValue("role");
  447. if (roleValue == null)
  448. {
  449. inDesc.setField("role","operation");
  450. } else {
  451. final String role = (String)roleValue;
  452. if (!(role.equalsIgnoreCase("operation")
  453. || role.equalsIgnoreCase("setter")
  454. || role.equalsIgnoreCase("getter"))) {
  455. results = false;
  456. badField="role";
  457. }
  458. }
  459. Object targetValue = inDesc.getFieldValue("targetType");
  460. if (targetValue != null) {
  461. if (!(targetValue instanceof java.lang.String)) {
  462. results = false;
  463. badField="targetType";
  464. }
  465. }
  466. if ((inDesc.getFieldValue("displayName")) == null)
  467. {
  468. inDesc.setField("displayName",this.getName());
  469. }
  470. }
  471. if (tracing()) trace("isValid()",("Returning " + results + ": Invalid field is " + badField));
  472. return results;
  473. }
  474. // SUN Trace and debug functions
  475. private boolean tracing()
  476. {
  477. // return false;
  478. return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN);
  479. }
  480. private void trace(String inClass, String inMethod, String inText)
  481. {
  482. // System.out.println("TRACE: " + inClass + ":" + inMethod + ": " + inText);
  483. Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN, inClass,
  484. inMethod, Integer.toHexString(this.hashCode()) + " " + inText);
  485. }
  486. private void trace(String inMethod, String inText)
  487. {
  488. trace(currClass, inMethod, inText);
  489. }
  490. /**
  491. * Deserializes a {@link ModelMBeanOperationInfo} from an {@link ObjectInputStream}.
  492. */
  493. private void readObject(ObjectInputStream in)
  494. throws IOException, ClassNotFoundException {
  495. // New serial form ignores extra field "currClass"
  496. in.defaultReadObject();
  497. }
  498. /**
  499. * Serializes a {@link ModelMBeanOperationInfo} to an {@link ObjectOutputStream}.
  500. */
  501. private void writeObject(ObjectOutputStream out)
  502. throws IOException {
  503. if (compat)
  504. {
  505. // Serializes this instance in the old serial form
  506. //
  507. ObjectOutputStream.PutField fields = out.putFields();
  508. fields.put("operationDescriptor", operationDescriptor);
  509. fields.put("currClass", currClass);
  510. out.writeFields();
  511. }
  512. else
  513. {
  514. // Serializes this instance in the new serial form
  515. //
  516. out.defaultWriteObject();
  517. }
  518. }
  519. }