blob: 2d51eccb8db09e566fced57870778b0789d57f9a [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.MBeanAttributeInfo;
45import javax.management.MBeanConstructorInfo;
46import javax.management.MBeanException;
47import javax.management.MBeanInfo;
48import javax.management.MBeanNotificationInfo;
49import javax.management.MBeanOperationInfo;
50import javax.management.RuntimeOperationsException;
51
52/**
53 * This class represents the meta data for ModelMBeans. Descriptors have been
54 * added on the meta data objects.
55 * <P>
56 * Java resources wishing to be manageable instantiate the ModelMBean using the
57 * MBeanServer's createMBean method. The resource then sets the ModelMBeanInfo
58 * and Descriptors for the ModelMBean instance. The attributes and operations
59 * exposed via the ModelMBeanInfo for the ModelMBean are accessible
60 * from MBeans, connectors/adaptors like other MBeans. Through the Descriptors,
61 * values and methods in the managed application can be defined and mapped to
62 * attributes and operations of the ModelMBean.
63 * This mapping can be defined during development in a file or dynamically and
64 * programmatically at runtime.
65 * <P>
66 * Every ModelMBean which is instantiated in the MBeanServer becomes manageable:
67 * its attributes and operations
68 * become remotely accessible through the connectors/adaptors connected to that
69 * MBeanServer.
70 * A Java object cannot be registered in the MBeanServer unless it is a JMX
71 * compliant MBean.
72 * By instantiating a ModelMBean, resources are guaranteed that the MBean is
73 * valid.
74 *
75 * MBeanException and RuntimeOperationsException must be thrown on every public
76 * method. This allows for wrapping exceptions from distributed
77 * communications (RMI, EJB, etc.)
78 *
79 * <p>The <b>serialVersionUID</b> of this class is
80 * <code>-1935722590756516193L</code>.
81 *
82 * @since 1.5
83 */
84@SuppressWarnings("serial")
85public class ModelMBeanInfoSupport extends MBeanInfo implements ModelMBeanInfo {
86
87 // Serialization compatibility stuff:
88 // Two serial forms are supported in this class. The selected form depends
89 // on system property "jmx.serial.form":
90 // - "1.0" for JMX 1.0
91 // - any other value for JMX 1.1 and higher
92 //
93 // Serial version for old serial form
94 private static final long oldSerialVersionUID = -3944083498453227709L;
95 //
96 // Serial version for new serial form
97 private static final long newSerialVersionUID = -1935722590756516193L;
98 //
99 // Serializable fields in old serial form
100 private static final ObjectStreamField[] oldSerialPersistentFields =
101 {
102 new ObjectStreamField("modelMBeanDescriptor", Descriptor.class),
103 new ObjectStreamField("mmbAttributes", MBeanAttributeInfo[].class),
104 new ObjectStreamField("mmbConstructors", MBeanConstructorInfo[].class),
105 new ObjectStreamField("mmbNotifications", MBeanNotificationInfo[].class),
106 new ObjectStreamField("mmbOperations", MBeanOperationInfo[].class),
107 new ObjectStreamField("currClass", String.class)
108 };
109 //
110 // Serializable fields in new serial form
111 private static final ObjectStreamField[] newSerialPersistentFields =
112 {
113 new ObjectStreamField("modelMBeanDescriptor", Descriptor.class),
114 new ObjectStreamField("modelMBeanAttributes", MBeanAttributeInfo[].class),
115 new ObjectStreamField("modelMBeanConstructors", MBeanConstructorInfo[].class),
116 new ObjectStreamField("modelMBeanNotifications", MBeanNotificationInfo[].class),
117 new ObjectStreamField("modelMBeanOperations", MBeanOperationInfo[].class)
118 };
119 //
120 // Actual serial version and serial form
121 private static final long serialVersionUID;
122 /**
123 * @serialField modelMBeanDescriptor Descriptor The descriptor containing
124 * MBean wide policy
125 * @serialField modelMBeanAttributes ModelMBeanAttributeInfo[] The array of
126 * {@link ModelMBeanAttributeInfo} objects which
127 * have descriptors
128 * @serialField modelMBeanConstructors MBeanConstructorInfo[] The array of
129 * {@link ModelMBeanConstructorInfo} objects which
130 * have descriptors
131 * @serialField modelMBeanNotifications MBeanNotificationInfo[] The array of
132 * {@link ModelMBeanNotificationInfo} objects which
133 * have descriptors
134 * @serialField modelMBeanOperations MBeanOperationInfo[] The array of
135 * {@link ModelMBeanOperationInfo} objects which
136 * have descriptors
137 */
138 private static final ObjectStreamField[] serialPersistentFields;
139 private static boolean compat = false;
140 static {
141 try {
142 GetPropertyAction act = new GetPropertyAction("jmx.serial.form");
143 String form = AccessController.doPrivileged(act);
144 compat = (form != null && form.equals("1.0"));
145 } catch (Exception e) {
146 // OK: No compat with 1.0
147 }
148 if (compat) {
149 serialPersistentFields = oldSerialPersistentFields;
150 serialVersionUID = oldSerialVersionUID;
151 } else {
152 serialPersistentFields = newSerialPersistentFields;
153 serialVersionUID = newSerialVersionUID;
154 }
155 }
156 //
157 // END Serialization compatibility stuff
158
159 /**
160 * @serial The descriptor containing MBean wide policy
161 */
162 private Descriptor modelMBeanDescriptor = null;
163
164 /* The following fields always have the same values as the
165 fields inherited from MBeanInfo and are retained only for
166 compatibility. By rewriting the serialization code we could
167 get rid of them.
168
169 These fields can't be final because they are assigned to by
170 readObject(). */
171
172 /**
173 * @serial The array of {@link ModelMBeanAttributeInfo} objects which
174 * have descriptors
175 */
176 private MBeanAttributeInfo[] modelMBeanAttributes;
177
178 /**
179 * @serial The array of {@link ModelMBeanConstructorInfo} objects which
180 * have descriptors
181 */
182 private MBeanConstructorInfo[] modelMBeanConstructors;
183
184 /**
185 * @serial The array of {@link ModelMBeanNotificationInfo} objects which
186 * have descriptors
187 */
188 private MBeanNotificationInfo[] modelMBeanNotifications;
189
190 /**
191 * @serial The array of {@link ModelMBeanOperationInfo} objects which
192 * have descriptors
193 */
194 private MBeanOperationInfo[] modelMBeanOperations;
195
196 private static final String ATTR = "attribute";
197 private static final String OPER = "operation";
198 private static final String NOTF = "notification";
199 private static final String CONS = "constructor";
200 private static final String MMB = "mbean";
201 private static final String ALL = "all";
202 private static final String currClass = "ModelMBeanInfoSupport";
203
204 /**
205 * Constructs a ModelMBeanInfoSupport which is a duplicate of the given
206 * ModelMBeanInfo. The returned object is a shallow copy of the given
207 * object. Neither the Descriptor nor the contained arrays
208 * ({@code ModelMBeanAttributeInfo[]} etc) are cloned. This method is
209 * chiefly of interest to modify the Descriptor of the returned instance
210 * via {@link #setDescriptor setDescriptor} without affecting the
211 * Descriptor of the original object.
212 *
213 * @param mbi the ModelMBeanInfo instance from which the ModelMBeanInfo
214 * being created is initialized.
215 */
216 public ModelMBeanInfoSupport(ModelMBeanInfo mbi) {
217 super(mbi.getClassName(),
218 mbi.getDescription(),
219 mbi.getAttributes(),
220 mbi.getConstructors(),
221 mbi.getOperations(),
222 mbi.getNotifications());
223
224 modelMBeanAttributes = mbi.getAttributes();
225 modelMBeanConstructors = mbi.getConstructors();
226 modelMBeanOperations = mbi.getOperations();
227 modelMBeanNotifications = mbi.getNotifications();
228
229 try {
230 Descriptor mbeandescriptor = mbi.getMBeanDescriptor();
231 modelMBeanDescriptor = validDescriptor(mbeandescriptor);
232 } catch (MBeanException mbe) {
233 modelMBeanDescriptor = validDescriptor(null);
234 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
235 MODELMBEAN_LOGGER.logp(Level.FINER,
236 ModelMBeanInfoSupport.class.getName(),
237 "ModelMBeanInfo(ModelMBeanInfo)",
238 "Could not get a valid modelMBeanDescriptor, " +
239 "setting a default Descriptor");
240 }
241 }
242
243 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
244 MODELMBEAN_LOGGER.logp(Level.FINER,
245 ModelMBeanInfoSupport.class.getName(),
246 "ModelMBeanInfo(ModelMBeanInfo)", "Exit");
247 }
248 }
249
250 /**
251 * Creates a ModelMBeanInfoSupport with the provided information,
252 * but the descriptor is a default.
253 * The default descriptor is: name=className, descriptorType="mbean",
254 * displayName=className, persistPolicy="never", log="F", visibility="1"
255 *
256 * @param className classname of the MBean
257 * @param description human readable description of the
258 * ModelMBean
259 * @param attributes array of ModelMBeanAttributeInfo objects
260 * which have descriptors
261 * @param constructors array of ModelMBeanConstructorInfo
262 * objects which have descriptors
263 * @param operations array of ModelMBeanOperationInfo objects
264 * which have descriptors
265 * @param notifications array of ModelMBeanNotificationInfo
266 * objects which have descriptors
267 */
268 public ModelMBeanInfoSupport(String className,
269 String description,
270 ModelMBeanAttributeInfo[] attributes,
271 ModelMBeanConstructorInfo[] constructors,
272 ModelMBeanOperationInfo[] operations,
273 ModelMBeanNotificationInfo[] notifications) {
274 this(className, description, attributes, constructors,
275 operations, notifications, null);
276 }
277
278 /**
279 * Creates a ModelMBeanInfoSupport with the provided information
280 * and the descriptor given in parameter.
281 *
282 * @param className classname of the MBean
283 * @param description human readable description of the
284 * ModelMBean
285 * @param attributes array of ModelMBeanAttributeInfo objects
286 * which have descriptors
287 * @param constructors array of ModelMBeanConstructorInfo
288 * objects which have descriptor
289 * @param operations array of ModelMBeanOperationInfo objects
290 * which have descriptor
291 * @param notifications array of ModelMBeanNotificationInfo
292 * objects which have descriptor
293 * @param mbeandescriptor descriptor to be used as the
294 * MBeanDescriptor containing MBean wide policy. If the
295 * descriptor is null, a default descriptor will be constructed.
296 * The default descriptor is:
297 * name=className, descriptorType="mbean", displayName=className,
298 * persistPolicy="never", log="F", visibility="1". If the descriptor
299 * does not contain all of these fields, the missing ones are
300 * added with these default values.
301 *
302 * @exception RuntimeOperationsException Wraps an
303 * IllegalArgumentException for invalid descriptor passed in
304 * parameter. (see {@link #getMBeanDescriptor
305 * getMBeanDescriptor} for the definition of a valid MBean
306 * descriptor.)
307 */
308
309 public ModelMBeanInfoSupport(String className,
310 String description,
311 ModelMBeanAttributeInfo[] attributes,
312 ModelMBeanConstructorInfo[] constructors,
313 ModelMBeanOperationInfo[] operations,
314 ModelMBeanNotificationInfo[] notifications,
315 Descriptor mbeandescriptor) {
316 super(className,
317 description,
318 (attributes != null) ? attributes : NO_ATTRIBUTES,
319 (constructors != null) ? constructors : NO_CONSTRUCTORS,
320 (operations != null) ? operations : NO_OPERATIONS,
321 (notifications != null) ? notifications : NO_NOTIFICATIONS);
322 /* The values saved here are possibly null, but we
323 check this everywhere they are referenced. If at
324 some stage we replace null with an empty array
325 here, as we do in the superclass constructor
326 parameters, then we must also do this in
327 readObject(). */
328 modelMBeanAttributes = attributes;
329 modelMBeanConstructors = constructors;
330 modelMBeanOperations = operations;
331 modelMBeanNotifications = notifications;
332 modelMBeanDescriptor = validDescriptor(mbeandescriptor);
333 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
334 MODELMBEAN_LOGGER.logp(Level.FINER,
335 ModelMBeanInfoSupport.class.getName(),
336 "ModelMBeanInfoSupport(String,String,ModelMBeanAttributeInfo[]," +
337 "ModelMBeanConstructorInfo[],ModelMBeanOperationInfo[]," +
338 "ModelMBeanNotificationInfo[],Descriptor)",
339 "Exit");
340 }
341 }
342
343 private static final ModelMBeanAttributeInfo[] NO_ATTRIBUTES =
344 new ModelMBeanAttributeInfo[0];
345 private static final ModelMBeanConstructorInfo[] NO_CONSTRUCTORS =
346 new ModelMBeanConstructorInfo[0];
347 private static final ModelMBeanNotificationInfo[] NO_NOTIFICATIONS =
348 new ModelMBeanNotificationInfo[0];
349 private static final ModelMBeanOperationInfo[] NO_OPERATIONS =
350 new ModelMBeanOperationInfo[0];
351
352 // Java doc inherited from MOdelMBeanInfo interface
353
354 /**
355 * Returns a shallow clone of this instance. Neither the Descriptor nor
356 * the contained arrays ({@code ModelMBeanAttributeInfo[]} etc) are
357 * cloned. This method is chiefly of interest to modify the Descriptor
358 * of the clone via {@link #setDescriptor setDescriptor} without affecting
359 * the Descriptor of the original object.
360 *
361 * @return a shallow clone of this instance.
362 */
363 public Object clone() {
364 return(new ModelMBeanInfoSupport(this));
365 }
366
367
368 public Descriptor[] getDescriptors(String inDescriptorType)
369 throws MBeanException, RuntimeOperationsException {
370 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
371 MODELMBEAN_LOGGER.logp(Level.FINER,
372 ModelMBeanInfoSupport.class.getName(),
373 "getDescriptors(String)", "Entry");
374 }
375
376 if ((inDescriptorType == null) || (inDescriptorType.isEmpty())) {
377 inDescriptorType = "all";
378 }
379
380 // if no descriptors of that type, will return empty array
381 //
382 final Descriptor[] retList;
383
384 if (inDescriptorType.equalsIgnoreCase(MMB)) {
385 retList = new Descriptor[] {modelMBeanDescriptor};
386 } else if (inDescriptorType.equalsIgnoreCase(ATTR)) {
387 final MBeanAttributeInfo[] attrList = modelMBeanAttributes;
388 int numAttrs = 0;
389 if (attrList != null) numAttrs = attrList.length;
390
391 retList = new Descriptor[numAttrs];
392 for (int i=0; i < numAttrs; i++) {
393 retList[i] = (((ModelMBeanAttributeInfo)
394 attrList[i]).getDescriptor());
395 }
396 } else if (inDescriptorType.equalsIgnoreCase(OPER)) {
397 final MBeanOperationInfo[] operList = modelMBeanOperations;
398 int numOpers = 0;
399 if (operList != null) numOpers = operList.length;
400
401 retList = new Descriptor[numOpers];
402 for (int i=0; i < numOpers; i++) {
403 retList[i] = (((ModelMBeanOperationInfo)
404 operList[i]).getDescriptor());
405 }
406 } else if (inDescriptorType.equalsIgnoreCase(CONS)) {
407 final MBeanConstructorInfo[] consList = modelMBeanConstructors;
408 int numCons = 0;
409 if (consList != null) numCons = consList.length;
410
411 retList = new Descriptor[numCons];
412 for (int i=0; i < numCons; i++) {
413 retList[i] = (((ModelMBeanConstructorInfo)
414 consList[i]).getDescriptor());
415 }
416 } else if (inDescriptorType.equalsIgnoreCase(NOTF)) {
417 final MBeanNotificationInfo[] notifList = modelMBeanNotifications;
418 int numNotifs = 0;
419 if (notifList != null) numNotifs = notifList.length;
420
421 retList = new Descriptor[numNotifs];
422 for (int i=0; i < numNotifs; i++) {
423 retList[i] = (((ModelMBeanNotificationInfo)
424 notifList[i]).getDescriptor());
425 }
426 } else if (inDescriptorType.equalsIgnoreCase(ALL)) {
427
428 final MBeanAttributeInfo[] attrList = modelMBeanAttributes;
429 int numAttrs = 0;
430 if (attrList != null) numAttrs = attrList.length;
431
432 final MBeanOperationInfo[] operList = modelMBeanOperations;
433 int numOpers = 0;
434 if (operList != null) numOpers = operList.length;
435
436 final MBeanConstructorInfo[] consList = modelMBeanConstructors;
437 int numCons = 0;
438 if (consList != null) numCons = consList.length;
439
440 final MBeanNotificationInfo[] notifList = modelMBeanNotifications;
441 int numNotifs = 0;
442 if (notifList != null) numNotifs = notifList.length;
443
444 int count = numAttrs + numCons + numOpers + numNotifs + 1;
445 retList = new Descriptor[count];
446
447 retList[count-1] = modelMBeanDescriptor;
448
449 int j=0;
450 for (int i=0; i < numAttrs; i++) {
451 retList[j] = (((ModelMBeanAttributeInfo)
452 attrList[i]).getDescriptor());
453 j++;
454 }
455 for (int i=0; i < numCons; i++) {
456 retList[j] = (((ModelMBeanConstructorInfo)
457 consList[i]).getDescriptor());
458 j++;
459 }
460 for (int i=0; i < numOpers; i++) {
461 retList[j] = (((ModelMBeanOperationInfo)operList[i]).
462 getDescriptor());
463 j++;
464 }
465 for (int i=0; i < numNotifs; i++) {
466 retList[j] = (((ModelMBeanNotificationInfo)notifList[i]).
467 getDescriptor());
468 j++;
469 }
470 } else {
471 final IllegalArgumentException iae =
472 new IllegalArgumentException("Descriptor Type is invalid");
473 final String msg = "Exception occurred trying to find"+
474 " the descriptors of the MBean";
475 throw new RuntimeOperationsException(iae,msg);
476 }
477 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
478 MODELMBEAN_LOGGER.logp(Level.FINER,
479 ModelMBeanInfoSupport.class.getName(),
480 "getDescriptors(String)", "Exit");
481 }
482
483 return retList;
484 }
485
486
487 public void setDescriptors(Descriptor[] inDescriptors)
488 throws MBeanException, RuntimeOperationsException {
489 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
490 MODELMBEAN_LOGGER.logp(Level.FINER,
491 ModelMBeanInfoSupport.class.getName(),
492 "setDescriptors(Descriptor[])", "Entry");
493 }
494 if (inDescriptors==null) {
495 // throw RuntimeOperationsException - invalid descriptor
496 throw new RuntimeOperationsException(
497 new IllegalArgumentException("Descriptor list is invalid"),
498 "Exception occurred trying to set the descriptors " +
499 "of the MBeanInfo");
500 }
501 if (inDescriptors.length == 0) { // empty list, no-op
502 return;
503 }
504 for (int j=0; j < inDescriptors.length; j++) {
505 setDescriptor(inDescriptors[j],null);
506 }
507 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
508 MODELMBEAN_LOGGER.logp(Level.FINER,
509 ModelMBeanInfoSupport.class.getName(),
510 "setDescriptors(Descriptor[])", "Exit");
511 }
512
513 }
514
515
516 /**
517 * Returns a Descriptor requested by name.
518 *
519 * @param inDescriptorName The name of the descriptor.
520 *
521 * @return Descriptor containing a descriptor for the ModelMBean with the
522 * same name. If no descriptor is found, null is returned.
523 *
524 * @exception MBeanException Wraps a distributed communication Exception.
525 * @exception RuntimeOperationsException Wraps an IllegalArgumentException
526 * for null name.
527 *
528 * @see #setDescriptor
529 */
530
531 public Descriptor getDescriptor(String inDescriptorName)
532 throws MBeanException, RuntimeOperationsException {
533 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
534 MODELMBEAN_LOGGER.logp(Level.FINER,
535 ModelMBeanInfoSupport.class.getName(),
536 "getDescriptor(String)", "Entry");
537 }
538 return(getDescriptor(inDescriptorName, null));
539 }
540
541
542 public Descriptor getDescriptor(String inDescriptorName,
543 String inDescriptorType)
544 throws MBeanException, RuntimeOperationsException {
545 if (inDescriptorName==null) {
546 // throw RuntimeOperationsException - invalid descriptor
547 throw new RuntimeOperationsException(
548 new IllegalArgumentException("Descriptor is invalid"),
549 "Exception occurred trying to set the descriptors of " +
550 "the MBeanInfo");
551 }
552
553 if (MMB.equalsIgnoreCase(inDescriptorType)) {
554 return (Descriptor) modelMBeanDescriptor.clone();
555 }
556
557 /* The logic here is a bit convoluted, because we are
558 dealing with two possible cases, depending on whether
559 inDescriptorType is null. If it's not null, then only
560 one of the following ifs will run, and it will either
561 return a descriptor or null. If inDescriptorType is
562 null, then all of the following ifs will run until one
563 of them finds a descriptor. */
564 if (ATTR.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
565 ModelMBeanAttributeInfo attr = getAttribute(inDescriptorName);
566 if (attr != null)
567 return attr.getDescriptor();
568 if (inDescriptorType != null)
569 return null;
570 }
571 if (OPER.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
572 ModelMBeanOperationInfo oper = getOperation(inDescriptorName);
573 if (oper != null)
574 return oper.getDescriptor();
575 if (inDescriptorType != null)
576 return null;
577 }
578 if (CONS.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
579 ModelMBeanConstructorInfo oper =
580 getConstructor(inDescriptorName);
581 if (oper != null)
582 return oper.getDescriptor();
583 if (inDescriptorType != null)
584 return null;
585 }
586 if (NOTF.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) {
587 ModelMBeanNotificationInfo notif =
588 getNotification(inDescriptorName);
589 if (notif != null)
590 return notif.getDescriptor();
591 if (inDescriptorType != null)
592 return null;
593 }
594 if (inDescriptorType == null)
595 return null;
596 throw new RuntimeOperationsException(
597 new IllegalArgumentException("Descriptor Type is invalid"),
598 "Exception occurred trying to find the descriptors of the MBean");
599
600 }
601
602
603
604 public void setDescriptor(Descriptor inDescriptor,
605 String inDescriptorType)
606 throws MBeanException, RuntimeOperationsException {
607 final String excMsg =
608 "Exception occurred trying to set the descriptors of the MBean";
609 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
610 MODELMBEAN_LOGGER.logp(Level.FINER,
611 ModelMBeanInfoSupport.class.getName(),
612 "setDescriptor(Descriptor,String)", "Entry");
613 }
614
615 if (inDescriptor==null) {
616 inDescriptor = new DescriptorSupport();
617 }
618
619 if ((inDescriptorType == null) || (inDescriptorType.isEmpty())) {
620 inDescriptorType =
621 (String) inDescriptor.getFieldValue("descriptorType");
622
623 if (inDescriptorType == null) {
624 MODELMBEAN_LOGGER.logp(Level.FINER,
625 ModelMBeanInfoSupport.class.getName(),
626 "setDescriptor(Descriptor,String)",
627 "descriptorType null in both String parameter and Descriptor, defaulting to "+ MMB);
628 inDescriptorType = MMB;
629 }
630 }
631
632 String inDescriptorName =
633 (String) inDescriptor.getFieldValue("name");
634 if (inDescriptorName == null) {
635 MODELMBEAN_LOGGER.logp(Level.FINER,
636 ModelMBeanInfoSupport.class.getName(),
637 "setDescriptor(Descriptor,String)",
638 "descriptor name null, defaulting to "+ this.getClassName());
639 inDescriptorName = this.getClassName();
640 }
641 boolean found = false;
642 if (inDescriptorType.equalsIgnoreCase(MMB)) {
643 setMBeanDescriptor(inDescriptor);
644 found = true;
645 } else if (inDescriptorType.equalsIgnoreCase(ATTR)) {
646 MBeanAttributeInfo[] attrList = modelMBeanAttributes;
647 int numAttrs = 0;
648 if (attrList != null) numAttrs = attrList.length;
649
650 for (int i=0; i < numAttrs; i++) {
651 if (inDescriptorName.equals(attrList[i].getName())) {
652 found = true;
653 ModelMBeanAttributeInfo mmbai =
654 (ModelMBeanAttributeInfo) attrList[i];
655 mmbai.setDescriptor(inDescriptor);
656 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
657 StringBuilder strb = new StringBuilder()
658 .append("Setting descriptor to ").append(inDescriptor)
659 .append("\t\n local: AttributeInfo descriptor is ")
660 .append(mmbai.getDescriptor())
661 .append("\t\n modelMBeanInfo: AttributeInfo descriptor is ")
662 .append(this.getDescriptor(inDescriptorName,"attribute"));
663 MODELMBEAN_LOGGER.logp(Level.FINER,
664 ModelMBeanInfoSupport.class.getName(),
665 "setDescriptor(Descriptor,String)",
666 strb.toString());
667 }
668 }
669 }
670 } else if (inDescriptorType.equalsIgnoreCase(OPER)) {
671 MBeanOperationInfo[] operList = modelMBeanOperations;
672 int numOpers = 0;
673 if (operList != null) numOpers = operList.length;
674
675 for (int i=0; i < numOpers; i++) {
676 if (inDescriptorName.equals(operList[i].getName())) {
677 found = true;
678 ModelMBeanOperationInfo mmboi =
679 (ModelMBeanOperationInfo) operList[i];
680 mmboi.setDescriptor(inDescriptor);
681 }
682 }
683 } else if (inDescriptorType.equalsIgnoreCase(CONS)) {
684 MBeanConstructorInfo[] consList = modelMBeanConstructors;
685 int numCons = 0;
686 if (consList != null) numCons = consList.length;
687
688 for (int i=0; i < numCons; i++) {
689 if (inDescriptorName.equals(consList[i].getName())) {
690 found = true;
691 ModelMBeanConstructorInfo mmbci =
692 (ModelMBeanConstructorInfo) consList[i];
693 mmbci.setDescriptor(inDescriptor);
694 }
695 }
696 } else if (inDescriptorType.equalsIgnoreCase(NOTF)) {
697 MBeanNotificationInfo[] notifList = modelMBeanNotifications;
698 int numNotifs = 0;
699 if (notifList != null) numNotifs = notifList.length;
700
701 for (int i=0; i < numNotifs; i++) {
702 if (inDescriptorName.equals(notifList[i].getName())) {
703 found = true;
704 ModelMBeanNotificationInfo mmbni =
705 (ModelMBeanNotificationInfo) notifList[i];
706 mmbni.setDescriptor(inDescriptor);
707 }
708 }
709 } else {
710 RuntimeException iae =
711 new IllegalArgumentException("Invalid descriptor type: " +
712 inDescriptorType);
713 throw new RuntimeOperationsException(iae, excMsg);
714 }
715
716 if (!found) {
717 RuntimeException iae =
718 new IllegalArgumentException("Descriptor name is invalid: " +
719 "type=" + inDescriptorType +
720 "; name=" + inDescriptorName);
721 throw new RuntimeOperationsException(iae, excMsg);
722 }
723 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
724 MODELMBEAN_LOGGER.logp(Level.FINER,
725 ModelMBeanInfoSupport.class.getName(),
726 "setDescriptor(Descriptor,String)", "Exit");
727 }
728
729 }
730
731
732 public ModelMBeanAttributeInfo getAttribute(String inName)
733 throws MBeanException, RuntimeOperationsException {
734 ModelMBeanAttributeInfo retInfo = null;
735 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
736 MODELMBEAN_LOGGER.logp(Level.FINER,
737 ModelMBeanInfoSupport.class.getName(),
738 "getAttribute(String)", "Entry");
739 }
740 if (inName == null) {
741 throw new RuntimeOperationsException(
742 new IllegalArgumentException("Attribute Name is null"),
743 "Exception occurred trying to get the " +
744 "ModelMBeanAttributeInfo of the MBean");
745 }
746 MBeanAttributeInfo[] attrList = modelMBeanAttributes;
747 int numAttrs = 0;
748 if (attrList != null) numAttrs = attrList.length;
749
750 for (int i=0; (i < numAttrs) && (retInfo == null); i++) {
751 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
752 final StringBuilder strb = new StringBuilder()
753 .append("\t\n this.getAttributes() MBeanAttributeInfo Array ")
754 .append(i).append(":")
755 .append(((ModelMBeanAttributeInfo)attrList[i]).getDescriptor())
756 .append("\t\n this.modelMBeanAttributes MBeanAttributeInfo Array ")
757 .append(i).append(":")
758 .append(((ModelMBeanAttributeInfo)modelMBeanAttributes[i]).getDescriptor());
759 MODELMBEAN_LOGGER.logp(Level.FINER,
760 ModelMBeanInfoSupport.class.getName(),
761 "getAttribute(String)", strb.toString());
762 }
763 if (inName.equals(attrList[i].getName())) {
764 retInfo = ((ModelMBeanAttributeInfo)attrList[i].clone());
765 }
766 }
767 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
768 MODELMBEAN_LOGGER.logp(Level.FINER,
769 ModelMBeanInfoSupport.class.getName(),
770 "getAttribute(String)", "Exit");
771 }
772
773 return retInfo;
774 }
775
776
777
778 public ModelMBeanOperationInfo getOperation(String inName)
779 throws MBeanException, RuntimeOperationsException {
780 ModelMBeanOperationInfo retInfo = null;
781 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
782 MODELMBEAN_LOGGER.logp(Level.FINER,
783 ModelMBeanInfoSupport.class.getName(),
784 "getOperation(String)", "Entry");
785 }
786 if (inName == null) {
787 throw new RuntimeOperationsException(
788 new IllegalArgumentException("inName is null"),
789 "Exception occurred trying to get the " +
790 "ModelMBeanOperationInfo of the MBean");
791 }
792 MBeanOperationInfo[] operList = modelMBeanOperations; //this.getOperations();
793 int numOpers = 0;
794 if (operList != null) numOpers = operList.length;
795
796 for (int i=0; (i < numOpers) && (retInfo == null); i++) {
797 if (inName.equals(operList[i].getName())) {
798 retInfo = ((ModelMBeanOperationInfo) operList[i].clone());
799 }
800 }
801 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
802 MODELMBEAN_LOGGER.logp(Level.FINER,
803 ModelMBeanInfoSupport.class.getName(),
804 "getOperation(String)", "Exit");
805 }
806
807 return retInfo;
808 }
809
810 /**
811 * Returns the ModelMBeanConstructorInfo requested by name.
812 * If no ModelMBeanConstructorInfo exists for this name null is returned.
813 *
814 * @param inName the name of the constructor.
815 *
816 * @return the constructor info for the named constructor, or null
817 * if there is none.
818 *
819 * @exception MBeanException Wraps a distributed communication Exception.
820 * @exception RuntimeOperationsException Wraps an IllegalArgumentException
821 * for a null constructor name.
822 */
823
824 public ModelMBeanConstructorInfo getConstructor(String inName)
825 throws MBeanException, RuntimeOperationsException {
826 ModelMBeanConstructorInfo retInfo = null;
827 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
828 MODELMBEAN_LOGGER.logp(Level.FINER,
829 ModelMBeanInfoSupport.class.getName(),
830 "getConstructor(String)", "Entry");
831 }
832 if (inName == null) {
833 throw new RuntimeOperationsException(
834 new IllegalArgumentException("Constructor name is null"),
835 "Exception occurred trying to get the " +
836 "ModelMBeanConstructorInfo of the MBean");
837 }
838 MBeanConstructorInfo[] consList = modelMBeanConstructors; //this.getConstructors();
839 int numCons = 0;
840 if (consList != null) numCons = consList.length;
841
842 for (int i=0; (i < numCons) && (retInfo == null); i++) {
843 if (inName.equals(consList[i].getName())) {
844 retInfo = ((ModelMBeanConstructorInfo) consList[i].clone());
845 }
846 }
847 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
848 MODELMBEAN_LOGGER.logp(Level.FINER,
849 ModelMBeanInfoSupport.class.getName(),
850 "getConstructor(String)", "Exit");
851 }
852
853 return retInfo;
854 }
855
856
857 public ModelMBeanNotificationInfo getNotification(String inName)
858 throws MBeanException, RuntimeOperationsException {
859 ModelMBeanNotificationInfo retInfo = null;
860 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
861 MODELMBEAN_LOGGER.logp(Level.FINER,
862 ModelMBeanInfoSupport.class.getName(),
863 "getNotification(String)", "Entry");
864 }
865 if (inName == null) {
866 throw new RuntimeOperationsException(
867 new IllegalArgumentException("Notification name is null"),
868 "Exception occurred trying to get the " +
869 "ModelMBeanNotificationInfo of the MBean");
870 }
871 MBeanNotificationInfo[] notifList = modelMBeanNotifications; //this.getNotifications();
872 int numNotifs = 0;
873 if (notifList != null) numNotifs = notifList.length;
874
875 for (int i=0; (i < numNotifs) && (retInfo == null); i++) {
876 if (inName.equals(notifList[i].getName())) {
877 retInfo = ((ModelMBeanNotificationInfo) notifList[i].clone());
878 }
879 }
880 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
881 MODELMBEAN_LOGGER.logp(Level.FINER,
882 ModelMBeanInfoSupport.class.getName(),
883 "getNotification(String)", "Exit");
884 }
885
886 return retInfo;
887 }
888
889
890 /* We override MBeanInfo.getDescriptor() to return our descriptor. */
891 /**
892 * @since 1.6
893 */
894 @Override
895 public Descriptor getDescriptor() {
896 return getMBeanDescriptorNoException();
897 }
898
899 public Descriptor getMBeanDescriptor() throws MBeanException {
900 return getMBeanDescriptorNoException();
901 }
902
903 private Descriptor getMBeanDescriptorNoException() {
904 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
905 MODELMBEAN_LOGGER.logp(Level.FINER,
906 ModelMBeanInfoSupport.class.getName(),
907 "getMBeanDescriptorNoException()", "Entry");
908 }
909
910 if (modelMBeanDescriptor == null)
911 modelMBeanDescriptor = validDescriptor(null);
912
913 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
914 MODELMBEAN_LOGGER.logp(Level.FINER,
915 ModelMBeanInfoSupport.class.getName(),
916 "getMBeanDescriptorNoException()",
917 "Exit, returning: " + modelMBeanDescriptor);
918 }
919 return (Descriptor) modelMBeanDescriptor.clone();
920 }
921
922 public void setMBeanDescriptor(Descriptor inMBeanDescriptor)
923 throws MBeanException, RuntimeOperationsException {
924 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
925 MODELMBEAN_LOGGER.logp(Level.FINER,
926 ModelMBeanInfoSupport.class.getName(),
927 "setMBeanDescriptor(Descriptor)", "Entry");
928 }
929 modelMBeanDescriptor = validDescriptor(inMBeanDescriptor);
930 }
931
932
933 /**
934 * Clones the passed in Descriptor, sets default values, and checks for validity.
935 * If the Descriptor is invalid (for instance by having the wrong "name"),
936 * this indicates programming error and a RuntimeOperationsException will be thrown.
937 *
938 * The following fields will be defaulted if they are not already set:
939 * displayName=className,name=className,descriptorType="mbean",
940 * persistPolicy="never", log="F", visibility="1"
941 *
942 * @param in Descriptor to be checked, or null which is equivalent to
943 * an empty Descriptor.
944 * @exception RuntimeOperationsException if Descriptor is invalid
945 */
946 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
947 Descriptor clone = null;
948 if (in == null) {
949 clone = new DescriptorSupport();
950 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
951 } else {
952 clone = (Descriptor) in.clone();
953 }
954
955 //Setting defaults.
956 if (clone.getFieldValue("name")==null) {
957 clone.setField("name", this.getClassName());
958 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getClassName());
959 }
960 if (clone.getFieldValue("descriptorType")==null) {
961 clone.setField("descriptorType", MMB);
962 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"" + MMB + "\"");
963 }
964 if (clone.getFieldValue("displayName") == null) {
965 clone.setField("displayName",this.getClassName());
966 MODELMBEAN_LOGGER.finer("Defaulting Descriptor displayName to " + this.getClassName());
967 }
968 if (clone.getFieldValue("persistPolicy") == null) {
969 clone.setField("persistPolicy","never");
970 MODELMBEAN_LOGGER.finer("Defaulting Descriptor persistPolicy to \"never\"");
971 }
972 if (clone.getFieldValue("log") == null) {
973 clone.setField("log","F");
974 MODELMBEAN_LOGGER.finer("Defaulting Descriptor \"log\" field to \"F\"");
975 }
976 if (clone.getFieldValue("visibility") == null) {
977 clone.setField("visibility","1");
978 MODELMBEAN_LOGGER.finer("Defaulting Descriptor visibility to 1");
979 }
980
981 //Checking validity
982 if (!clone.isValid()) {
983 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
984 "The isValid() method of the Descriptor object itself returned false,"+
985 "one or more required fields are invalid. Descriptor:" + clone.toString());
986 }
987
988 if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase(MMB)) {
989 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
990 "The Descriptor \"descriptorType\" field does not match the object described. " +
991 " Expected: "+ MMB + " , was: " + clone.getFieldValue("descriptorType"));
992 }
993
994 return clone;
995 }
996
997
998
999
1000 /**
1001 * Deserializes a {@link ModelMBeanInfoSupport} from an {@link ObjectInputStream}.
1002 */
1003 private void readObject(ObjectInputStream in)
1004 throws IOException, ClassNotFoundException {
1005 if (compat) {
1006 // Read an object serialized in the old serial form
1007 //
1008 ObjectInputStream.GetField fields = in.readFields();
1009 modelMBeanDescriptor =
1010 (Descriptor) fields.get("modelMBeanDescriptor", null);
1011 if (fields.defaulted("modelMBeanDescriptor")) {
1012 throw new NullPointerException("modelMBeanDescriptor");
1013 }
1014 modelMBeanAttributes =
1015 (MBeanAttributeInfo[]) fields.get("mmbAttributes", null);
1016 if (fields.defaulted("mmbAttributes")) {
1017 throw new NullPointerException("mmbAttributes");
1018 }
1019 modelMBeanConstructors =
1020 (MBeanConstructorInfo[]) fields.get("mmbConstructors", null);
1021 if (fields.defaulted("mmbConstructors")) {
1022 throw new NullPointerException("mmbConstructors");
1023 }
1024 modelMBeanNotifications =
1025 (MBeanNotificationInfo[]) fields.get("mmbNotifications", null);
1026 if (fields.defaulted("mmbNotifications")) {
1027 throw new NullPointerException("mmbNotifications");
1028 }
1029 modelMBeanOperations =
1030 (MBeanOperationInfo[]) fields.get("mmbOperations", null);
1031 if (fields.defaulted("mmbOperations")) {
1032 throw new NullPointerException("mmbOperations");
1033 }
1034 } else {
1035 // Read an object serialized in the new serial form
1036 //
1037 in.defaultReadObject();
1038 }
1039 }
1040
1041
1042 /**
1043 * Serializes a {@link ModelMBeanInfoSupport} to an {@link ObjectOutputStream}.
1044 */
1045 private void writeObject(ObjectOutputStream out)
1046 throws IOException {
1047 if (compat) {
1048 // Serializes this instance in the old serial form
1049 //
1050 ObjectOutputStream.PutField fields = out.putFields();
1051 fields.put("modelMBeanDescriptor", modelMBeanDescriptor);
1052 fields.put("mmbAttributes", modelMBeanAttributes);
1053 fields.put("mmbConstructors", modelMBeanConstructors);
1054 fields.put("mmbNotifications", modelMBeanNotifications);
1055 fields.put("mmbOperations", modelMBeanOperations);
1056 fields.put("currClass", currClass);
1057 out.writeFields();
1058 } else {
1059 // Serializes this instance in the new serial form
1060 //
1061 out.defaultWriteObject();
1062 }
1063 }
1064
1065
1066}