1. /*
  2. * @(#)file ModelMBeanNotificationInfo.java
  3. * @(#)author IBM Corp.
  4. * @(#)version 1.35
  5. * @(#)lastedit 04/02/10
  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 com.sun.jmx.mbeanserver.GetPropertyAction;
  36. import com.sun.jmx.trace.Trace;
  37. /**
  38. * The ModelMBeanNotificationInfo object describes a notification emitted
  39. * by a ModelMBean.
  40. * It is a subclass of MBeanNotificationInfo with the addition of an
  41. * associated Descriptor and an implementation of the Descriptor interface.
  42. * <P>
  43. * The fields in the descriptor are defined, but not limited to,
  44. * the following:
  45. * <PRE>
  46. * name : notification name
  47. * descriptorType : must be "notification"
  48. * severity : 0-6 where 0: unknown; 1: non-recoverable;
  49. * 2: critical, failure; 3: major, severe;
  50. * 4: minor, marginal, error; 5: warning;
  51. * 6: normal, cleared, informative
  52. * messageID : unique key for message text (to allow translation,
  53. * analysis)
  54. * messageText : text of notification
  55. * log : T - log message F - do not log message
  56. * logfile : string fully qualified file name appropriate for
  57. * operating system
  58. * visibility : 1-4 where 1: always visible 4: rarely visible
  59. * presentationString : xml formatted string to allow presentation of data
  60. * </PRE>
  61. * The default descriptor contains the name, descriptorType, displayName
  62. * and severity(=6) fields.
  63. *
  64. * @since 1.5
  65. */
  66. // Sun Microsystems, Sept. 2002: Revisited for JMX 1.2 (DF)
  67. //
  68. public class ModelMBeanNotificationInfo extends MBeanNotificationInfo
  69. implements DescriptorAccess, Cloneable
  70. {
  71. // Serialization compatibility stuff:
  72. // Two serial forms are supported in this class. The selected form
  73. // depends 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 = -5211564525059047097L;
  79. //
  80. // Serial version for new serial form
  81. private static final long newSerialVersionUID = -7445681389570207141L;
  82. //
  83. // Serializable fields in old serial form
  84. private static final ObjectStreamField[] oldSerialPersistentFields =
  85. {
  86. new ObjectStreamField("notificationDescriptor", 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("notificationDescriptor", Descriptor.class)
  94. };
  95. //
  96. // Actual serial version and serial form
  97. private static final long serialVersionUID;
  98. /**
  99. * @serialField notificationDescriptor Descriptor The descriptor
  100. * containing the appropriate metadata for this instance
  101. */
  102. private static final ObjectStreamField[] serialPersistentFields;
  103. private static boolean compat = false;
  104. static {
  105. try {
  106. PrivilegedAction act = new GetPropertyAction("jmx.serial.form");
  107. String form = (String) AccessController.doPrivileged(act);
  108. compat = (form != null && form.equals("1.0"));
  109. } catch (Exception e) {
  110. // OK: No compat with 1.0
  111. }
  112. if (compat) {
  113. serialPersistentFields = oldSerialPersistentFields;
  114. serialVersionUID = oldSerialVersionUID;
  115. } else {
  116. serialPersistentFields = newSerialPersistentFields;
  117. serialVersionUID = newSerialVersionUID;
  118. }
  119. }
  120. //
  121. // END Serialization compatibility stuff
  122. /**
  123. * @serial The descriptor containing the appropriate metadata for
  124. * this instance
  125. */
  126. private Descriptor notificationDescriptor;
  127. private static final String currClass = "ModelMBeanNotificationInfo";
  128. /**
  129. * Constructs a ModelMBeanNotificationInfo object with a default
  130. * descriptor.
  131. *
  132. * @param notifTypes The array of strings (in dot notation) containing
  133. * the notification types that may be emitted.
  134. * @param name The name of the Notification class.
  135. * @param description A human readable description of the
  136. * Notification. Optional.
  137. **/
  138. public ModelMBeanNotificationInfo(String[] notifTypes,
  139. String name,
  140. String description) {
  141. this(notifTypes,name,description,null);
  142. }
  143. /**
  144. * Constructs a ModelMBeanNotificationInfo object.
  145. *
  146. * @param notifTypes The array of strings (in dot notation)
  147. * containing the notification types that may be emitted.
  148. * @param name The name of the Notification class.
  149. * @param description A human readable description of the Notification.
  150. * Optional.
  151. * @param descriptor An instance of Descriptor containing the
  152. * appropriate metadata for this instance of the
  153. * MBeanNotificationInfo. If it is null a default descriptor
  154. * will be created. If the descriptor does not contain the
  155. * fields "displayName" or "severity" these fields are added
  156. * in the descriptor with their default values.
  157. *
  158. * @exception RuntimeOperationsException Wraps an
  159. * {@link IllegalArgumentException}. The descriptor is invalid, or
  160. * descriptor field "name" is not equal to parameter name, or
  161. * descriptor field "DescriptorType" is not equal to "notification".
  162. *
  163. **/
  164. public ModelMBeanNotificationInfo(String[] notifTypes,
  165. String name,
  166. String description,
  167. Descriptor descriptor) {
  168. super(notifTypes, name, description);
  169. if (tracing())
  170. trace("ModelMBeanNotificationInfo()","Executed");
  171. applyDescriptor(descriptor,"ModelMBeanNotificationInfo()");
  172. }
  173. /**
  174. * Constructs a new ModelMBeanNotificationInfo object from this
  175. * ModelMBeanNotfication Object.
  176. *
  177. * @param inInfo the ModelMBeanNotificationInfo to be duplicated
  178. *
  179. **/
  180. public ModelMBeanNotificationInfo(ModelMBeanNotificationInfo inInfo) {
  181. this(inInfo.getNotifTypes(),
  182. inInfo.getName(),
  183. inInfo.getDescription(),inInfo.getDescriptor());
  184. }
  185. /**
  186. * Creates and returns a new ModelMBeanNotificationInfo which is a
  187. * duplicate of this ModelMBeanNotificationInfo.
  188. **/
  189. public Object clone () {
  190. if (tracing())
  191. trace("ModelMBeanNotificationInfo.clone()","Executed");
  192. return(new ModelMBeanNotificationInfo(this));
  193. }
  194. /**
  195. * Returns a copy of the associated Descriptor for the
  196. * ModelMBeanNotificationInfo.
  197. *
  198. * @return Descriptor associated with the
  199. * ModelMBeanNotificationInfo object.
  200. *
  201. * @see #setDescriptor
  202. **/
  203. public Descriptor getDescriptor() {
  204. if (tracing())
  205. trace("ModelMBeanNotificationInfo.getDescriptor()","Executed");
  206. if (notificationDescriptor == null) {
  207. // Dead code. Should never happen.
  208. if (tracing())
  209. trace("ModelMBeanNotificationInfo.getDescriptor()",
  210. "Received null for new descriptor value, " +
  211. "setting descriptor to default values");
  212. notificationDescriptor = createDefaultDescriptor();
  213. }
  214. return((Descriptor)notificationDescriptor.clone());
  215. }
  216. /**
  217. * Sets associated Descriptor (full replace) for the
  218. * ModelMBeanNotificationInfo If the new Descriptor is null,
  219. * then the associated Descriptor reverts to a default
  220. * descriptor. The Descriptor is validated before it is
  221. * assigned. If the new Descriptor is invalid, then a
  222. * RuntimeOperationsException wrapping an
  223. * IllegalArgumentException is thrown.
  224. *
  225. * @param inDescriptor replaces the Descriptor associated with the
  226. * ModelMBeanNotification interface
  227. *
  228. * @exception RuntimeOperationsException Wraps an
  229. * {@link IllegalArgumentException} for invalid Descriptor.
  230. *
  231. * @see #getDescriptor
  232. **/
  233. public void setDescriptor(Descriptor inDescriptor) {
  234. if (tracing())
  235. trace("setDescriptor(Descriptor)",
  236. "Executed");
  237. applyDescriptor(inDescriptor,"setDescriptor(Descriptor)");
  238. }
  239. /**
  240. * Returns a human readable string containing
  241. * ModelMBeanNotificationInfo.
  242. *
  243. * @return a string describing this object.
  244. **/
  245. public String toString() {
  246. if (tracing())
  247. trace("toString()","Executed");
  248. final StringBuffer retStr = new StringBuffer();
  249. retStr.append("ModelMBeanNotificationInfo: ")
  250. .append(this.getName());
  251. retStr.append(" ; Description: ")
  252. .append(this.getDescription());
  253. retStr.append(" ; Descriptor: ")
  254. .append(this.getDescriptor());
  255. retStr.append(" ; Types: ");
  256. String[] nTypes = this.getNotifTypes();
  257. for (int i=0; i < nTypes.length; i++) {
  258. if (i > 0) retStr.append(", ");
  259. retStr.append(nTypes[i]);
  260. }
  261. return retStr.toString();
  262. }
  263. /**
  264. * Creates default descriptor for notification as follows:
  265. * descriptorType=notification,
  266. * name=this.getName(),displayname=this.getName(),severity=6
  267. **/
  268. private final Descriptor createDefaultDescriptor() {
  269. if (tracing())
  270. trace("createDefaultDescriptor()","Executed");
  271. return new DescriptorSupport(new
  272. String[] {"descriptorType=notification",
  273. ("name=" + this.getName()),
  274. ("displayName=" + this.getName()),
  275. "severity=6"});
  276. }
  277. /**
  278. * Tests that the descriptor is valid and adds appropriate default
  279. * fields not already specified. Field values must be correct for
  280. * field names.
  281. * Descriptor must have the same name as the notification,
  282. * the descriptorType field must be "notification",
  283. **/
  284. private boolean isValid(Descriptor inDesc) {
  285. boolean results = true;
  286. String badField = "none";
  287. if (inDesc == null) {
  288. badField="nullDescriptor";
  289. return false;
  290. }
  291. if (!inDesc.isValid()) {
  292. // checks for empty descriptors, null,
  293. // checks for empty name and descriptorType adn valid
  294. // values for fields.
  295. badField="invalidDescriptor";
  296. results = false;
  297. } else if (!((String)inDesc.getFieldValue("name")).
  298. equalsIgnoreCase(this.getName())) {
  299. badField="name";
  300. results = false;
  301. } else if (! ((String)inDesc.getFieldValue("descriptorType")).
  302. equalsIgnoreCase("notification")) {
  303. badField="descriptorType";
  304. results = false;
  305. }
  306. if (tracing()) trace("isValid()",("Returning " + results +
  307. ": Invalid field is " + badField));
  308. return results;
  309. }
  310. /**
  311. * The following fields will be defaulted if they are not already
  312. * set:
  313. * displayName=this.getName(),severity=6
  314. * @return the given descriptor, possibly modified.
  315. **/
  316. private final Descriptor setDefaults(Descriptor descriptor) {
  317. if ((descriptor.getFieldValue("displayName")) == null) {
  318. descriptor.setField("displayName",this.getName());
  319. }
  320. if ((descriptor.getFieldValue("severity")) == null) {
  321. descriptor.setField("severity","6");
  322. }
  323. return descriptor;
  324. }
  325. /**
  326. * Set the given descriptor as this.notificationDescriptor.
  327. * Creates a default descriptor if the given descriptor is null.
  328. * If the given descriptor is null, check its validity.
  329. * If it is valid, clones it and set the defaults fields
  330. * "displayName" and "severity", if not present.
  331. * If it is not valid, throws an exception.
  332. * This method is called both by the constructors and by
  333. * setDescriptor().
  334. * @see #setDefaults
  335. * @see #setDescriptor
  336. **/
  337. private final void applyDescriptor(Descriptor descriptor,
  338. String ftag) {
  339. if (descriptor == null) {
  340. if (tracing())
  341. trace(ftag,
  342. "Received null for new descriptor value, " +
  343. "setting descriptor to default values");
  344. notificationDescriptor = createDefaultDescriptor();
  345. } else if (isValid(descriptor)) {
  346. notificationDescriptor =
  347. setDefaults((Descriptor)descriptor.clone());
  348. } else {
  349. throw new RuntimeOperationsException(new
  350. IllegalArgumentException(
  351. "Invalid descriptor passed in parameter"),
  352. "Exception occured in ModelMBeanNotificationInfo " + ftag);
  353. }
  354. }
  355. // SUN Trace and debug functions
  356. private boolean tracing() {
  357. // return true;
  358. return Trace.isSelected(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN);
  359. }
  360. private void trace(String inClass, String inMethod, String inText) {
  361. Trace.send(Trace.LEVEL_TRACE, Trace.INFO_MODELMBEAN, inClass,
  362. inMethod, Integer.toHexString(this.hashCode()) +
  363. " " + inText);
  364. }
  365. private void trace(String inMethod, String inText) {
  366. trace(currClass, inMethod, inText);
  367. }
  368. /**
  369. * Deserializes a {@link ModelMBeanNotificationInfo} from an
  370. * {@link ObjectInputStream}.
  371. **/
  372. private void readObject(ObjectInputStream in)
  373. throws IOException, ClassNotFoundException {
  374. // New serial form ignores extra field "currClass"
  375. in.defaultReadObject();
  376. }
  377. /**
  378. * Serializes a {@link ModelMBeanNotificationInfo} to an
  379. * {@link ObjectOutputStream}.
  380. **/
  381. private void writeObject(ObjectOutputStream out)
  382. throws IOException {
  383. if (compat) {
  384. // Serializes this instance in the old serial form
  385. //
  386. ObjectOutputStream.PutField fields = out.putFields();
  387. fields.put("notificationDescriptor", notificationDescriptor);
  388. fields.put("currClass", currClass);
  389. out.writeFields();
  390. } else {
  391. // Serializes this instance in the new serial form
  392. //
  393. out.defaultWriteObject();
  394. }
  395. }
  396. }