blob: 918f0de14c15a9caf4b4ed4f03f5150f71c1ad48 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Portions Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25/*
26 * @author IBM Corp.
27 *
28 * Copyright IBM Corp. 1999-2000. All rights reserved.
29 */
30
31package javax.management.modelmbean;
32
33import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER;
34import com.sun.jmx.mbeanserver.GetPropertyAction;
35
36import java.io.IOException;
37import java.io.ObjectInputStream;
38import java.io.ObjectOutputStream;
39import java.io.ObjectStreamField;
40import java.security.AccessController;
41import java.util.logging.Level;
42
43import javax.management.Descriptor;
44import javax.management.DescriptorAccess;
45import javax.management.MBeanNotificationInfo;
46import javax.management.RuntimeOperationsException;
47
48/**
49 * The ModelMBeanNotificationInfo object describes a notification emitted
50 * by a ModelMBean.
51 * It is a subclass of MBeanNotificationInfo with the addition of an
52 * associated Descriptor and an implementation of the Descriptor interface.
53 * <P>
54 * The fields in the descriptor are defined, but not limited to,
55 * the following:
56 * <PRE>
57 * name : notification name
58 * descriptorType : must be "notification"
59 * severity : 0-6 where 0: unknown; 1: non-recoverable;
60 * 2: critical, failure; 3: major, severe;
61 * 4: minor, marginal, error; 5: warning;
62 * 6: normal, cleared, informative
63 * messageID : unique key for message text (to allow translation,
64 * analysis)
65 * messageText : text of notification
66 * log : T - log message F - do not log message
67 * logfile : string fully qualified file name appropriate for
68 * operating system
69 * visibility : 1-4 where 1: always visible 4: rarely visible
70 * presentationString : xml formatted string to allow presentation of data
71 * </PRE>
72 * The default descriptor contains the name, descriptorType,
73 * displayName and severity(=6) fields. The default value of the name
74 * and displayName fields is the name of the Notification class (as
75 * specified by the <code>name</code> parameter of the
76 * ModelMBeanNotificationInfo constructor).
77 *
78 * <p>The <b>serialVersionUID</b> of this class is <code>-7445681389570207141L</code>.
79 *
80 * @since 1.5
81 */
82
83// Sun Microsystems, Sept. 2002: Revisited for JMX 1.2 (DF)
84//
85@SuppressWarnings("serial") // serialVersionUID is not constant
86public class ModelMBeanNotificationInfo
87 extends MBeanNotificationInfo
88 implements DescriptorAccess {
89
90 // Serialization compatibility stuff:
91 // Two serial forms are supported in this class. The selected form
92 // depends on system property "jmx.serial.form":
93 // - "1.0" for JMX 1.0
94 // - any other value for JMX 1.1 and higher
95 //
96 // Serial version for old serial form
97 private static final long oldSerialVersionUID = -5211564525059047097L;
98 //
99 // Serial version for new serial form
100 private static final long newSerialVersionUID = -7445681389570207141L;
101 //
102 // Serializable fields in old serial form
103 private static final ObjectStreamField[] oldSerialPersistentFields =
104 {
105 new ObjectStreamField("notificationDescriptor", Descriptor.class),
106 new ObjectStreamField("currClass", String.class)
107 };
108 //
109 // Serializable fields in new serial form
110 private static final ObjectStreamField[] newSerialPersistentFields =
111 {
112 new ObjectStreamField("notificationDescriptor", Descriptor.class)
113 };
114 //
115 // Actual serial version and serial form
116 private static final long serialVersionUID;
117 /**
118 * @serialField notificationDescriptor Descriptor The descriptor
119 * containing the appropriate metadata for this instance
120 */
121 private static final ObjectStreamField[] serialPersistentFields;
122 private static boolean compat = false;
123 static {
124 try {
125 GetPropertyAction act = new GetPropertyAction("jmx.serial.form");
126 String form = AccessController.doPrivileged(act);
127 compat = (form != null && form.equals("1.0"));
128 } catch (Exception e) {
129 // OK: No compat with 1.0
130 }
131 if (compat) {
132 serialPersistentFields = oldSerialPersistentFields;
133 serialVersionUID = oldSerialVersionUID;
134 } else {
135 serialPersistentFields = newSerialPersistentFields;
136 serialVersionUID = newSerialVersionUID;
137 }
138 }
139 //
140 // END Serialization compatibility stuff
141
142 /**
143 * @serial The descriptor containing the appropriate metadata for
144 * this instance
145 */
146 private Descriptor notificationDescriptor;
147
148 private static final String currClass = "ModelMBeanNotificationInfo";
149
150 /**
151 * Constructs a ModelMBeanNotificationInfo object with a default
152 * descriptor.
153 *
154 * @param notifTypes The array of strings (in dot notation) containing
155 * the notification types that may be emitted.
156 * @param name The name of the Notification class.
157 * @param description A human readable description of the
158 * Notification. Optional.
159 **/
160 public ModelMBeanNotificationInfo(String[] notifTypes,
161 String name,
162 String description) {
163 this(notifTypes,name,description,null);
164 }
165
166 /**
167 * Constructs a ModelMBeanNotificationInfo object.
168 *
169 * @param notifTypes The array of strings (in dot notation)
170 * containing the notification types that may be emitted.
171 * @param name The name of the Notification class.
172 * @param description A human readable description of the Notification.
173 * Optional.
174 * @param descriptor An instance of Descriptor containing the
175 * appropriate metadata for this instance of the
176 * MBeanNotificationInfo. If it is null a default descriptor
177 * will be created. If the descriptor does not contain all the
178 * fields "name", "descriptorType", "displayName" and "severity",
179 * the missing ones are added with their default values.
180 *
181 * @exception RuntimeOperationsException Wraps an
182 * {@link IllegalArgumentException}. The descriptor is invalid, or
183 * descriptor field "name" is present but not equal to parameter name, or
184 * descriptor field "descriptorType" is present but not equal to "notification".
185 *
186 **/
187 public ModelMBeanNotificationInfo(String[] notifTypes,
188 String name,
189 String description,
190 Descriptor descriptor) {
191 super(notifTypes, name, description);
192 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
193 MODELMBEAN_LOGGER.logp(Level.FINER,
194 ModelMBeanNotificationInfo.class.getName(),
195 "ModelMBeanNotificationInfo", "Entry");
196 }
197 notificationDescriptor = validDescriptor(descriptor);
198 }
199
200 /**
201 * Constructs a new ModelMBeanNotificationInfo object from this
202 * ModelMBeanNotfication Object.
203 *
204 * @param inInfo the ModelMBeanNotificationInfo to be duplicated
205 *
206 **/
207 public ModelMBeanNotificationInfo(ModelMBeanNotificationInfo inInfo) {
208 this(inInfo.getNotifTypes(),
209 inInfo.getName(),
210 inInfo.getDescription(),inInfo.getDescriptor());
211 }
212
213 /**
214 * Creates and returns a new ModelMBeanNotificationInfo which is a
215 * duplicate of this ModelMBeanNotificationInfo.
216 **/
217 public Object clone () {
218 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
219 MODELMBEAN_LOGGER.logp(Level.FINER,
220 ModelMBeanNotificationInfo.class.getName(),
221 "clone()", "Entry");
222 }
223 return(new ModelMBeanNotificationInfo(this));
224 }
225
226 /**
227 * Returns a copy of the associated Descriptor for the
228 * ModelMBeanNotificationInfo.
229 *
230 * @return Descriptor associated with the
231 * ModelMBeanNotificationInfo object.
232 *
233 * @see #setDescriptor
234 **/
235 public Descriptor getDescriptor() {
236 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
237 MODELMBEAN_LOGGER.logp(Level.FINER,
238 ModelMBeanNotificationInfo.class.getName(),
239 "getDescriptor()", "Entry");
240 }
241
242 if (notificationDescriptor == null) {
243 // Dead code. Should never happen.
244 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
245 MODELMBEAN_LOGGER.logp(Level.FINER,
246 ModelMBeanNotificationInfo.class.getName(),
247 "getDescriptor()", "Descriptor value is null, " +
248 "setting descriptor to default values");
249 }
250 notificationDescriptor = validDescriptor(null);
251 }
252
253 return((Descriptor)notificationDescriptor.clone());
254 }
255
256 /**
257 * Sets associated Descriptor (full replace) for the
258 * ModelMBeanNotificationInfo If the new Descriptor is null,
259 * then the associated Descriptor reverts to a default
260 * descriptor. The Descriptor is validated before it is
261 * assigned. If the new Descriptor is invalid, then a
262 * RuntimeOperationsException wrapping an
263 * IllegalArgumentException is thrown.
264 *
265 * @param inDescriptor replaces the Descriptor associated with the
266 * ModelMBeanNotification interface
267 *
268 * @exception RuntimeOperationsException Wraps an
269 * {@link IllegalArgumentException} for invalid Descriptor.
270 *
271 * @see #getDescriptor
272 **/
273 public void setDescriptor(Descriptor inDescriptor) {
274 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
275 MODELMBEAN_LOGGER.logp(Level.FINER,
276 ModelMBeanNotificationInfo.class.getName(),
277 "setDescriptor(Descriptor)", "Entry");
278 }
279 notificationDescriptor = validDescriptor(inDescriptor);
280 }
281
282 /**
283 * Returns a human readable string containing
284 * ModelMBeanNotificationInfo.
285 *
286 * @return a string describing this object.
287 **/
288 public String toString() {
289 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
290 MODELMBEAN_LOGGER.logp(Level.FINER,
291 ModelMBeanNotificationInfo.class.getName(),
292 "toString()", "Entry");
293 }
294
295 final StringBuilder retStr = new StringBuilder();
296
297 retStr.append("ModelMBeanNotificationInfo: ")
298 .append(this.getName());
299
300 retStr.append(" ; Description: ")
301 .append(this.getDescription());
302
303 retStr.append(" ; Descriptor: ")
304 .append(this.getDescriptor());
305
306 retStr.append(" ; Types: ");
307 String[] nTypes = this.getNotifTypes();
308 for (int i=0; i < nTypes.length; i++) {
309 if (i > 0) retStr.append(", ");
310 retStr.append(nTypes[i]);
311 }
312 return retStr.toString();
313 }
314
315
316 /**
317 * Clones the passed in Descriptor, sets default values, and checks for validity.
318 * If the Descriptor is invalid (for instance by having the wrong "name"),
319 * this indicates programming error and a RuntimeOperationsException will be thrown.
320 *
321 * The following fields will be defaulted if they are not already set:
322 * descriptorType="notification",displayName=this.getName(),
323 * name=this.getName(),severity="6"
324 *
325 *
326 * @param in Descriptor to be checked, or null which is equivalent to an
327 * empty Descriptor.
328 * @exception RuntimeOperationsException if Descriptor is invalid
329 */
330 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
331 Descriptor clone = null;
332 if (in == null) {
333 clone = new DescriptorSupport();
334 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
335 } else {
336 clone = (Descriptor) in.clone();
337 }
338
339 //Setting defaults.
340 if (clone.getFieldValue("name")==null) {
341 clone.setField("name", this.getName());
342 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName());
343 }
344 if (clone.getFieldValue("descriptorType")==null) {
345 clone.setField("descriptorType", "notification");
346 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"notification\"");
347 }
348 if (clone.getFieldValue("displayName") == null) {
349 clone.setField("displayName",this.getName());
350 MODELMBEAN_LOGGER.finer("Defaulting Descriptor displayName to " + this.getName());
351 }
352 if (clone.getFieldValue("severity") == null) {
353 clone.setField("severity", "6");
354 MODELMBEAN_LOGGER.finer("Defaulting Descriptor severity field to 6");
355 }
356
357 //Checking validity
358 if (!clone.isValid()) {
359 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
360 "The isValid() method of the Descriptor object itself returned false,"+
361 "one or more required fields are invalid. Descriptor:" + clone.toString());
362 }
363 if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) {
364 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
365 "The Descriptor \"name\" field does not match the object described. " +
366 " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name"));
367 }
368 if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("notification")) {
369 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
370 "The Descriptor \"descriptorType\" field does not match the object described. " +
371 " Expected: \"notification\" ," + " was: " + clone.getFieldValue("descriptorType"));
372 }
373
374 return clone;
375 }
376
377
378 /**
379 * Deserializes a {@link ModelMBeanNotificationInfo} from an
380 * {@link ObjectInputStream}.
381 **/
382 private void readObject(ObjectInputStream in)
383 throws IOException, ClassNotFoundException {
384 // New serial form ignores extra field "currClass"
385 in.defaultReadObject();
386 }
387
388
389 /**
390 * Serializes a {@link ModelMBeanNotificationInfo} to an
391 * {@link ObjectOutputStream}.
392 **/
393 private void writeObject(ObjectOutputStream out)
394 throws IOException {
395 if (compat) {
396 // Serializes this instance in the old serial form
397 //
398 ObjectOutputStream.PutField fields = out.putFields();
399 fields.put("notificationDescriptor", notificationDescriptor);
400 fields.put("currClass", currClass);
401 out.writeFields();
402 } else {
403 // Serializes this instance in the new serial form
404 //
405 out.defaultWriteObject();
406 }
407 }
408
409}