1 /* 2 * Copyright (c) 2000, 2017, Oracle and/or its affiliates. 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. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 /* 26 * @author IBM Corp. 27 * 28 * Copyright IBM Corp. 1999-2000. All rights reserved. 29 */ 30 31 package javax.management.modelmbean; 32 33 import static com.sun.jmx.defaults.JmxProperties.MODELMBEAN_LOGGER; 34 import com.sun.jmx.mbeanserver.GetPropertyAction; 35 36 import java.io.IOException; 37 import java.io.ObjectInputStream; 38 import java.io.ObjectOutputStream; 39 import java.io.ObjectStreamField; 40 import java.security.AccessController; 41 import java.lang.System.Logger.Level; 42 43 import javax.management.Descriptor; 44 import javax.management.MBeanAttributeInfo; 45 import javax.management.MBeanConstructorInfo; 46 import javax.management.MBeanException; 47 import javax.management.MBeanInfo; 48 import javax.management.MBeanNotificationInfo; 49 import javax.management.MBeanOperationInfo; 50 import 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") 85 public 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.TRACE)) { 235 MODELMBEAN_LOGGER.log(Level.TRACE, 236 "ModelMBeanInfo(ModelMBeanInfo) " + 237 "Could not get a valid modelMBeanDescriptor, " + 238 "setting a default Descriptor"); 239 } 240 } 241 242 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 243 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 244 } 245 } 246 247 /** 248 * Creates a ModelMBeanInfoSupport with the provided information, 249 * but the descriptor is a default. 250 * The default descriptor is: name=className, descriptorType="mbean", 251 * displayName=className, persistPolicy="never", log="F", visibility="1" 252 * 253 * @param className classname of the MBean 254 * @param description human readable description of the 255 * ModelMBean 256 * @param attributes array of ModelMBeanAttributeInfo objects 257 * which have descriptors 258 * @param constructors array of ModelMBeanConstructorInfo 259 * objects which have descriptors 260 * @param operations array of ModelMBeanOperationInfo objects 261 * which have descriptors 262 * @param notifications array of ModelMBeanNotificationInfo 263 * objects which have descriptors 264 */ 265 public ModelMBeanInfoSupport(String className, 266 String description, 267 ModelMBeanAttributeInfo[] attributes, 268 ModelMBeanConstructorInfo[] constructors, 269 ModelMBeanOperationInfo[] operations, 270 ModelMBeanNotificationInfo[] notifications) { 271 this(className, description, attributes, constructors, 272 operations, notifications, null); 273 } 274 275 /** 276 * Creates a ModelMBeanInfoSupport with the provided information 277 * and the descriptor given in parameter. 278 * 279 * @param className classname of the MBean 280 * @param description human readable description of the 281 * ModelMBean 282 * @param attributes array of ModelMBeanAttributeInfo objects 283 * which have descriptors 284 * @param constructors array of ModelMBeanConstructorInfo 285 * objects which have descriptor 286 * @param operations array of ModelMBeanOperationInfo objects 287 * which have descriptor 288 * @param notifications array of ModelMBeanNotificationInfo 289 * objects which have descriptor 290 * @param mbeandescriptor descriptor to be used as the 291 * MBeanDescriptor containing MBean wide policy. If the 292 * descriptor is null, a default descriptor will be constructed. 293 * The default descriptor is: 294 * name=className, descriptorType="mbean", displayName=className, 295 * persistPolicy="never", log="F", visibility="1". If the descriptor 296 * does not contain all of these fields, the missing ones are 297 * added with these default values. 298 * 299 * @exception RuntimeOperationsException Wraps an 300 * IllegalArgumentException for invalid descriptor passed in 301 * parameter. (see {@link #getMBeanDescriptor 302 * getMBeanDescriptor} for the definition of a valid MBean 303 * descriptor.) 304 */ 305 306 public ModelMBeanInfoSupport(String className, 307 String description, 308 ModelMBeanAttributeInfo[] attributes, 309 ModelMBeanConstructorInfo[] constructors, 310 ModelMBeanOperationInfo[] operations, 311 ModelMBeanNotificationInfo[] notifications, 312 Descriptor mbeandescriptor) { 313 super(className, 314 description, 315 (attributes != null) ? attributes : NO_ATTRIBUTES, 316 (constructors != null) ? constructors : NO_CONSTRUCTORS, 317 (operations != null) ? operations : NO_OPERATIONS, 318 (notifications != null) ? notifications : NO_NOTIFICATIONS); 319 /* The values saved here are possibly null, but we 320 check this everywhere they are referenced. If at 321 some stage we replace null with an empty array 322 here, as we do in the superclass constructor 323 parameters, then we must also do this in 324 readObject(). */ 325 modelMBeanAttributes = attributes; 326 modelMBeanConstructors = constructors; 327 modelMBeanOperations = operations; 328 modelMBeanNotifications = notifications; 329 modelMBeanDescriptor = validDescriptor(mbeandescriptor); 330 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 331 MODELMBEAN_LOGGER.log(Level.TRACE, 332 "ModelMBeanInfoSupport(String,String,ModelMBeanAttributeInfo[]," + 333 "ModelMBeanConstructorInfo[],ModelMBeanOperationInfo[]," + 334 "ModelMBeanNotificationInfo[],Descriptor) " + 335 "Exit"); 336 } 337 } 338 339 private static final ModelMBeanAttributeInfo[] NO_ATTRIBUTES = 340 new ModelMBeanAttributeInfo[0]; 341 private static final ModelMBeanConstructorInfo[] NO_CONSTRUCTORS = 342 new ModelMBeanConstructorInfo[0]; 343 private static final ModelMBeanNotificationInfo[] NO_NOTIFICATIONS = 344 new ModelMBeanNotificationInfo[0]; 345 private static final ModelMBeanOperationInfo[] NO_OPERATIONS = 346 new ModelMBeanOperationInfo[0]; 347 348 // Java doc inherited from MOdelMBeanInfo interface 349 350 /** 351 * Returns a shallow clone of this instance. Neither the Descriptor nor 352 * the contained arrays ({@code ModelMBeanAttributeInfo[]} etc) are 353 * cloned. This method is chiefly of interest to modify the Descriptor 354 * of the clone via {@link #setDescriptor setDescriptor} without affecting 355 * the Descriptor of the original object. 356 * 357 * @return a shallow clone of this instance. 358 */ 359 public Object clone() { 360 return(new ModelMBeanInfoSupport(this)); 361 } 362 363 364 public Descriptor[] getDescriptors(String inDescriptorType) 365 throws MBeanException, RuntimeOperationsException { 366 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 367 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 368 } 369 370 if ((inDescriptorType == null) || (inDescriptorType.isEmpty())) { 371 inDescriptorType = "all"; 372 } 373 374 // if no descriptors of that type, will return empty array 375 // 376 final Descriptor[] retList; 377 378 if (inDescriptorType.equalsIgnoreCase(MMB)) { 379 retList = new Descriptor[] {modelMBeanDescriptor}; 380 } else if (inDescriptorType.equalsIgnoreCase(ATTR)) { 381 final MBeanAttributeInfo[] attrList = modelMBeanAttributes; 382 int numAttrs = 0; 383 if (attrList != null) numAttrs = attrList.length; 384 385 retList = new Descriptor[numAttrs]; 386 for (int i=0; i < numAttrs; i++) { 387 retList[i] = (((ModelMBeanAttributeInfo) 388 attrList[i]).getDescriptor()); 389 } 390 } else if (inDescriptorType.equalsIgnoreCase(OPER)) { 391 final MBeanOperationInfo[] operList = modelMBeanOperations; 392 int numOpers = 0; 393 if (operList != null) numOpers = operList.length; 394 395 retList = new Descriptor[numOpers]; 396 for (int i=0; i < numOpers; i++) { 397 retList[i] = (((ModelMBeanOperationInfo) 398 operList[i]).getDescriptor()); 399 } 400 } else if (inDescriptorType.equalsIgnoreCase(CONS)) { 401 final MBeanConstructorInfo[] consList = modelMBeanConstructors; 402 int numCons = 0; 403 if (consList != null) numCons = consList.length; 404 405 retList = new Descriptor[numCons]; 406 for (int i=0; i < numCons; i++) { 407 retList[i] = (((ModelMBeanConstructorInfo) 408 consList[i]).getDescriptor()); 409 } 410 } else if (inDescriptorType.equalsIgnoreCase(NOTF)) { 411 final MBeanNotificationInfo[] notifList = modelMBeanNotifications; 412 int numNotifs = 0; 413 if (notifList != null) numNotifs = notifList.length; 414 415 retList = new Descriptor[numNotifs]; 416 for (int i=0; i < numNotifs; i++) { 417 retList[i] = (((ModelMBeanNotificationInfo) 418 notifList[i]).getDescriptor()); 419 } 420 } else if (inDescriptorType.equalsIgnoreCase(ALL)) { 421 422 final MBeanAttributeInfo[] attrList = modelMBeanAttributes; 423 int numAttrs = 0; 424 if (attrList != null) numAttrs = attrList.length; 425 426 final MBeanOperationInfo[] operList = modelMBeanOperations; 427 int numOpers = 0; 428 if (operList != null) numOpers = operList.length; 429 430 final MBeanConstructorInfo[] consList = modelMBeanConstructors; 431 int numCons = 0; 432 if (consList != null) numCons = consList.length; 433 434 final MBeanNotificationInfo[] notifList = modelMBeanNotifications; 435 int numNotifs = 0; 436 if (notifList != null) numNotifs = notifList.length; 437 438 int count = numAttrs + numCons + numOpers + numNotifs + 1; 439 retList = new Descriptor[count]; 440 441 retList[count-1] = modelMBeanDescriptor; 442 443 int j=0; 444 for (int i=0; i < numAttrs; i++) { 445 retList[j] = (((ModelMBeanAttributeInfo) 446 attrList[i]).getDescriptor()); 447 j++; 448 } 449 for (int i=0; i < numCons; i++) { 450 retList[j] = (((ModelMBeanConstructorInfo) 451 consList[i]).getDescriptor()); 452 j++; 453 } 454 for (int i=0; i < numOpers; i++) { 455 retList[j] = (((ModelMBeanOperationInfo)operList[i]). 456 getDescriptor()); 457 j++; 458 } 459 for (int i=0; i < numNotifs; i++) { 460 retList[j] = (((ModelMBeanNotificationInfo)notifList[i]). 461 getDescriptor()); 462 j++; 463 } 464 } else { 465 final IllegalArgumentException iae = 466 new IllegalArgumentException("Descriptor Type is invalid"); 467 final String msg = "Exception occurred trying to find"+ 468 " the descriptors of the MBean"; 469 throw new RuntimeOperationsException(iae,msg); 470 } 471 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 472 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 473 } 474 475 return retList; 476 } 477 478 479 public void setDescriptors(Descriptor[] inDescriptors) 480 throws MBeanException, RuntimeOperationsException { 481 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 482 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 483 } 484 if (inDescriptors==null) { 485 // throw RuntimeOperationsException - invalid descriptor 486 throw new RuntimeOperationsException( 487 new IllegalArgumentException("Descriptor list is invalid"), 488 "Exception occurred trying to set the descriptors " + 489 "of the MBeanInfo"); 490 } 491 if (inDescriptors.length == 0) { // empty list, no-op 492 return; 493 } 494 for (int j=0; j < inDescriptors.length; j++) { 495 setDescriptor(inDescriptors[j],null); 496 } 497 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 498 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 499 } 500 501 } 502 503 504 /** 505 * Returns a Descriptor requested by name. 506 * 507 * @param inDescriptorName The name of the descriptor. 508 * 509 * @return Descriptor containing a descriptor for the ModelMBean with the 510 * same name. If no descriptor is found, null is returned. 511 * 512 * @exception MBeanException Wraps a distributed communication Exception. 513 * @exception RuntimeOperationsException Wraps an IllegalArgumentException 514 * for null name. 515 * 516 * @see #setDescriptor 517 */ 518 519 public Descriptor getDescriptor(String inDescriptorName) 520 throws MBeanException, RuntimeOperationsException { 521 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 522 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 523 } 524 return(getDescriptor(inDescriptorName, null)); 525 } 526 527 528 public Descriptor getDescriptor(String inDescriptorName, 529 String inDescriptorType) 530 throws MBeanException, RuntimeOperationsException { 531 if (inDescriptorName==null) { 532 // throw RuntimeOperationsException - invalid descriptor 533 throw new RuntimeOperationsException( 534 new IllegalArgumentException("Descriptor is invalid"), 535 "Exception occurred trying to set the descriptors of " + 536 "the MBeanInfo"); 537 } 538 539 if (MMB.equalsIgnoreCase(inDescriptorType)) { 540 return (Descriptor) modelMBeanDescriptor.clone(); 541 } 542 543 /* The logic here is a bit convoluted, because we are 544 dealing with two possible cases, depending on whether 545 inDescriptorType is null. If it's not null, then only 546 one of the following ifs will run, and it will either 547 return a descriptor or null. If inDescriptorType is 548 null, then all of the following ifs will run until one 549 of them finds a descriptor. */ 550 if (ATTR.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) { 551 ModelMBeanAttributeInfo attr = getAttribute(inDescriptorName); 552 if (attr != null) 553 return attr.getDescriptor(); 554 if (inDescriptorType != null) 555 return null; 556 } 557 if (OPER.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) { 558 ModelMBeanOperationInfo oper = getOperation(inDescriptorName); 559 if (oper != null) 560 return oper.getDescriptor(); 561 if (inDescriptorType != null) 562 return null; 563 } 564 if (CONS.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) { 565 ModelMBeanConstructorInfo oper = 566 getConstructor(inDescriptorName); 567 if (oper != null) 568 return oper.getDescriptor(); 569 if (inDescriptorType != null) 570 return null; 571 } 572 if (NOTF.equalsIgnoreCase(inDescriptorType) || inDescriptorType == null) { 573 ModelMBeanNotificationInfo notif = 574 getNotification(inDescriptorName); 575 if (notif != null) 576 return notif.getDescriptor(); 577 if (inDescriptorType != null) 578 return null; 579 } 580 if (inDescriptorType == null) 581 return null; 582 throw new RuntimeOperationsException( 583 new IllegalArgumentException("Descriptor Type is invalid"), 584 "Exception occurred trying to find the descriptors of the MBean"); 585 586 } 587 588 589 590 public void setDescriptor(Descriptor inDescriptor, 591 String inDescriptorType) 592 throws MBeanException, RuntimeOperationsException { 593 final String excMsg = 594 "Exception occurred trying to set the descriptors of the MBean"; 595 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 596 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 597 } 598 599 if (inDescriptor==null) { 600 inDescriptor = new DescriptorSupport(); 601 } 602 603 if ((inDescriptorType == null) || (inDescriptorType.isEmpty())) { 604 inDescriptorType = 605 (String) inDescriptor.getFieldValue("descriptorType"); 606 607 if (inDescriptorType == null) { 608 MODELMBEAN_LOGGER.log(Level.TRACE, 609 "descriptorType null in both String parameter " + 610 "and Descriptor, defaulting to "+ MMB); 611 inDescriptorType = MMB; 612 } 613 } 614 615 String inDescriptorName = 616 (String) inDescriptor.getFieldValue("name"); 617 if (inDescriptorName == null) { 618 MODELMBEAN_LOGGER.log(Level.TRACE, 619 "descriptor name null, defaulting to " + 620 this.getClassName()); 621 inDescriptorName = this.getClassName(); 622 } 623 boolean found = false; 624 if (inDescriptorType.equalsIgnoreCase(MMB)) { 625 setMBeanDescriptor(inDescriptor); 626 found = true; 627 } else if (inDescriptorType.equalsIgnoreCase(ATTR)) { 628 MBeanAttributeInfo[] attrList = modelMBeanAttributes; 629 int numAttrs = 0; 630 if (attrList != null) numAttrs = attrList.length; 631 632 for (int i=0; i < numAttrs; i++) { 633 if (inDescriptorName.equals(attrList[i].getName())) { 634 found = true; 635 ModelMBeanAttributeInfo mmbai = 636 (ModelMBeanAttributeInfo) attrList[i]; 637 mmbai.setDescriptor(inDescriptor); 638 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 639 StringBuilder strb = new StringBuilder() 640 .append("Setting descriptor to ").append(inDescriptor) 641 .append("\t\n local: AttributeInfo descriptor is ") 642 .append(mmbai.getDescriptor()) 643 .append("\t\n modelMBeanInfo: AttributeInfo descriptor is ") 644 .append(this.getDescriptor(inDescriptorName,"attribute")); 645 MODELMBEAN_LOGGER.log(Level.TRACE, strb::toString); 646 } 647 } 648 } 649 } else if (inDescriptorType.equalsIgnoreCase(OPER)) { 650 MBeanOperationInfo[] operList = modelMBeanOperations; 651 int numOpers = 0; 652 if (operList != null) numOpers = operList.length; 653 654 for (int i=0; i < numOpers; i++) { 655 if (inDescriptorName.equals(operList[i].getName())) { 656 found = true; 657 ModelMBeanOperationInfo mmboi = 658 (ModelMBeanOperationInfo) operList[i]; 659 mmboi.setDescriptor(inDescriptor); 660 } 661 } 662 } else if (inDescriptorType.equalsIgnoreCase(CONS)) { 663 MBeanConstructorInfo[] consList = modelMBeanConstructors; 664 int numCons = 0; 665 if (consList != null) numCons = consList.length; 666 667 for (int i=0; i < numCons; i++) { 668 if (inDescriptorName.equals(consList[i].getName())) { 669 found = true; 670 ModelMBeanConstructorInfo mmbci = 671 (ModelMBeanConstructorInfo) consList[i]; 672 mmbci.setDescriptor(inDescriptor); 673 } 674 } 675 } else if (inDescriptorType.equalsIgnoreCase(NOTF)) { 676 MBeanNotificationInfo[] notifList = modelMBeanNotifications; 677 int numNotifs = 0; 678 if (notifList != null) numNotifs = notifList.length; 679 680 for (int i=0; i < numNotifs; i++) { 681 if (inDescriptorName.equals(notifList[i].getName())) { 682 found = true; 683 ModelMBeanNotificationInfo mmbni = 684 (ModelMBeanNotificationInfo) notifList[i]; 685 mmbni.setDescriptor(inDescriptor); 686 } 687 } 688 } else { 689 RuntimeException iae = 690 new IllegalArgumentException("Invalid descriptor type: " + 691 inDescriptorType); 692 throw new RuntimeOperationsException(iae, excMsg); 693 } 694 695 if (!found) { 696 RuntimeException iae = 697 new IllegalArgumentException("Descriptor name is invalid: " + 698 "type=" + inDescriptorType + 699 "; name=" + inDescriptorName); 700 throw new RuntimeOperationsException(iae, excMsg); 701 } 702 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 703 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 704 } 705 706 } 707 708 709 public ModelMBeanAttributeInfo getAttribute(String inName) 710 throws MBeanException, RuntimeOperationsException { 711 ModelMBeanAttributeInfo retInfo = null; 712 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 713 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 714 } 715 if (inName == null) { 716 throw new RuntimeOperationsException( 717 new IllegalArgumentException("Attribute Name is null"), 718 "Exception occurred trying to get the " + 719 "ModelMBeanAttributeInfo of the MBean"); 720 } 721 MBeanAttributeInfo[] attrList = modelMBeanAttributes; 722 int numAttrs = 0; 723 if (attrList != null) numAttrs = attrList.length; 724 725 for (int i=0; (i < numAttrs) && (retInfo == null); i++) { 726 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 727 final StringBuilder strb = new StringBuilder() 728 .append("\t\n this.getAttributes() MBeanAttributeInfo Array ") 729 .append(i).append(":") 730 .append(((ModelMBeanAttributeInfo)attrList[i]).getDescriptor()) 731 .append("\t\n this.modelMBeanAttributes MBeanAttributeInfo Array ") 732 .append(i).append(":") 733 .append(((ModelMBeanAttributeInfo)modelMBeanAttributes[i]).getDescriptor()); 734 MODELMBEAN_LOGGER.log(Level.TRACE, strb::toString); 735 } 736 if (inName.equals(attrList[i].getName())) { 737 retInfo = ((ModelMBeanAttributeInfo)attrList[i].clone()); 738 } 739 } 740 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 741 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 742 } 743 744 return retInfo; 745 } 746 747 748 749 public ModelMBeanOperationInfo getOperation(String inName) 750 throws MBeanException, RuntimeOperationsException { 751 ModelMBeanOperationInfo retInfo = null; 752 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 753 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 754 } 755 if (inName == null) { 756 throw new RuntimeOperationsException( 757 new IllegalArgumentException("inName is null"), 758 "Exception occurred trying to get the " + 759 "ModelMBeanOperationInfo of the MBean"); 760 } 761 MBeanOperationInfo[] operList = modelMBeanOperations; //this.getOperations(); 762 int numOpers = 0; 763 if (operList != null) numOpers = operList.length; 764 765 for (int i=0; (i < numOpers) && (retInfo == null); i++) { 766 if (inName.equals(operList[i].getName())) { 767 retInfo = ((ModelMBeanOperationInfo) operList[i].clone()); 768 } 769 } 770 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 771 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 772 } 773 774 return retInfo; 775 } 776 777 /** 778 * Returns the ModelMBeanConstructorInfo requested by name. 779 * If no ModelMBeanConstructorInfo exists for this name null is returned. 780 * 781 * @param inName the name of the constructor. 782 * 783 * @return the constructor info for the named constructor, or null 784 * if there is none. 785 * 786 * @exception MBeanException Wraps a distributed communication Exception. 787 * @exception RuntimeOperationsException Wraps an IllegalArgumentException 788 * for a null constructor name. 789 */ 790 791 public ModelMBeanConstructorInfo getConstructor(String inName) 792 throws MBeanException, RuntimeOperationsException { 793 ModelMBeanConstructorInfo retInfo = null; 794 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 795 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 796 } 797 if (inName == null) { 798 throw new RuntimeOperationsException( 799 new IllegalArgumentException("Constructor name is null"), 800 "Exception occurred trying to get the " + 801 "ModelMBeanConstructorInfo of the MBean"); 802 } 803 MBeanConstructorInfo[] consList = modelMBeanConstructors; //this.getConstructors(); 804 int numCons = 0; 805 if (consList != null) numCons = consList.length; 806 807 for (int i=0; (i < numCons) && (retInfo == null); i++) { 808 if (inName.equals(consList[i].getName())) { 809 retInfo = ((ModelMBeanConstructorInfo) consList[i].clone()); 810 } 811 } 812 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 813 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 814 } 815 816 return retInfo; 817 } 818 819 820 public ModelMBeanNotificationInfo getNotification(String inName) 821 throws MBeanException, RuntimeOperationsException { 822 ModelMBeanNotificationInfo retInfo = null; 823 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 824 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 825 } 826 if (inName == null) { 827 throw new RuntimeOperationsException( 828 new IllegalArgumentException("Notification name is null"), 829 "Exception occurred trying to get the " + 830 "ModelMBeanNotificationInfo of the MBean"); 831 } 832 MBeanNotificationInfo[] notifList = modelMBeanNotifications; //this.getNotifications(); 833 int numNotifs = 0; 834 if (notifList != null) numNotifs = notifList.length; 835 836 for (int i=0; (i < numNotifs) && (retInfo == null); i++) { 837 if (inName.equals(notifList[i].getName())) { 838 retInfo = ((ModelMBeanNotificationInfo) notifList[i].clone()); 839 } 840 } 841 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 842 MODELMBEAN_LOGGER.log(Level.TRACE, "Exit"); 843 } 844 845 return retInfo; 846 } 847 848 849 /* We override MBeanInfo.getDescriptor() to return our descriptor. */ 850 /** 851 * @since 1.6 852 */ 853 @Override 854 public Descriptor getDescriptor() { 855 return getMBeanDescriptorNoException(); 856 } 857 858 public Descriptor getMBeanDescriptor() throws MBeanException { 859 return getMBeanDescriptorNoException(); 860 } 861 862 private Descriptor getMBeanDescriptorNoException() { 863 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 864 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 865 } 866 867 if (modelMBeanDescriptor == null) 868 modelMBeanDescriptor = validDescriptor(null); 869 870 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 871 MODELMBEAN_LOGGER.log(Level.TRACE, 872 "Exit, returning: " + modelMBeanDescriptor); 873 } 874 return (Descriptor) modelMBeanDescriptor.clone(); 875 } 876 877 public void setMBeanDescriptor(Descriptor inMBeanDescriptor) 878 throws MBeanException, RuntimeOperationsException { 879 if (MODELMBEAN_LOGGER.isLoggable(Level.TRACE)) { 880 MODELMBEAN_LOGGER.log(Level.TRACE, "Entry"); 881 } 882 modelMBeanDescriptor = validDescriptor(inMBeanDescriptor); 883 } 884 885 886 /** 887 * Clones the passed in Descriptor, sets default values, and checks for validity. 888 * If the Descriptor is invalid (for instance by having the wrong "name"), 889 * this indicates programming error and a RuntimeOperationsException will be thrown. 890 * 891 * The following fields will be defaulted if they are not already set: 892 * displayName=className,name=className,descriptorType="mbean", 893 * persistPolicy="never", log="F", visibility="1" 894 * 895 * @param in Descriptor to be checked, or null which is equivalent to 896 * an empty Descriptor. 897 * @exception RuntimeOperationsException if Descriptor is invalid 898 */ 899 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException { 900 Descriptor clone; 901 boolean defaulted = (in == null); 902 if (defaulted) { 903 clone = new DescriptorSupport(); 904 MODELMBEAN_LOGGER.log(Level.TRACE, "Null Descriptor, creating new."); 905 } else { 906 clone = (Descriptor) in.clone(); 907 } 908 909 //Setting defaults. 910 if (defaulted && clone.getFieldValue("name")==null) { 911 clone.setField("name", this.getClassName()); 912 MODELMBEAN_LOGGER.log(Level.TRACE, "Defaulting Descriptor name to " + this.getClassName()); 913 } 914 if (defaulted && clone.getFieldValue("descriptorType")==null) { 915 clone.setField("descriptorType", MMB); 916 MODELMBEAN_LOGGER.log(Level.TRACE, "Defaulting descriptorType to \"" + MMB + "\""); 917 } 918 if (clone.getFieldValue("displayName") == null) { 919 clone.setField("displayName",this.getClassName()); 920 MODELMBEAN_LOGGER.log(Level.TRACE, "Defaulting Descriptor displayName to " + this.getClassName()); 921 } 922 if (clone.getFieldValue("persistPolicy") == null) { 923 clone.setField("persistPolicy","never"); 924 MODELMBEAN_LOGGER.log(Level.TRACE, "Defaulting Descriptor persistPolicy to \"never\""); 925 } 926 if (clone.getFieldValue("log") == null) { 927 clone.setField("log","F"); 928 MODELMBEAN_LOGGER.log(Level.TRACE, "Defaulting Descriptor \"log\" field to \"F\""); 929 } 930 if (clone.getFieldValue("visibility") == null) { 931 clone.setField("visibility","1"); 932 MODELMBEAN_LOGGER.log(Level.TRACE, "Defaulting Descriptor visibility to 1"); 933 } 934 935 //Checking validity 936 if (!clone.isValid()) { 937 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), 938 "The isValid() method of the Descriptor object itself returned false,"+ 939 "one or more required fields are invalid. Descriptor:" + clone.toString()); 940 } 941 942 if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase(MMB)) { 943 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"), 944 "The Descriptor \"descriptorType\" field does not match the object described. " + 945 " Expected: "+ MMB + " , was: " + clone.getFieldValue("descriptorType")); 946 } 947 948 return clone; 949 } 950 951 952 953 954 /** 955 * Deserializes a {@link ModelMBeanInfoSupport} from an {@link ObjectInputStream}. 956 */ 957 private void readObject(ObjectInputStream in) 958 throws IOException, ClassNotFoundException { 959 if (compat) { 960 // Read an object serialized in the old serial form 961 // 962 ObjectInputStream.GetField fields = in.readFields(); 963 modelMBeanDescriptor = 964 (Descriptor) fields.get("modelMBeanDescriptor", null); 965 if (fields.defaulted("modelMBeanDescriptor")) { 966 throw new NullPointerException("modelMBeanDescriptor"); 967 } 968 modelMBeanAttributes = 969 (MBeanAttributeInfo[]) fields.get("mmbAttributes", null); 970 if (fields.defaulted("mmbAttributes")) { 971 throw new NullPointerException("mmbAttributes"); 972 } 973 modelMBeanConstructors = 974 (MBeanConstructorInfo[]) fields.get("mmbConstructors", null); 975 if (fields.defaulted("mmbConstructors")) { 976 throw new NullPointerException("mmbConstructors"); 977 } 978 modelMBeanNotifications = 979 (MBeanNotificationInfo[]) fields.get("mmbNotifications", null); 980 if (fields.defaulted("mmbNotifications")) { 981 throw new NullPointerException("mmbNotifications"); 982 } 983 modelMBeanOperations = 984 (MBeanOperationInfo[]) fields.get("mmbOperations", null); 985 if (fields.defaulted("mmbOperations")) { 986 throw new NullPointerException("mmbOperations"); 987 } 988 } else { 989 // Read an object serialized in the new serial form 990 // 991 in.defaultReadObject(); 992 } 993 } 994 995 996 /** 997 * Serializes a {@link ModelMBeanInfoSupport} to an {@link ObjectOutputStream}. 998 */ 999 private void writeObject(ObjectOutputStream out) 1000 throws IOException { 1001 if (compat) { 1002 // Serializes this instance in the old serial form 1003 // 1004 ObjectOutputStream.PutField fields = out.putFields(); 1005 fields.put("modelMBeanDescriptor", modelMBeanDescriptor); 1006 fields.put("mmbAttributes", modelMBeanAttributes); 1007 fields.put("mmbConstructors", modelMBeanConstructors); 1008 fields.put("mmbNotifications", modelMBeanNotifications); 1009 fields.put("mmbOperations", modelMBeanOperations); 1010 fields.put("currClass", currClass); 1011 out.writeFields(); 1012 } else { 1013 // Serializes this instance in the new serial form 1014 // 1015 out.defaultWriteObject(); 1016 } 1017 } 1018 1019 1020 }