1 /* 2 * Copyright (c) 2000, 2008, 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 package javax.management.relation; 27 28 import static com.sun.jmx.defaults.JmxProperties.RELATION_LOGGER; 29 import static com.sun.jmx.mbeanserver.Util.cast; 30 31 import java.util.ArrayList; 32 import java.util.Date; 33 import java.util.HashMap; 34 import java.util.Iterator; 35 import java.util.List; 36 import java.util.Map; 37 import java.util.Set; 38 import java.util.concurrent.atomic.AtomicLong; 39 import java.util.logging.Level; 40 41 import javax.management.Attribute; 42 import javax.management.AttributeNotFoundException; 43 import javax.management.InstanceNotFoundException; 44 import javax.management.InvalidAttributeValueException; 45 import javax.management.MBeanException; 46 import javax.management.MBeanNotificationInfo; 47 import javax.management.MBeanRegistration; 48 import javax.management.MBeanServer; 49 import javax.management.MBeanServerDelegate; 50 import javax.management.MBeanServerNotification; 51 import javax.management.Notification; 52 import javax.management.NotificationBroadcasterSupport; 53 import javax.management.NotificationListener; 54 import javax.management.ObjectName; 55 import javax.management.ReflectionException; 56 57 /** 58 * The Relation Service is in charge of creating and deleting relation types 59 * and relations, of handling the consistency and of providing query 60 * mechanisms. 61 * <P>It implements the NotificationBroadcaster by extending 62 * NotificationBroadcasterSupport to send notifications when a relation is 63 * removed from it. 64 * <P>It implements the NotificationListener interface to be able to receive 65 * notifications concerning unregistration of MBeans referenced in relation 66 * roles and of relation MBeans. 67 * <P>It implements the MBeanRegistration interface to be able to retrieve 68 * its ObjectName and MBean Server. 69 * 70 * @since 1.5 71 */ 72 public class RelationService extends NotificationBroadcasterSupport 73 implements RelationServiceMBean, MBeanRegistration, NotificationListener { 74 75 // 76 // Private members 77 // 78 79 // Map associating: 80 // <relation id> -> <RelationSupport object/ObjectName> 81 // depending if the relation has been created using createRelation() 82 // method (so internally handled) or is an MBean added as a relation by the 83 // user 84 private Map<String,Object> myRelId2ObjMap = new HashMap<String,Object>(); 85 86 // Map associating: 87 // <relation id> -> <relation type name> 88 private Map<String,String> myRelId2RelTypeMap = new HashMap<String,String>(); 89 90 // Map associating: 91 // <relation MBean Object Name> -> <relation id> 92 private Map<ObjectName,String> myRelMBeanObjName2RelIdMap = 93 new HashMap<ObjectName,String>(); 94 95 // Map associating: 96 // <relation type name> -> <RelationType object> 97 private Map<String,RelationType> myRelType2ObjMap = 98 new HashMap<String,RelationType>(); 99 100 // Map associating: 101 // <relation type name> -> ArrayList of <relation id> 102 // to list all the relations of a given type 103 private Map<String,List<String>> myRelType2RelIdsMap = 104 new HashMap<String,List<String>>(); 105 106 // Map associating: 107 // <ObjectName> -> HashMap 108 // the value HashMap mapping: 109 // <relation id> -> ArrayList of <role name> 110 // to track where a given MBean is referenced. 111 private final Map<ObjectName,Map<String,List<String>>> 112 myRefedMBeanObjName2RelIdsMap = 113 new HashMap<ObjectName,Map<String,List<String>>>(); 114 115 // Flag to indicate if, when a notification is received for the 116 // unregistration of an MBean referenced in a relation, if an immediate 117 // "purge" of the relations (look for the relations no 118 // longer valid) has to be performed , or if that will be performed only 119 // when the purgeRelations method will be explicitly called. 120 // true is immediate purge. 121 private boolean myPurgeFlag = true; 122 123 // Internal counter to provide sequence numbers for notifications sent by: 124 // - the Relation Service 125 // - a relation handled by the Relation Service 126 private final AtomicLong atomicSeqNo = new AtomicLong(); 127 128 // ObjectName used to register the Relation Service in the MBean Server 129 private ObjectName myObjName = null; 130 131 // MBean Server where the Relation Service is registered 132 private MBeanServer myMBeanServer = null; 133 134 // Filter registered in the MBean Server with the Relation Service to be 135 // informed of referenced MBean unregistrations 136 private MBeanServerNotificationFilter myUnregNtfFilter = null; 137 138 // List of unregistration notifications received (storage used if purge 139 // of relations when unregistering a referenced MBean is not immediate but 140 // on user request) 141 private List<MBeanServerNotification> myUnregNtfList = 142 new ArrayList<MBeanServerNotification>(); 143 144 // 145 // Constructor 146 // 147 148 /** 149 * Constructor. 150 * 151 * @param immediatePurgeFlag flag to indicate when a notification is 152 * received for the unregistration of an MBean referenced in a relation, if 153 * an immediate "purge" of the relations (look for the relations no 154 * longer valid) has to be performed , or if that will be performed only 155 * when the purgeRelations method will be explicitly called. 156 * <P>true is immediate purge. 157 */ 158 public RelationService(boolean immediatePurgeFlag) { 159 160 RELATION_LOGGER.entering(RelationService.class.getName(), 161 "RelationService"); 162 163 setPurgeFlag(immediatePurgeFlag); 164 165 RELATION_LOGGER.exiting(RelationService.class.getName(), 166 "RelationService"); 167 return; 168 } 169 170 /** 171 * Checks if the Relation Service is active. 172 * Current condition is that the Relation Service must be registered in the 173 * MBean Server 174 * 175 * @exception RelationServiceNotRegisteredException if it is not 176 * registered 177 */ 178 public void isActive() 179 throws RelationServiceNotRegisteredException { 180 if (myMBeanServer == null) { 181 // MBean Server not set by preRegister(): relation service not 182 // registered 183 String excMsg = 184 "Relation Service not registered in the MBean Server."; 185 throw new RelationServiceNotRegisteredException(excMsg); 186 } 187 return; 188 } 189 190 // 191 // MBeanRegistration interface 192 // 193 194 // Pre-registration: retrieves its ObjectName and MBean Server 195 // 196 // No exception thrown. 197 public ObjectName preRegister(MBeanServer server, 198 ObjectName name) 199 throws Exception { 200 201 myMBeanServer = server; 202 myObjName = name; 203 return name; 204 } 205 206 // Post-registration: does nothing 207 public void postRegister(Boolean registrationDone) { 208 return; 209 } 210 211 // Pre-unregistration: does nothing 212 public void preDeregister() 213 throws Exception { 214 return; 215 } 216 217 // Post-unregistration: does nothing 218 public void postDeregister() { 219 return; 220 } 221 222 // 223 // Accessors 224 // 225 226 /** 227 * Returns the flag to indicate if when a notification is received for the 228 * unregistration of an MBean referenced in a relation, if an immediate 229 * "purge" of the relations (look for the relations no longer valid) 230 * has to be performed , or if that will be performed only when the 231 * purgeRelations method will be explicitly called. 232 * <P>true is immediate purge. 233 * 234 * @return true if purges are automatic. 235 * 236 * @see #setPurgeFlag 237 */ 238 public boolean getPurgeFlag() { 239 return myPurgeFlag; 240 } 241 242 /** 243 * Sets the flag to indicate if when a notification is received for the 244 * unregistration of an MBean referenced in a relation, if an immediate 245 * "purge" of the relations (look for the relations no longer valid) 246 * has to be performed , or if that will be performed only when the 247 * purgeRelations method will be explicitly called. 248 * <P>true is immediate purge. 249 * 250 * @param purgeFlag flag 251 * 252 * @see #getPurgeFlag 253 */ 254 public void setPurgeFlag(boolean purgeFlag) { 255 256 myPurgeFlag = purgeFlag; 257 return; 258 } 259 260 // 261 // Relation type handling 262 // 263 264 /** 265 * Creates a relation type (a RelationTypeSupport object) with given 266 * role infos (provided by the RoleInfo objects), and adds it in the 267 * Relation Service. 268 * 269 * @param relationTypeName name of the relation type 270 * @param roleInfoArray array of role infos 271 * 272 * @exception IllegalArgumentException if null parameter 273 * @exception InvalidRelationTypeException If: 274 * <P>- there is already a relation type with that name 275 * <P>- the same name has been used for two different role infos 276 * <P>- no role info provided 277 * <P>- one null role info provided 278 */ 279 public void createRelationType(String relationTypeName, 280 RoleInfo[] roleInfoArray) 281 throws IllegalArgumentException, 282 InvalidRelationTypeException { 283 284 if (relationTypeName == null || roleInfoArray == null) { 285 String excMsg = "Invalid parameter."; 286 throw new IllegalArgumentException(excMsg); 287 } 288 289 RELATION_LOGGER.entering(RelationService.class.getName(), 290 "createRelationType", relationTypeName); 291 292 // Can throw an InvalidRelationTypeException 293 RelationType relType = 294 new RelationTypeSupport(relationTypeName, roleInfoArray); 295 296 addRelationTypeInt(relType); 297 298 RELATION_LOGGER.exiting(RelationService.class.getName(), 299 "createRelationType"); 300 return; 301 } 302 303 /** 304 * Adds given object as a relation type. The object is expected to 305 * implement the RelationType interface. 306 * 307 * @param relationTypeObj relation type object (implementing the 308 * RelationType interface) 309 * 310 * @exception IllegalArgumentException if null parameter or if 311 * {@link RelationType#getRelationTypeName 312 * relationTypeObj.getRelationTypeName()} returns null. 313 * @exception InvalidRelationTypeException if: 314 * <P>- the same name has been used for two different roles 315 * <P>- no role info provided 316 * <P>- one null role info provided 317 * <P>- there is already a relation type with that name 318 */ 319 public void addRelationType(RelationType relationTypeObj) 320 throws IllegalArgumentException, 321 InvalidRelationTypeException { 322 323 if (relationTypeObj == null) { 324 String excMsg = "Invalid parameter."; 325 throw new IllegalArgumentException(excMsg); 326 } 327 328 RELATION_LOGGER.entering(RelationService.class.getName(), 329 "addRelationType"); 330 331 // Checks the role infos 332 List<RoleInfo> roleInfoList = relationTypeObj.getRoleInfos(); 333 if (roleInfoList == null) { 334 String excMsg = "No role info provided."; 335 throw new InvalidRelationTypeException(excMsg); 336 } 337 338 RoleInfo[] roleInfoArray = new RoleInfo[roleInfoList.size()]; 339 int i = 0; 340 for (RoleInfo currRoleInfo : roleInfoList) { 341 roleInfoArray[i] = currRoleInfo; 342 i++; 343 } 344 // Can throw InvalidRelationTypeException 345 RelationTypeSupport.checkRoleInfos(roleInfoArray); 346 347 addRelationTypeInt(relationTypeObj); 348 349 RELATION_LOGGER.exiting(RelationService.class.getName(), 350 "addRelationType"); 351 return; 352 } 353 354 /** 355 * Retrieves names of all known relation types. 356 * 357 * @return ArrayList of relation type names (Strings) 358 */ 359 public List<String> getAllRelationTypeNames() { 360 ArrayList<String> result; 361 synchronized(myRelType2ObjMap) { 362 result = new ArrayList<String>(myRelType2ObjMap.keySet()); 363 } 364 return result; 365 } 366 367 /** 368 * Retrieves list of role infos (RoleInfo objects) of a given relation 369 * type. 370 * 371 * @param relationTypeName name of relation type 372 * 373 * @return ArrayList of RoleInfo. 374 * 375 * @exception IllegalArgumentException if null parameter 376 * @exception RelationTypeNotFoundException if there is no relation type 377 * with that name. 378 */ 379 public List<RoleInfo> getRoleInfos(String relationTypeName) 380 throws IllegalArgumentException, 381 RelationTypeNotFoundException { 382 383 if (relationTypeName == null) { 384 String excMsg = "Invalid parameter."; 385 throw new IllegalArgumentException(excMsg); 386 } 387 388 RELATION_LOGGER.entering(RelationService.class.getName(), 389 "getRoleInfos", relationTypeName); 390 391 // Can throw a RelationTypeNotFoundException 392 RelationType relType = getRelationType(relationTypeName); 393 394 RELATION_LOGGER.exiting(RelationService.class.getName(), 395 "getRoleInfos"); 396 return relType.getRoleInfos(); 397 } 398 399 /** 400 * Retrieves role info for given role name of a given relation type. 401 * 402 * @param relationTypeName name of relation type 403 * @param roleInfoName name of role 404 * 405 * @return RoleInfo object. 406 * 407 * @exception IllegalArgumentException if null parameter 408 * @exception RelationTypeNotFoundException if the relation type is not 409 * known in the Relation Service 410 * @exception RoleInfoNotFoundException if the role is not part of the 411 * relation type. 412 */ 413 public RoleInfo getRoleInfo(String relationTypeName, 414 String roleInfoName) 415 throws IllegalArgumentException, 416 RelationTypeNotFoundException, 417 RoleInfoNotFoundException { 418 419 if (relationTypeName == null || roleInfoName == null) { 420 String excMsg = "Invalid parameter."; 421 throw new IllegalArgumentException(excMsg); 422 } 423 424 RELATION_LOGGER.entering(RelationService.class.getName(), 425 "getRoleInfo", new Object[] {relationTypeName, roleInfoName}); 426 427 // Can throw a RelationTypeNotFoundException 428 RelationType relType = getRelationType(relationTypeName); 429 430 // Can throw a RoleInfoNotFoundException 431 RoleInfo roleInfo = relType.getRoleInfo(roleInfoName); 432 433 RELATION_LOGGER.exiting(RelationService.class.getName(), 434 "getRoleInfo"); 435 return roleInfo; 436 } 437 438 /** 439 * Removes given relation type from Relation Service. 440 * <P>The relation objects of that type will be removed from the 441 * Relation Service. 442 * 443 * @param relationTypeName name of the relation type to be removed 444 * 445 * @exception RelationServiceNotRegisteredException if the Relation 446 * Service is not registered in the MBean Server 447 * @exception IllegalArgumentException if null parameter 448 * @exception RelationTypeNotFoundException If there is no relation type 449 * with that name 450 */ 451 public void removeRelationType(String relationTypeName) 452 throws RelationServiceNotRegisteredException, 453 IllegalArgumentException, 454 RelationTypeNotFoundException { 455 456 // Can throw RelationServiceNotRegisteredException 457 isActive(); 458 459 if (relationTypeName == null) { 460 String excMsg = "Invalid parameter."; 461 throw new IllegalArgumentException(excMsg); 462 } 463 464 RELATION_LOGGER.entering(RelationService.class.getName(), 465 "removeRelationType", relationTypeName); 466 467 // Checks if the relation type to be removed exists 468 // Can throw a RelationTypeNotFoundException 469 RelationType relType = getRelationType(relationTypeName); 470 471 // Retrieves the relation ids for relations of that type 472 List<String> relIdList = null; 473 synchronized(myRelType2RelIdsMap) { 474 // Note: take a copy of the list as it is a part of a map that 475 // will be updated by removeRelation() below. 476 List<String> relIdList1 = 477 myRelType2RelIdsMap.get(relationTypeName); 478 if (relIdList1 != null) { 479 relIdList = new ArrayList<String>(relIdList1); 480 } 481 } 482 483 // Removes the relation type from all maps 484 synchronized(myRelType2ObjMap) { 485 myRelType2ObjMap.remove(relationTypeName); 486 } 487 synchronized(myRelType2RelIdsMap) { 488 myRelType2RelIdsMap.remove(relationTypeName); 489 } 490 491 // Removes all relations of that type 492 if (relIdList != null) { 493 for (String currRelId : relIdList) { 494 // Note: will remove it from myRelId2RelTypeMap :) 495 // 496 // Can throw RelationServiceNotRegisteredException (detected 497 // above) 498 // Shall not throw a RelationNotFoundException 499 try { 500 removeRelation(currRelId); 501 } catch (RelationNotFoundException exc1) { 502 throw new RuntimeException(exc1.getMessage()); 503 } 504 } 505 } 506 507 RELATION_LOGGER.exiting(RelationService.class.getName(), 508 "removeRelationType"); 509 return; 510 } 511 512 // 513 // Relation handling 514 // 515 516 /** 517 * Creates a simple relation (represented by a RelationSupport object) of 518 * given relation type, and adds it in the Relation Service. 519 * <P>Roles are initialized according to the role list provided in 520 * parameter. The ones not initialized in this way are set to an empty 521 * ArrayList of ObjectNames. 522 * <P>A RelationNotification, with type RELATION_BASIC_CREATION, is sent. 523 * 524 * @param relationId relation identifier, to identify uniquely the relation 525 * inside the Relation Service 526 * @param relationTypeName name of the relation type (has to be created 527 * in the Relation Service) 528 * @param roleList role list to initialize roles of the relation (can 529 * be null). 530 * 531 * @exception RelationServiceNotRegisteredException if the Relation 532 * Service is not registered in the MBean Server 533 * @exception IllegalArgumentException if null parameter, except the role 534 * list which can be null if no role initialization 535 * @exception RoleNotFoundException if a value is provided for a role 536 * that does not exist in the relation type 537 * @exception InvalidRelationIdException if relation id already used 538 * @exception RelationTypeNotFoundException if relation type not known in 539 * Relation Service 540 * @exception InvalidRoleValueException if: 541 * <P>- the same role name is used for two different roles 542 * <P>- the number of referenced MBeans in given value is less than 543 * expected minimum degree 544 * <P>- the number of referenced MBeans in provided value exceeds expected 545 * maximum degree 546 * <P>- one referenced MBean in the value is not an Object of the MBean 547 * class expected for that role 548 * <P>- an MBean provided for that role does not exist 549 */ 550 public void createRelation(String relationId, 551 String relationTypeName, 552 RoleList roleList) 553 throws RelationServiceNotRegisteredException, 554 IllegalArgumentException, 555 RoleNotFoundException, 556 InvalidRelationIdException, 557 RelationTypeNotFoundException, 558 InvalidRoleValueException { 559 560 // Can throw RelationServiceNotRegisteredException 561 isActive(); 562 563 if (relationId == null || 564 relationTypeName == null) { 565 String excMsg = "Invalid parameter."; 566 throw new IllegalArgumentException(excMsg); 567 } 568 569 RELATION_LOGGER.entering(RelationService.class.getName(), 570 "createRelation", 571 new Object[] {relationId, relationTypeName, roleList}); 572 573 // Creates RelationSupport object 574 // Can throw InvalidRoleValueException 575 RelationSupport relObj = new RelationSupport(relationId, 576 myObjName, 577 relationTypeName, 578 roleList); 579 580 // Adds relation object as a relation into the Relation Service 581 // Can throw RoleNotFoundException, InvalidRelationId, 582 // RelationTypeNotFoundException, InvalidRoleValueException 583 // 584 // Cannot throw MBeanException 585 addRelationInt(true, 586 relObj, 587 null, 588 relationId, 589 relationTypeName, 590 roleList); 591 RELATION_LOGGER.exiting(RelationService.class.getName(), 592 "createRelation"); 593 return; 594 } 595 596 /** 597 * Adds an MBean created by the user (and registered by him in the MBean 598 * Server) as a relation in the Relation Service. 599 * <P>To be added as a relation, the MBean must conform to the 600 * following: 601 * <P>- implement the Relation interface 602 * <P>- have for RelationService ObjectName the ObjectName of current 603 * Relation Service 604 * <P>- have a relation id unique and unused in current Relation Service 605 * <P>- have for relation type a relation type created in the Relation 606 * Service 607 * <P>- have roles conforming to the role info provided in the relation 608 * type. 609 * 610 * @param relationObjectName ObjectName of the relation MBean to be added. 611 * 612 * @exception IllegalArgumentException if null parameter 613 * @exception RelationServiceNotRegisteredException if the Relation 614 * Service is not registered in the MBean Server 615 * @exception NoSuchMethodException If the MBean does not implement the 616 * Relation interface 617 * @exception InvalidRelationIdException if: 618 * <P>- no relation identifier in MBean 619 * <P>- the relation identifier is already used in the Relation Service 620 * @exception InstanceNotFoundException if the MBean for given ObjectName 621 * has not been registered 622 * @exception InvalidRelationServiceException if: 623 * <P>- no Relation Service name in MBean 624 * <P>- the Relation Service name in the MBean is not the one of the 625 * current Relation Service 626 * @exception RelationTypeNotFoundException if: 627 * <P>- no relation type name in MBean 628 * <P>- the relation type name in MBean does not correspond to a relation 629 * type created in the Relation Service 630 * @exception InvalidRoleValueException if: 631 * <P>- the number of referenced MBeans in a role is less than 632 * expected minimum degree 633 * <P>- the number of referenced MBeans in a role exceeds expected 634 * maximum degree 635 * <P>- one referenced MBean in the value is not an Object of the MBean 636 * class expected for that role 637 * <P>- an MBean provided for a role does not exist 638 * @exception RoleNotFoundException if a value is provided for a role 639 * that does not exist in the relation type 640 */ 641 public void addRelation(ObjectName relationObjectName) 642 throws IllegalArgumentException, 643 RelationServiceNotRegisteredException, 644 NoSuchMethodException, 645 InvalidRelationIdException, 646 InstanceNotFoundException, 647 InvalidRelationServiceException, 648 RelationTypeNotFoundException, 649 RoleNotFoundException, 650 InvalidRoleValueException { 651 652 if (relationObjectName == null) { 653 String excMsg = "Invalid parameter."; 654 throw new IllegalArgumentException(excMsg); 655 } 656 657 RELATION_LOGGER.entering(RelationService.class.getName(), 658 "addRelation", relationObjectName); 659 660 // Can throw RelationServiceNotRegisteredException 661 isActive(); 662 663 // Checks that the relation MBean implements the Relation interface. 664 // It will also check that the provided ObjectName corresponds to a 665 // registered MBean (else will throw an InstanceNotFoundException) 666 if ((!(myMBeanServer.isInstanceOf(relationObjectName, "javax.management.relation.Relation")))) { 667 String excMsg = "This MBean does not implement the Relation interface."; 668 throw new NoSuchMethodException(excMsg); 669 } 670 // Checks there is a relation id in the relation MBean (its uniqueness 671 // is checked in addRelationInt()) 672 // Can throw InstanceNotFoundException (but detected above) 673 // No MBeanException as no exception raised by this method, and no 674 // ReflectionException 675 String relId; 676 try { 677 relId = (String)(myMBeanServer.getAttribute(relationObjectName, 678 "RelationId")); 679 680 } catch (MBeanException exc1) { 681 throw new RuntimeException( 682 (exc1.getTargetException()).getMessage()); 683 } catch (ReflectionException exc2) { 684 throw new RuntimeException(exc2.getMessage()); 685 } catch (AttributeNotFoundException exc3) { 686 throw new RuntimeException(exc3.getMessage()); 687 } 688 689 if (relId == null) { 690 String excMsg = "This MBean does not provide a relation id."; 691 throw new InvalidRelationIdException(excMsg); 692 } 693 // Checks that the Relation Service where the relation MBean is 694 // expected to be added is the current one 695 // Can throw InstanceNotFoundException (but detected above) 696 // No MBeanException as no exception raised by this method, no 697 // ReflectionException 698 ObjectName relServObjName; 699 try { 700 relServObjName = (ObjectName) 701 (myMBeanServer.getAttribute(relationObjectName, 702 "RelationServiceName")); 703 704 } catch (MBeanException exc1) { 705 throw new RuntimeException( 706 (exc1.getTargetException()).getMessage()); 707 } catch (ReflectionException exc2) { 708 throw new RuntimeException(exc2.getMessage()); 709 } catch (AttributeNotFoundException exc3) { 710 throw new RuntimeException(exc3.getMessage()); 711 } 712 713 boolean badRelServFlag = false; 714 if (relServObjName == null) { 715 badRelServFlag = true; 716 717 } else if (!(relServObjName.equals(myObjName))) { 718 badRelServFlag = true; 719 } 720 if (badRelServFlag) { 721 String excMsg = "The Relation Service referenced in the MBean is not the current one."; 722 throw new InvalidRelationServiceException(excMsg); 723 } 724 // Checks that a relation type has been specified for the relation 725 // Can throw InstanceNotFoundException (but detected above) 726 // No MBeanException as no exception raised by this method, no 727 // ReflectionException 728 String relTypeName; 729 try { 730 relTypeName = (String)(myMBeanServer.getAttribute(relationObjectName, 731 "RelationTypeName")); 732 733 } catch (MBeanException exc1) { 734 throw new RuntimeException( 735 (exc1.getTargetException()).getMessage()); 736 }catch (ReflectionException exc2) { 737 throw new RuntimeException(exc2.getMessage()); 738 } catch (AttributeNotFoundException exc3) { 739 throw new RuntimeException(exc3.getMessage()); 740 } 741 if (relTypeName == null) { 742 String excMsg = "No relation type provided."; 743 throw new RelationTypeNotFoundException(excMsg); 744 } 745 // Retrieves all roles without considering read mode 746 // Can throw InstanceNotFoundException (but detected above) 747 // No MBeanException as no exception raised by this method, no 748 // ReflectionException 749 RoleList roleList; 750 try { 751 roleList = (RoleList)(myMBeanServer.invoke(relationObjectName, 752 "retrieveAllRoles", 753 null, 754 null)); 755 } catch (MBeanException exc1) { 756 throw new RuntimeException( 757 (exc1.getTargetException()).getMessage()); 758 } catch (ReflectionException exc2) { 759 throw new RuntimeException(exc2.getMessage()); 760 } 761 762 // Can throw RoleNotFoundException, InvalidRelationIdException, 763 // RelationTypeNotFoundException, InvalidRoleValueException 764 addRelationInt(false, 765 null, 766 relationObjectName, 767 relId, 768 relTypeName, 769 roleList); 770 // Adds relation MBean ObjectName in map 771 synchronized(myRelMBeanObjName2RelIdMap) { 772 myRelMBeanObjName2RelIdMap.put(relationObjectName, relId); 773 } 774 775 // Updates flag to specify that the relation is managed by the Relation 776 // Service 777 // This flag and setter are inherited from RelationSupport and not parts 778 // of the Relation interface, so may be not supported. 779 try { 780 myMBeanServer.setAttribute(relationObjectName, 781 new Attribute( 782 "RelationServiceManagementFlag", 783 Boolean.TRUE)); 784 } catch (Exception exc) { 785 // OK : The flag is not supported. 786 } 787 788 // Updates listener information to received notification for 789 // unregistration of this MBean 790 List<ObjectName> newRefList = new ArrayList<ObjectName>(); 791 newRefList.add(relationObjectName); 792 updateUnregistrationListener(newRefList, null); 793 794 RELATION_LOGGER.exiting(RelationService.class.getName(), 795 "addRelation"); 796 return; 797 } 798 799 /** 800 * If the relation is represented by an MBean (created by the user and 801 * added as a relation in the Relation Service), returns the ObjectName of 802 * the MBean. 803 * 804 * @param relationId relation id identifying the relation 805 * 806 * @return ObjectName of the corresponding relation MBean, or null if 807 * the relation is not an MBean. 808 * 809 * @exception IllegalArgumentException if null parameter 810 * @exception RelationNotFoundException there is no relation associated 811 * to that id 812 */ 813 public ObjectName isRelationMBean(String relationId) 814 throws IllegalArgumentException, 815 RelationNotFoundException{ 816 817 if (relationId == null) { 818 String excMsg = "Invalid parameter."; 819 throw new IllegalArgumentException(excMsg); 820 } 821 822 RELATION_LOGGER.entering(RelationService.class.getName(), 823 "isRelationMBean", relationId); 824 825 // Can throw RelationNotFoundException 826 Object result = getRelation(relationId); 827 if (result instanceof ObjectName) { 828 return ((ObjectName)result); 829 } else { 830 return null; 831 } 832 } 833 834 /** 835 * Returns the relation id associated to the given ObjectName if the 836 * MBean has been added as a relation in the Relation Service. 837 * 838 * @param objectName ObjectName of supposed relation 839 * 840 * @return relation id (String) or null (if the ObjectName is not a 841 * relation handled by the Relation Service) 842 * 843 * @exception IllegalArgumentException if null parameter 844 */ 845 public String isRelation(ObjectName objectName) 846 throws IllegalArgumentException { 847 848 if (objectName == null) { 849 String excMsg = "Invalid parameter."; 850 throw new IllegalArgumentException(excMsg); 851 } 852 853 RELATION_LOGGER.entering(RelationService.class.getName(), 854 "isRelation", objectName); 855 856 String result = null; 857 synchronized(myRelMBeanObjName2RelIdMap) { 858 String relId = myRelMBeanObjName2RelIdMap.get(objectName); 859 if (relId != null) { 860 result = relId; 861 } 862 } 863 return result; 864 } 865 866 /** 867 * Checks if there is a relation identified in Relation Service with given 868 * relation id. 869 * 870 * @param relationId relation id identifying the relation 871 * 872 * @return boolean: true if there is a relation, false else 873 * 874 * @exception IllegalArgumentException if null parameter 875 */ 876 public Boolean hasRelation(String relationId) 877 throws IllegalArgumentException { 878 879 if (relationId == null) { 880 String excMsg = "Invalid parameter."; 881 throw new IllegalArgumentException(excMsg); 882 } 883 884 RELATION_LOGGER.entering(RelationService.class.getName(), 885 "hasRelation", relationId); 886 887 try { 888 // Can throw RelationNotFoundException 889 Object result = getRelation(relationId); 890 return true; 891 } catch (RelationNotFoundException exc) { 892 return false; 893 } 894 } 895 896 /** 897 * Returns all the relation ids for all the relations handled by the 898 * Relation Service. 899 * 900 * @return ArrayList of String 901 */ 902 public List<String> getAllRelationIds() { 903 List<String> result; 904 synchronized(myRelId2ObjMap) { 905 result = new ArrayList<String>(myRelId2ObjMap.keySet()); 906 } 907 return result; 908 } 909 910 /** 911 * Checks if given Role can be read in a relation of the given type. 912 * 913 * @param roleName name of role to be checked 914 * @param relationTypeName name of the relation type 915 * 916 * @return an Integer wrapping an integer corresponding to possible 917 * problems represented as constants in RoleUnresolved: 918 * <P>- 0 if role can be read 919 * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME 920 * <P>- integer corresponding to RoleStatus.ROLE_NOT_READABLE 921 * 922 * @exception IllegalArgumentException if null parameter 923 * @exception RelationTypeNotFoundException if the relation type is not 924 * known in the Relation Service 925 */ 926 public Integer checkRoleReading(String roleName, 927 String relationTypeName) 928 throws IllegalArgumentException, 929 RelationTypeNotFoundException { 930 931 if (roleName == null || relationTypeName == null) { 932 String excMsg = "Invalid parameter."; 933 throw new IllegalArgumentException(excMsg); 934 } 935 936 RELATION_LOGGER.entering(RelationService.class.getName(), 937 "checkRoleReading", new Object[] {roleName, relationTypeName}); 938 939 Integer result; 940 941 // Can throw a RelationTypeNotFoundException 942 RelationType relType = getRelationType(relationTypeName); 943 944 try { 945 // Can throw a RoleInfoNotFoundException to be transformed into 946 // returned value RoleStatus.NO_ROLE_WITH_NAME 947 RoleInfo roleInfo = relType.getRoleInfo(roleName); 948 949 result = checkRoleInt(1, 950 roleName, 951 null, 952 roleInfo, 953 false); 954 955 } catch (RoleInfoNotFoundException exc) { 956 result = Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); 957 } 958 959 RELATION_LOGGER.exiting(RelationService.class.getName(), 960 "checkRoleReading"); 961 return result; 962 } 963 964 /** 965 * Checks if given Role can be set in a relation of given type. 966 * 967 * @param role role to be checked 968 * @param relationTypeName name of relation type 969 * @param initFlag flag to specify that the checking is done for the 970 * initialization of a role, write access shall not be verified. 971 * 972 * @return an Integer wrapping an integer corresponding to possible 973 * problems represented as constants in RoleUnresolved: 974 * <P>- 0 if role can be set 975 * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME 976 * <P>- integer for RoleStatus.ROLE_NOT_WRITABLE 977 * <P>- integer for RoleStatus.LESS_THAN_MIN_ROLE_DEGREE 978 * <P>- integer for RoleStatus.MORE_THAN_MAX_ROLE_DEGREE 979 * <P>- integer for RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS 980 * <P>- integer for RoleStatus.REF_MBEAN_NOT_REGISTERED 981 * 982 * @exception IllegalArgumentException if null parameter 983 * @exception RelationTypeNotFoundException if unknown relation type 984 */ 985 public Integer checkRoleWriting(Role role, 986 String relationTypeName, 987 Boolean initFlag) 988 throws IllegalArgumentException, 989 RelationTypeNotFoundException { 990 991 if (role == null || 992 relationTypeName == null || 993 initFlag == null) { 994 String excMsg = "Invalid parameter."; 995 throw new IllegalArgumentException(excMsg); 996 } 997 998 RELATION_LOGGER.entering(RelationService.class.getName(), 999 "checkRoleWriting", 1000 new Object[] {role, relationTypeName, initFlag}); 1001 1002 // Can throw a RelationTypeNotFoundException 1003 RelationType relType = getRelationType(relationTypeName); 1004 1005 String roleName = role.getRoleName(); 1006 List<ObjectName> roleValue = role.getRoleValue(); 1007 boolean writeChkFlag = true; 1008 if (initFlag.booleanValue()) { 1009 writeChkFlag = false; 1010 } 1011 1012 RoleInfo roleInfo; 1013 try { 1014 roleInfo = relType.getRoleInfo(roleName); 1015 } catch (RoleInfoNotFoundException exc) { 1016 RELATION_LOGGER.exiting(RelationService.class.getName(), 1017 "checkRoleWriting"); 1018 return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); 1019 } 1020 1021 Integer result = checkRoleInt(2, 1022 roleName, 1023 roleValue, 1024 roleInfo, 1025 writeChkFlag); 1026 1027 RELATION_LOGGER.exiting(RelationService.class.getName(), 1028 "checkRoleWriting"); 1029 return result; 1030 } 1031 1032 /** 1033 * Sends a notification (RelationNotification) for a relation creation. 1034 * The notification type is: 1035 * <P>- RelationNotification.RELATION_BASIC_CREATION if the relation is an 1036 * object internal to the Relation Service 1037 * <P>- RelationNotification.RELATION_MBEAN_CREATION if the relation is a 1038 * MBean added as a relation. 1039 * <P>The source object is the Relation Service itself. 1040 * <P>It is called in Relation Service createRelation() and 1041 * addRelation() methods. 1042 * 1043 * @param relationId relation identifier of the updated relation 1044 * 1045 * @exception IllegalArgumentException if null parameter 1046 * @exception RelationNotFoundException if there is no relation for given 1047 * relation id 1048 */ 1049 public void sendRelationCreationNotification(String relationId) 1050 throws IllegalArgumentException, 1051 RelationNotFoundException { 1052 1053 if (relationId == null) { 1054 String excMsg = "Invalid parameter."; 1055 throw new IllegalArgumentException(excMsg); 1056 } 1057 1058 RELATION_LOGGER.entering(RelationService.class.getName(), 1059 "sendRelationCreationNotification", relationId); 1060 1061 // Message 1062 StringBuilder ntfMsg = new StringBuilder("Creation of relation "); 1063 ntfMsg.append(relationId); 1064 1065 // Can throw RelationNotFoundException 1066 sendNotificationInt(1, 1067 ntfMsg.toString(), 1068 relationId, 1069 null, 1070 null, 1071 null, 1072 null); 1073 1074 RELATION_LOGGER.exiting(RelationService.class.getName(), 1075 "sendRelationCreationNotification"); 1076 return; 1077 } 1078 1079 /** 1080 * Sends a notification (RelationNotification) for a role update in the 1081 * given relation. The notification type is: 1082 * <P>- RelationNotification.RELATION_BASIC_UPDATE if the relation is an 1083 * object internal to the Relation Service 1084 * <P>- RelationNotification.RELATION_MBEAN_UPDATE if the relation is a 1085 * MBean added as a relation. 1086 * <P>The source object is the Relation Service itself. 1087 * <P>It is called in relation MBean setRole() (for given role) and 1088 * setRoles() (for each role) methods (implementation provided in 1089 * RelationSupport class). 1090 * <P>It is also called in Relation Service setRole() (for given role) and 1091 * setRoles() (for each role) methods. 1092 * 1093 * @param relationId relation identifier of the updated relation 1094 * @param newRole new role (name and new value) 1095 * @param oldValue old role value (List of ObjectName objects) 1096 * 1097 * @exception IllegalArgumentException if null parameter 1098 * @exception RelationNotFoundException if there is no relation for given 1099 * relation id 1100 */ 1101 public void sendRoleUpdateNotification(String relationId, 1102 Role newRole, 1103 List<ObjectName> oldValue) 1104 throws IllegalArgumentException, 1105 RelationNotFoundException { 1106 1107 if (relationId == null || 1108 newRole == null || 1109 oldValue == null) { 1110 String excMsg = "Invalid parameter."; 1111 throw new IllegalArgumentException(excMsg); 1112 } 1113 1114 if (!(oldValue instanceof ArrayList<?>)) 1115 oldValue = new ArrayList<ObjectName>(oldValue); 1116 1117 RELATION_LOGGER.entering(RelationService.class.getName(), 1118 "sendRoleUpdateNotification", 1119 new Object[] {relationId, newRole, oldValue}); 1120 1121 String roleName = newRole.getRoleName(); 1122 List<ObjectName> newRoleVal = newRole.getRoleValue(); 1123 1124 // Message 1125 String newRoleValString = Role.roleValueToString(newRoleVal); 1126 String oldRoleValString = Role.roleValueToString(oldValue); 1127 StringBuilder ntfMsg = new StringBuilder("Value of role "); 1128 ntfMsg.append(roleName); 1129 ntfMsg.append(" has changed\nOld value:\n"); 1130 ntfMsg.append(oldRoleValString); 1131 ntfMsg.append("\nNew value:\n"); 1132 ntfMsg.append(newRoleValString); 1133 1134 // Can throw a RelationNotFoundException 1135 sendNotificationInt(2, 1136 ntfMsg.toString(), 1137 relationId, 1138 null, 1139 roleName, 1140 newRoleVal, 1141 oldValue); 1142 1143 RELATION_LOGGER.exiting(RelationService.class.getName(), 1144 "sendRoleUpdateNotification"); 1145 } 1146 1147 /** 1148 * Sends a notification (RelationNotification) for a relation removal. 1149 * The notification type is: 1150 * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation is an 1151 * object internal to the Relation Service 1152 * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is a 1153 * MBean added as a relation. 1154 * <P>The source object is the Relation Service itself. 1155 * <P>It is called in Relation Service removeRelation() method. 1156 * 1157 * @param relationId relation identifier of the updated relation 1158 * @param unregMBeanList List of ObjectNames of MBeans expected 1159 * to be unregistered due to relation removal (can be null) 1160 * 1161 * @exception IllegalArgumentException if null parameter 1162 * @exception RelationNotFoundException if there is no relation for given 1163 * relation id 1164 */ 1165 public void sendRelationRemovalNotification(String relationId, 1166 List<ObjectName> unregMBeanList) 1167 throws IllegalArgumentException, 1168 RelationNotFoundException { 1169 1170 if (relationId == null) { 1171 String excMsg = "Invalid parameter"; 1172 throw new IllegalArgumentException(excMsg); 1173 } 1174 1175 RELATION_LOGGER.entering(RelationService.class.getName(), 1176 "sendRelationRemovalNotification", 1177 new Object[] {relationId, unregMBeanList}); 1178 1179 // Can throw RelationNotFoundException 1180 sendNotificationInt(3, 1181 "Removal of relation " + relationId, 1182 relationId, 1183 unregMBeanList, 1184 null, 1185 null, 1186 null); 1187 1188 1189 RELATION_LOGGER.exiting(RelationService.class.getName(), 1190 "sendRelationRemovalNotification"); 1191 return; 1192 } 1193 1194 /** 1195 * Handles update of the Relation Service role map for the update of given 1196 * role in given relation. 1197 * <P>It is called in relation MBean setRole() (for given role) and 1198 * setRoles() (for each role) methods (implementation provided in 1199 * RelationSupport class). 1200 * <P>It is also called in Relation Service setRole() (for given role) and 1201 * setRoles() (for each role) methods. 1202 * <P>To allow the Relation Service to maintain the consistency (in case 1203 * of MBean unregistration) and to be able to perform queries, this method 1204 * must be called when a role is updated. 1205 * 1206 * @param relationId relation identifier of the updated relation 1207 * @param newRole new role (name and new value) 1208 * @param oldValue old role value (List of ObjectName objects) 1209 * 1210 * @exception IllegalArgumentException if null parameter 1211 * @exception RelationServiceNotRegisteredException if the Relation 1212 * Service is not registered in the MBean Server 1213 * @exception RelationNotFoundException if no relation for given id. 1214 */ 1215 public void updateRoleMap(String relationId, 1216 Role newRole, 1217 List<ObjectName> oldValue) 1218 throws IllegalArgumentException, 1219 RelationServiceNotRegisteredException, 1220 RelationNotFoundException { 1221 1222 if (relationId == null || 1223 newRole == null || 1224 oldValue == null) { 1225 String excMsg = "Invalid parameter."; 1226 throw new IllegalArgumentException(excMsg); 1227 } 1228 1229 RELATION_LOGGER.entering(RelationService.class.getName(), 1230 "updateRoleMap", new Object[] {relationId, newRole, oldValue}); 1231 1232 // Can throw RelationServiceNotRegisteredException 1233 isActive(); 1234 1235 // Verifies the relation has been added in the Relation Service 1236 // Can throw a RelationNotFoundException 1237 Object result = getRelation(relationId); 1238 1239 String roleName = newRole.getRoleName(); 1240 List<ObjectName> newRoleValue = newRole.getRoleValue(); 1241 // Note: no need to test if oldValue not null before cloning, 1242 // tested above. 1243 List<ObjectName> oldRoleValue = 1244 new ArrayList<ObjectName>(oldValue); 1245 1246 // List of ObjectNames of new referenced MBeans 1247 List<ObjectName> newRefList = new ArrayList<ObjectName>(); 1248 1249 for (ObjectName currObjName : newRoleValue) { 1250 1251 // Checks if this ObjectName was already present in old value 1252 // Note: use copy (oldRoleValue) instead of original 1253 // oldValue to speed up, as oldRoleValue is decreased 1254 // by removing unchanged references :) 1255 int currObjNamePos = oldRoleValue.indexOf(currObjName); 1256 1257 if (currObjNamePos == -1) { 1258 // New reference to an ObjectName 1259 1260 // Stores this reference into map 1261 // Returns true if new reference, false if MBean already 1262 // referenced 1263 boolean isNewFlag = addNewMBeanReference(currObjName, 1264 relationId, 1265 roleName); 1266 1267 if (isNewFlag) { 1268 // Adds it into list of new reference 1269 newRefList.add(currObjName); 1270 } 1271 1272 } else { 1273 // MBean was already referenced in old value 1274 1275 // Removes it from old value (local list) to ignore it when 1276 // looking for remove MBean references 1277 oldRoleValue.remove(currObjNamePos); 1278 } 1279 } 1280 1281 // List of ObjectNames of MBeans no longer referenced 1282 List<ObjectName> obsRefList = new ArrayList<ObjectName>(); 1283 1284 // Each ObjectName remaining in oldRoleValue is an ObjectName no longer 1285 // referenced in new value 1286 for (ObjectName currObjName : oldRoleValue) { 1287 // Removes MBean reference from map 1288 // Returns true if the MBean is no longer referenced in any 1289 // relation 1290 boolean noLongerRefFlag = removeMBeanReference(currObjName, 1291 relationId, 1292 roleName, 1293 false); 1294 1295 if (noLongerRefFlag) { 1296 // Adds it into list of references to be removed 1297 obsRefList.add(currObjName); 1298 } 1299 } 1300 1301 // To avoid having one listener per ObjectName of referenced MBean, 1302 // and to increase performances, there is only one listener recording 1303 // all ObjectNames of interest 1304 updateUnregistrationListener(newRefList, obsRefList); 1305 1306 RELATION_LOGGER.exiting(RelationService.class.getName(), 1307 "updateRoleMap"); 1308 return; 1309 } 1310 1311 /** 1312 * Removes given relation from the Relation Service. 1313 * <P>A RelationNotification notification is sent, its type being: 1314 * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation was 1315 * only internal to the Relation Service 1316 * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is 1317 * registered as an MBean. 1318 * <P>For MBeans referenced in such relation, nothing will be done, 1319 * 1320 * @param relationId relation id of the relation to be removed 1321 * 1322 * @exception RelationServiceNotRegisteredException if the Relation 1323 * Service is not registered in the MBean Server 1324 * @exception IllegalArgumentException if null parameter 1325 * @exception RelationNotFoundException if no relation corresponding to 1326 * given relation id 1327 */ 1328 public void removeRelation(String relationId) 1329 throws RelationServiceNotRegisteredException, 1330 IllegalArgumentException, 1331 RelationNotFoundException { 1332 1333 // Can throw RelationServiceNotRegisteredException 1334 isActive(); 1335 1336 if (relationId == null) { 1337 String excMsg = "Invalid parameter."; 1338 throw new IllegalArgumentException(excMsg); 1339 } 1340 1341 RELATION_LOGGER.entering(RelationService.class.getName(), 1342 "removeRelation", relationId); 1343 1344 // Checks there is a relation with this id 1345 // Can throw RelationNotFoundException 1346 Object result = getRelation(relationId); 1347 1348 // Removes it from listener filter 1349 if (result instanceof ObjectName) { 1350 List<ObjectName> obsRefList = new ArrayList<ObjectName>(); 1351 obsRefList.add((ObjectName)result); 1352 // Can throw a RelationServiceNotRegisteredException 1353 updateUnregistrationListener(null, obsRefList); 1354 } 1355 1356 // Sends a notification 1357 // Note: has to be done FIRST as needs the relation to be still in the 1358 // Relation Service 1359 // No RelationNotFoundException as checked above 1360 1361 // Revisit [cebro] Handle CIM "Delete" and "IfDeleted" qualifiers: 1362 // deleting the relation can mean to delete referenced MBeans. In 1363 // that case, MBeans to be unregistered are put in a list sent along 1364 // with the notification below 1365 1366 // Can throw a RelationNotFoundException (but detected above) 1367 sendRelationRemovalNotification(relationId, null); 1368 1369 // Removes the relation from various internal maps 1370 1371 // - MBean reference map 1372 // Retrieves the MBeans referenced in this relation 1373 // Note: here we cannot use removeMBeanReference() because it would 1374 // require to know the MBeans referenced in the relation. For 1375 // that it would be necessary to call 'getReferencedMBeans()' 1376 // on the relation itself. Ok if it is an internal one, but if 1377 // it is an MBean, it is possible it is already unregistered, so 1378 // not available through the MBean Server. 1379 List<ObjectName> refMBeanList = new ArrayList<ObjectName>(); 1380 // List of MBeans no longer referenced in any relation, to be 1381 // removed fom the map 1382 List<ObjectName> nonRefObjNameList = new ArrayList<ObjectName>(); 1383 1384 synchronized(myRefedMBeanObjName2RelIdsMap) { 1385 1386 for (ObjectName currRefObjName : 1387 myRefedMBeanObjName2RelIdsMap.keySet()) { 1388 1389 // Retrieves relations where the MBean is referenced 1390 Map<String,List<String>> relIdMap = 1391 myRefedMBeanObjName2RelIdsMap.get(currRefObjName); 1392 1393 if (relIdMap.containsKey(relationId)) { 1394 relIdMap.remove(relationId); 1395 refMBeanList.add(currRefObjName); 1396 } 1397 1398 if (relIdMap.isEmpty()) { 1399 // MBean no longer referenced 1400 // Note: do not remove it here because pointed by the 1401 // iterator! 1402 nonRefObjNameList.add(currRefObjName); 1403 } 1404 } 1405 1406 // Cleans MBean reference map by removing MBeans no longer 1407 // referenced 1408 for (ObjectName currRefObjName : nonRefObjNameList) { 1409 myRefedMBeanObjName2RelIdsMap.remove(currRefObjName); 1410 } 1411 } 1412 1413 // - Relation id to object map 1414 synchronized(myRelId2ObjMap) { 1415 myRelId2ObjMap.remove(relationId); 1416 } 1417 1418 if (result instanceof ObjectName) { 1419 // - ObjectName to relation id map 1420 synchronized(myRelMBeanObjName2RelIdMap) { 1421 myRelMBeanObjName2RelIdMap.remove((ObjectName)result); 1422 } 1423 } 1424 1425 // Relation id to relation type name map 1426 // First retrieves the relation type name 1427 String relTypeName; 1428 synchronized(myRelId2RelTypeMap) { 1429 relTypeName = myRelId2RelTypeMap.get(relationId); 1430 myRelId2RelTypeMap.remove(relationId); 1431 } 1432 // - Relation type name to relation id map 1433 synchronized(myRelType2RelIdsMap) { 1434 List<String> relIdList = myRelType2RelIdsMap.get(relTypeName); 1435 if (relIdList != null) { 1436 // Can be null if called from removeRelationType() 1437 relIdList.remove(relationId); 1438 if (relIdList.isEmpty()) { 1439 // No other relation of that type 1440 myRelType2RelIdsMap.remove(relTypeName); 1441 } 1442 } 1443 } 1444 1445 RELATION_LOGGER.exiting(RelationService.class.getName(), 1446 "removeRelation"); 1447 return; 1448 } 1449 1450 /** 1451 * Purges the relations. 1452 * 1453 * <P>Depending on the purgeFlag value, this method is either called 1454 * automatically when a notification is received for the unregistration of 1455 * an MBean referenced in a relation (if the flag is set to true), or not 1456 * (if the flag is set to false). 1457 * <P>In that case it is up to the user to call it to maintain the 1458 * consistency of the relations. To be kept in mind that if an MBean is 1459 * unregistered and the purge not done immediately, if the ObjectName is 1460 * reused and assigned to another MBean referenced in a relation, calling 1461 * manually this purgeRelations() method will cause trouble, as will 1462 * consider the ObjectName as corresponding to the unregistered MBean, not 1463 * seeing the new one. 1464 * 1465 * <P>The behavior depends on the cardinality of the role where the 1466 * unregistered MBean is referenced: 1467 * <P>- if removing one MBean reference in the role makes its number of 1468 * references less than the minimum degree, the relation has to be removed. 1469 * <P>- if the remaining number of references after removing the MBean 1470 * reference is still in the cardinality range, keep the relation and 1471 * update it calling its handleMBeanUnregistration() callback. 1472 * 1473 * @exception RelationServiceNotRegisteredException if the Relation 1474 * Service is not registered in the MBean Server. 1475 */ 1476 public void purgeRelations() 1477 throws RelationServiceNotRegisteredException { 1478 1479 RELATION_LOGGER.entering(RelationService.class.getName(), 1480 "purgeRelations"); 1481 1482 // Can throw RelationServiceNotRegisteredException 1483 isActive(); 1484 1485 // Revisit [cebro] Handle the CIM "Delete" and "IfDeleted" qualifier: 1486 // if the unregistered MBean has the "IfDeleted" qualifier, 1487 // possible that the relation itself or other referenced MBeans 1488 // have to be removed (then a notification would have to be sent 1489 // to inform that they should be unregistered. 1490 1491 1492 // Clones the list of notifications to be able to still receive new 1493 // notifications while proceeding those ones 1494 List<MBeanServerNotification> localUnregNtfList; 1495 synchronized(myRefedMBeanObjName2RelIdsMap) { 1496 localUnregNtfList = 1497 new ArrayList<MBeanServerNotification>(myUnregNtfList); 1498 // Resets list 1499 myUnregNtfList = new ArrayList<MBeanServerNotification>(); 1500 } 1501 1502 1503 // Updates the listener filter to avoid receiving notifications for 1504 // those MBeans again 1505 // Makes also a local "myRefedMBeanObjName2RelIdsMap" map, mapping 1506 // ObjectName -> relId -> roles, to remove the MBean from the global 1507 // map 1508 // List of references to be removed from the listener filter 1509 List<ObjectName> obsRefList = new ArrayList<ObjectName>(); 1510 // Map including ObjectNames for unregistered MBeans, with 1511 // referencing relation ids and roles 1512 Map<ObjectName,Map<String,List<String>>> localMBean2RelIdMap = 1513 new HashMap<ObjectName,Map<String,List<String>>>(); 1514 1515 synchronized(myRefedMBeanObjName2RelIdsMap) { 1516 for (MBeanServerNotification currNtf : localUnregNtfList) { 1517 1518 ObjectName unregMBeanName = currNtf.getMBeanName(); 1519 1520 // Adds the unregsitered MBean in the list of references to 1521 // remove from the listener filter 1522 obsRefList.add(unregMBeanName); 1523 1524 // Retrieves the associated map of relation ids and roles 1525 Map<String,List<String>> relIdMap = 1526 myRefedMBeanObjName2RelIdsMap.get(unregMBeanName); 1527 localMBean2RelIdMap.put(unregMBeanName, relIdMap); 1528 1529 myRefedMBeanObjName2RelIdsMap.remove(unregMBeanName); 1530 } 1531 } 1532 1533 // Updates the listener 1534 // Can throw RelationServiceNotRegisteredException 1535 updateUnregistrationListener(null, obsRefList); 1536 1537 for (MBeanServerNotification currNtf : localUnregNtfList) { 1538 1539 ObjectName unregMBeanName = currNtf.getMBeanName(); 1540 1541 // Retrieves the relations where the MBean is referenced 1542 Map<String,List<String>> localRelIdMap = 1543 localMBean2RelIdMap.get(unregMBeanName); 1544 1545 // List of relation ids where the unregistered MBean is 1546 // referenced 1547 for (Map.Entry<String,List<String>> currRel : 1548 localRelIdMap.entrySet()) { 1549 final String currRelId = currRel.getKey(); 1550 // List of roles of the relation where the MBean is 1551 // referenced 1552 List<String> localRoleNameList = currRel.getValue(); 1553 1554 // Checks if the relation has to be removed or not, 1555 // regarding expected minimum role cardinality and current 1556 // number of references after removal of the current one 1557 // If the relation is kept, calls 1558 // handleMBeanUnregistration() callback of the relation to 1559 // update it 1560 // 1561 // Can throw RelationServiceNotRegisteredException 1562 // 1563 // Shall not throw RelationNotFoundException, 1564 // RoleNotFoundException, MBeanException 1565 try { 1566 handleReferenceUnregistration(currRelId, 1567 unregMBeanName, 1568 localRoleNameList); 1569 } catch (RelationNotFoundException exc1) { 1570 throw new RuntimeException(exc1.getMessage()); 1571 } catch (RoleNotFoundException exc2) { 1572 throw new RuntimeException(exc2.getMessage()); 1573 } 1574 } 1575 } 1576 1577 RELATION_LOGGER.exiting(RelationService.class.getName(), 1578 "purgeRelations"); 1579 return; 1580 } 1581 1582 /** 1583 * Retrieves the relations where a given MBean is referenced. 1584 * <P>This corresponds to the CIM "References" and "ReferenceNames" 1585 * operations. 1586 * 1587 * @param mbeanName ObjectName of MBean 1588 * @param relationTypeName can be null; if specified, only the relations 1589 * of that type will be considered in the search. Else all relation types 1590 * are considered. 1591 * @param roleName can be null; if specified, only the relations 1592 * where the MBean is referenced in that role will be returned. Else all 1593 * roles are considered. 1594 * 1595 * @return an HashMap, where the keys are the relation ids of the relations 1596 * where the MBean is referenced, and the value is, for each key, 1597 * an ArrayList of role names (as an MBean can be referenced in several 1598 * roles in the same relation). 1599 * 1600 * @exception IllegalArgumentException if null parameter 1601 */ 1602 public Map<String,List<String>> 1603 findReferencingRelations(ObjectName mbeanName, 1604 String relationTypeName, 1605 String roleName) 1606 throws IllegalArgumentException { 1607 1608 if (mbeanName == null) { 1609 String excMsg = "Invalid parameter."; 1610 throw new IllegalArgumentException(excMsg); 1611 } 1612 1613 RELATION_LOGGER.entering(RelationService.class.getName(), 1614 "findReferencingRelations", 1615 new Object[] {mbeanName, relationTypeName, roleName}); 1616 1617 Map<String,List<String>> result = new HashMap<String,List<String>>(); 1618 1619 synchronized(myRefedMBeanObjName2RelIdsMap) { 1620 1621 // Retrieves the relations referencing the MBean 1622 Map<String,List<String>> relId2RoleNamesMap = 1623 myRefedMBeanObjName2RelIdsMap.get(mbeanName); 1624 1625 if (relId2RoleNamesMap != null) { 1626 1627 // Relation Ids where the MBean is referenced 1628 Set<String> allRelIdSet = relId2RoleNamesMap.keySet(); 1629 1630 // List of relation ids of interest regarding the selected 1631 // relation type 1632 List<String> relIdList; 1633 if (relationTypeName == null) { 1634 // Considers all relations 1635 relIdList = new ArrayList<String>(allRelIdSet); 1636 1637 } else { 1638 1639 relIdList = new ArrayList<String>(); 1640 1641 // Considers only the relation ids for relations of given 1642 // type 1643 for (String currRelId : allRelIdSet) { 1644 1645 // Retrieves its relation type 1646 String currRelTypeName; 1647 synchronized(myRelId2RelTypeMap) { 1648 currRelTypeName = 1649 myRelId2RelTypeMap.get(currRelId); 1650 } 1651 1652 if (currRelTypeName.equals(relationTypeName)) { 1653 1654 relIdList.add(currRelId); 1655 1656 } 1657 } 1658 } 1659 1660 // Now looks at the roles where the MBean is expected to be 1661 // referenced 1662 1663 for (String currRelId : relIdList) { 1664 // Retrieves list of role names where the MBean is 1665 // referenced 1666 List<String> currRoleNameList = 1667 relId2RoleNamesMap.get(currRelId); 1668 1669 if (roleName == null) { 1670 // All roles to be considered 1671 // Note: no need to test if list not null before 1672 // cloning, MUST be not null else bug :( 1673 result.put(currRelId, 1674 new ArrayList<String>(currRoleNameList)); 1675 1676 } else if (currRoleNameList.contains(roleName)) { 1677 // Filters only the relations where the MBean is 1678 // referenced in // given role 1679 List<String> dummyList = new ArrayList<String>(); 1680 dummyList.add(roleName); 1681 result.put(currRelId, dummyList); 1682 } 1683 } 1684 } 1685 } 1686 1687 RELATION_LOGGER.exiting(RelationService.class.getName(), 1688 "findReferencingRelations"); 1689 return result; 1690 } 1691 1692 /** 1693 * Retrieves the MBeans associated to given one in a relation. 1694 * <P>This corresponds to CIM Associators and AssociatorNames operations. 1695 * 1696 * @param mbeanName ObjectName of MBean 1697 * @param relationTypeName can be null; if specified, only the relations 1698 * of that type will be considered in the search. Else all 1699 * relation types are considered. 1700 * @param roleName can be null; if specified, only the relations 1701 * where the MBean is referenced in that role will be considered. Else all 1702 * roles are considered. 1703 * 1704 * @return an HashMap, where the keys are the ObjectNames of the MBeans 1705 * associated to given MBean, and the value is, for each key, an ArrayList 1706 * of the relation ids of the relations where the key MBean is 1707 * associated to given one (as they can be associated in several different 1708 * relations). 1709 * 1710 * @exception IllegalArgumentException if null parameter 1711 */ 1712 public Map<ObjectName,List<String>> 1713 findAssociatedMBeans(ObjectName mbeanName, 1714 String relationTypeName, 1715 String roleName) 1716 throws IllegalArgumentException { 1717 1718 if (mbeanName == null) { 1719 String excMsg = "Invalid parameter."; 1720 throw new IllegalArgumentException(excMsg); 1721 } 1722 1723 RELATION_LOGGER.entering(RelationService.class.getName(), 1724 "findAssociatedMBeans", 1725 new Object[] {mbeanName, relationTypeName, roleName}); 1726 1727 // Retrieves the map <relation id> -> <role names> for those 1728 // criterias 1729 Map<String,List<String>> relId2RoleNamesMap = 1730 findReferencingRelations(mbeanName, 1731 relationTypeName, 1732 roleName); 1733 1734 Map<ObjectName,List<String>> result = 1735 new HashMap<ObjectName,List<String>>(); 1736 1737 for (String currRelId : relId2RoleNamesMap.keySet()) { 1738 1739 // Retrieves ObjectNames of MBeans referenced in this relation 1740 // 1741 // Shall not throw a RelationNotFoundException if incorrect status 1742 // of maps :( 1743 Map<ObjectName,List<String>> objName2RoleNamesMap; 1744 try { 1745 objName2RoleNamesMap = getReferencedMBeans(currRelId); 1746 } catch (RelationNotFoundException exc) { 1747 throw new RuntimeException(exc.getMessage()); 1748 } 1749 1750 // For each MBean associated to given one in a relation, adds the 1751 // association <ObjectName> -> <relation id> into result map 1752 for (ObjectName currObjName : objName2RoleNamesMap.keySet()) { 1753 1754 if (!(currObjName.equals(mbeanName))) { 1755 1756 // Sees if this MBean is already associated to the given 1757 // one in another relation 1758 List<String> currRelIdList = result.get(currObjName); 1759 if (currRelIdList == null) { 1760 1761 currRelIdList = new ArrayList<String>(); 1762 currRelIdList.add(currRelId); 1763 result.put(currObjName, currRelIdList); 1764 1765 } else { 1766 currRelIdList.add(currRelId); 1767 } 1768 } 1769 } 1770 } 1771 1772 RELATION_LOGGER.exiting(RelationService.class.getName(), 1773 "findAssociatedMBeans"); 1774 return result; 1775 } 1776 1777 /** 1778 * Returns the relation ids for relations of the given type. 1779 * 1780 * @param relationTypeName relation type name 1781 * 1782 * @return an ArrayList of relation ids. 1783 * 1784 * @exception IllegalArgumentException if null parameter 1785 * @exception RelationTypeNotFoundException if there is no relation type 1786 * with that name. 1787 */ 1788 public List<String> findRelationsOfType(String relationTypeName) 1789 throws IllegalArgumentException, 1790 RelationTypeNotFoundException { 1791 1792 if (relationTypeName == null) { 1793 String excMsg = "Invalid parameter."; 1794 throw new IllegalArgumentException(excMsg); 1795 } 1796 1797 RELATION_LOGGER.entering(RelationService.class.getName(), 1798 "findRelationsOfType"); 1799 1800 // Can throw RelationTypeNotFoundException 1801 RelationType relType = getRelationType(relationTypeName); 1802 1803 List<String> result; 1804 synchronized(myRelType2RelIdsMap) { 1805 List<String> result1 = myRelType2RelIdsMap.get(relationTypeName); 1806 if (result1 == null) 1807 result = new ArrayList<String>(); 1808 else 1809 result = new ArrayList<String>(result1); 1810 } 1811 1812 RELATION_LOGGER.exiting(RelationService.class.getName(), 1813 "findRelationsOfType"); 1814 return result; 1815 } 1816 1817 /** 1818 * Retrieves role value for given role name in given relation. 1819 * 1820 * @param relationId relation id 1821 * @param roleName name of role 1822 * 1823 * @return the ArrayList of ObjectName objects being the role value 1824 * 1825 * @exception RelationServiceNotRegisteredException if the Relation 1826 * Service is not registered 1827 * @exception IllegalArgumentException if null parameter 1828 * @exception RelationNotFoundException if no relation with given id 1829 * @exception RoleNotFoundException if: 1830 * <P>- there is no role with given name 1831 * <P>or 1832 * <P>- the role is not readable. 1833 * 1834 * @see #setRole 1835 */ 1836 public List<ObjectName> getRole(String relationId, 1837 String roleName) 1838 throws RelationServiceNotRegisteredException, 1839 IllegalArgumentException, 1840 RelationNotFoundException, 1841 RoleNotFoundException { 1842 1843 if (relationId == null || roleName == null) { 1844 String excMsg = "Invalid parameter."; 1845 throw new IllegalArgumentException(excMsg); 1846 } 1847 1848 RELATION_LOGGER.entering(RelationService.class.getName(), 1849 "getRole", new Object[] {relationId, roleName}); 1850 1851 // Can throw RelationServiceNotRegisteredException 1852 isActive(); 1853 1854 // Can throw a RelationNotFoundException 1855 Object relObj = getRelation(relationId); 1856 1857 List<ObjectName> result; 1858 1859 if (relObj instanceof RelationSupport) { 1860 // Internal relation 1861 // Can throw RoleNotFoundException 1862 result = cast( 1863 ((RelationSupport)relObj).getRoleInt(roleName, 1864 true, 1865 this, 1866 false)); 1867 1868 } else { 1869 // Relation MBean 1870 Object[] params = new Object[1]; 1871 params[0] = roleName; 1872 String[] signature = new String[1]; 1873 signature[0] = "java.lang.String"; 1874 // Can throw MBeanException wrapping a RoleNotFoundException: 1875 // throw wrapped exception 1876 // 1877 // Shall not throw InstanceNotFoundException or ReflectionException 1878 try { 1879 List<ObjectName> invokeResult = cast( 1880 myMBeanServer.invoke(((ObjectName)relObj), 1881 "getRole", 1882 params, 1883 signature)); 1884 if (invokeResult == null || invokeResult instanceof ArrayList<?>) 1885 result = invokeResult; 1886 else 1887 result = new ArrayList<ObjectName>(invokeResult); 1888 } catch (InstanceNotFoundException exc1) { 1889 throw new RuntimeException(exc1.getMessage()); 1890 } catch (ReflectionException exc2) { 1891 throw new RuntimeException(exc2.getMessage()); 1892 } catch (MBeanException exc3) { 1893 Exception wrappedExc = exc3.getTargetException(); 1894 if (wrappedExc instanceof RoleNotFoundException) { 1895 throw ((RoleNotFoundException)wrappedExc); 1896 } else { 1897 throw new RuntimeException(wrappedExc.getMessage()); 1898 } 1899 } 1900 } 1901 1902 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRole"); 1903 return result; 1904 } 1905 1906 /** 1907 * Retrieves values of roles with given names in given relation. 1908 * 1909 * @param relationId relation id 1910 * @param roleNameArray array of names of roles to be retrieved 1911 * 1912 * @return a RoleResult object, including a RoleList (for roles 1913 * successfully retrieved) and a RoleUnresolvedList (for roles not 1914 * retrieved). 1915 * 1916 * @exception RelationServiceNotRegisteredException if the Relation 1917 * Service is not registered in the MBean Server 1918 * @exception IllegalArgumentException if null parameter 1919 * @exception RelationNotFoundException if no relation with given id 1920 * 1921 * @see #setRoles 1922 */ 1923 public RoleResult getRoles(String relationId, 1924 String[] roleNameArray) 1925 throws RelationServiceNotRegisteredException, 1926 IllegalArgumentException, 1927 RelationNotFoundException { 1928 1929 if (relationId == null || roleNameArray == null) { 1930 String excMsg = "Invalid parameter."; 1931 throw new IllegalArgumentException(excMsg); 1932 } 1933 1934 RELATION_LOGGER.entering(RelationService.class.getName(), 1935 "getRoles", relationId); 1936 1937 // Can throw RelationServiceNotRegisteredException 1938 isActive(); 1939 1940 // Can throw a RelationNotFoundException 1941 Object relObj = getRelation(relationId); 1942 1943 RoleResult result; 1944 1945 if (relObj instanceof RelationSupport) { 1946 // Internal relation 1947 result = ((RelationSupport)relObj).getRolesInt(roleNameArray, 1948 true, 1949 this); 1950 } else { 1951 // Relation MBean 1952 Object[] params = new Object[1]; 1953 params[0] = roleNameArray; 1954 String[] signature = new String[1]; 1955 try { 1956 signature[0] = (roleNameArray.getClass()).getName(); 1957 } catch (Exception exc) { 1958 // OK : This is an array of java.lang.String 1959 // so this should never happen... 1960 } 1961 // Shall not throw InstanceNotFoundException, ReflectionException 1962 // or MBeanException 1963 try { 1964 result = (RoleResult) 1965 (myMBeanServer.invoke(((ObjectName)relObj), 1966 "getRoles", 1967 params, 1968 signature)); 1969 } catch (InstanceNotFoundException exc1) { 1970 throw new RuntimeException(exc1.getMessage()); 1971 } catch (ReflectionException exc2) { 1972 throw new RuntimeException(exc2.getMessage()); 1973 } catch (MBeanException exc3) { 1974 throw new 1975 RuntimeException((exc3.getTargetException()).getMessage()); 1976 } 1977 } 1978 1979 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles"); 1980 return result; 1981 } 1982 1983 /** 1984 * Returns all roles present in the relation. 1985 * 1986 * @param relationId relation id 1987 * 1988 * @return a RoleResult object, including a RoleList (for roles 1989 * successfully retrieved) and a RoleUnresolvedList (for roles not 1990 * readable). 1991 * 1992 * @exception IllegalArgumentException if null parameter 1993 * @exception RelationNotFoundException if no relation for given id 1994 * @exception RelationServiceNotRegisteredException if the Relation 1995 * Service is not registered in the MBean Server 1996 */ 1997 public RoleResult getAllRoles(String relationId) 1998 throws IllegalArgumentException, 1999 RelationNotFoundException, 2000 RelationServiceNotRegisteredException { 2001 2002 if (relationId == null) { 2003 String excMsg = "Invalid parameter."; 2004 throw new IllegalArgumentException(excMsg); 2005 } 2006 2007 RELATION_LOGGER.entering(RelationService.class.getName(), 2008 "getRoles", relationId); 2009 2010 // Can throw a RelationNotFoundException 2011 Object relObj = getRelation(relationId); 2012 2013 RoleResult result; 2014 2015 if (relObj instanceof RelationSupport) { 2016 // Internal relation 2017 result = ((RelationSupport)relObj).getAllRolesInt(true, this); 2018 2019 } else { 2020 // Relation MBean 2021 // Shall not throw any Exception 2022 try { 2023 result = (RoleResult) 2024 (myMBeanServer.getAttribute(((ObjectName)relObj), 2025 "AllRoles")); 2026 } catch (Exception exc) { 2027 throw new RuntimeException(exc.getMessage()); 2028 } 2029 } 2030 2031 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles"); 2032 return result; 2033 } 2034 2035 /** 2036 * Retrieves the number of MBeans currently referenced in the given role. 2037 * 2038 * @param relationId relation id 2039 * @param roleName name of role 2040 * 2041 * @return the number of currently referenced MBeans in that role 2042 * 2043 * @exception IllegalArgumentException if null parameter 2044 * @exception RelationNotFoundException if no relation with given id 2045 * @exception RoleNotFoundException if there is no role with given name 2046 */ 2047 public Integer getRoleCardinality(String relationId, 2048 String roleName) 2049 throws IllegalArgumentException, 2050 RelationNotFoundException, 2051 RoleNotFoundException { 2052 2053 if (relationId == null || roleName == null) { 2054 String excMsg = "Invalid parameter."; 2055 throw new IllegalArgumentException(excMsg); 2056 } 2057 2058 RELATION_LOGGER.entering(RelationService.class.getName(), 2059 "getRoleCardinality", new Object[] {relationId, roleName}); 2060 2061 // Can throw a RelationNotFoundException 2062 Object relObj = getRelation(relationId); 2063 2064 Integer result; 2065 2066 if (relObj instanceof RelationSupport) { 2067 // Internal relation 2068 // Can throw RoleNotFoundException 2069 result = ((RelationSupport)relObj).getRoleCardinality(roleName); 2070 2071 } else { 2072 // Relation MBean 2073 Object[] params = new Object[1]; 2074 params[0] = roleName; 2075 String[] signature = new String[1]; 2076 signature[0] = "java.lang.String"; 2077 // Can throw MBeanException wrapping RoleNotFoundException: 2078 // throw wrapped exception 2079 // 2080 // Shall not throw InstanceNotFoundException or ReflectionException 2081 try { 2082 result = (Integer) 2083 (myMBeanServer.invoke(((ObjectName)relObj), 2084 "getRoleCardinality", 2085 params, 2086 signature)); 2087 } catch (InstanceNotFoundException exc1) { 2088 throw new RuntimeException(exc1.getMessage()); 2089 } catch (ReflectionException exc2) { 2090 throw new RuntimeException(exc2.getMessage()); 2091 } catch (MBeanException exc3) { 2092 Exception wrappedExc = exc3.getTargetException(); 2093 if (wrappedExc instanceof RoleNotFoundException) { 2094 throw ((RoleNotFoundException)wrappedExc); 2095 } else { 2096 throw new RuntimeException(wrappedExc.getMessage()); 2097 } 2098 } 2099 } 2100 2101 RELATION_LOGGER.exiting(RelationService.class.getName(), 2102 "getRoleCardinality"); 2103 return result; 2104 } 2105 2106 /** 2107 * Sets the given role in given relation. 2108 * <P>Will check the role according to its corresponding role definition 2109 * provided in relation's relation type 2110 * <P>The Relation Service will keep track of the change to keep the 2111 * consistency of relations by handling referenced MBean unregistrations. 2112 * 2113 * @param relationId relation id 2114 * @param role role to be set (name and new value) 2115 * 2116 * @exception RelationServiceNotRegisteredException if the Relation 2117 * Service is not registered in the MBean Server 2118 * @exception IllegalArgumentException if null parameter 2119 * @exception RelationNotFoundException if no relation with given id 2120 * @exception RoleNotFoundException if the role does not exist or is not 2121 * writable 2122 * @exception InvalidRoleValueException if value provided for role is not 2123 * valid: 2124 * <P>- the number of referenced MBeans in given value is less than 2125 * expected minimum degree 2126 * <P>or 2127 * <P>- the number of referenced MBeans in provided value exceeds expected 2128 * maximum degree 2129 * <P>or 2130 * <P>- one referenced MBean in the value is not an Object of the MBean 2131 * class expected for that role 2132 * <P>or 2133 * <P>- an MBean provided for that role does not exist 2134 * 2135 * @see #getRole 2136 */ 2137 public void setRole(String relationId, 2138 Role role) 2139 throws RelationServiceNotRegisteredException, 2140 IllegalArgumentException, 2141 RelationNotFoundException, 2142 RoleNotFoundException, 2143 InvalidRoleValueException { 2144 2145 if (relationId == null || role == null) { 2146 String excMsg = "Invalid parameter."; 2147 throw new IllegalArgumentException(excMsg); 2148 } 2149 2150 RELATION_LOGGER.entering(RelationService.class.getName(), 2151 "setRole", new Object[] {relationId, role}); 2152 2153 // Can throw RelationServiceNotRegisteredException 2154 isActive(); 2155 2156 // Can throw a RelationNotFoundException 2157 Object relObj = getRelation(relationId); 2158 2159 if (relObj instanceof RelationSupport) { 2160 // Internal relation 2161 // Can throw RoleNotFoundException, 2162 // InvalidRoleValueException and 2163 // RelationServiceNotRegisteredException 2164 // 2165 // Shall not throw RelationTypeNotFoundException 2166 // (as relation exists in the RS, its relation type is known) 2167 try { 2168 ((RelationSupport)relObj).setRoleInt(role, 2169 true, 2170 this, 2171 false); 2172 2173 } catch (RelationTypeNotFoundException exc) { 2174 throw new RuntimeException(exc.getMessage()); 2175 } 2176 2177 } else { 2178 // Relation MBean 2179 Object[] params = new Object[1]; 2180 params[0] = role; 2181 String[] signature = new String[1]; 2182 signature[0] = "javax.management.relation.Role"; 2183 // Can throw MBeanException wrapping RoleNotFoundException, 2184 // InvalidRoleValueException 2185 // 2186 // Shall not MBeanException wrapping an MBeanException wrapping 2187 // RelationTypeNotFoundException, or ReflectionException, or 2188 // InstanceNotFoundException 2189 try { 2190 myMBeanServer.setAttribute(((ObjectName)relObj), 2191 new Attribute("Role", role)); 2192 2193 } catch (InstanceNotFoundException exc1) { 2194 throw new RuntimeException(exc1.getMessage()); 2195 } catch (ReflectionException exc3) { 2196 throw new RuntimeException(exc3.getMessage()); 2197 } catch (MBeanException exc2) { 2198 Exception wrappedExc = exc2.getTargetException(); 2199 if (wrappedExc instanceof RoleNotFoundException) { 2200 throw ((RoleNotFoundException)wrappedExc); 2201 } else if (wrappedExc instanceof InvalidRoleValueException) { 2202 throw ((InvalidRoleValueException)wrappedExc); 2203 } else { 2204 throw new RuntimeException(wrappedExc.getMessage()); 2205 2206 } 2207 } catch (AttributeNotFoundException exc4) { 2208 throw new RuntimeException(exc4.getMessage()); 2209 } catch (InvalidAttributeValueException exc5) { 2210 throw new RuntimeException(exc5.getMessage()); 2211 } 2212 } 2213 2214 RELATION_LOGGER.exiting(RelationService.class.getName(), "setRole"); 2215 return; 2216 } 2217 2218 /** 2219 * Sets the given roles in given relation. 2220 * <P>Will check the role according to its corresponding role definition 2221 * provided in relation's relation type 2222 * <P>The Relation Service keeps track of the changes to keep the 2223 * consistency of relations by handling referenced MBean unregistrations. 2224 * 2225 * @param relationId relation id 2226 * @param roleList list of roles to be set 2227 * 2228 * @return a RoleResult object, including a RoleList (for roles 2229 * successfully set) and a RoleUnresolvedList (for roles not 2230 * set). 2231 * 2232 * @exception RelationServiceNotRegisteredException if the Relation 2233 * Service is not registered in the MBean Server 2234 * @exception IllegalArgumentException if null parameter 2235 * @exception RelationNotFoundException if no relation with given id 2236 * 2237 * @see #getRoles 2238 */ 2239 public RoleResult setRoles(String relationId, 2240 RoleList roleList) 2241 throws RelationServiceNotRegisteredException, 2242 IllegalArgumentException, 2243 RelationNotFoundException { 2244 2245 if (relationId == null || roleList == null) { 2246 String excMsg = "Invalid parameter."; 2247 throw new IllegalArgumentException(excMsg); 2248 } 2249 2250 RELATION_LOGGER.entering(RelationService.class.getName(), 2251 "setRoles", new Object[] {relationId, roleList}); 2252 2253 // Can throw RelationServiceNotRegisteredException 2254 isActive(); 2255 2256 // Can throw a RelationNotFoundException 2257 Object relObj = getRelation(relationId); 2258 2259 RoleResult result; 2260 2261 if (relObj instanceof RelationSupport) { 2262 // Internal relation 2263 // Can throw RelationServiceNotRegisteredException 2264 // 2265 // Shall not throw RelationTypeNotFoundException (as relation is 2266 // known, its relation type exists) 2267 try { 2268 result = ((RelationSupport)relObj).setRolesInt(roleList, 2269 true, 2270 this); 2271 } catch (RelationTypeNotFoundException exc) { 2272 throw new RuntimeException(exc.getMessage()); 2273 } 2274 2275 } else { 2276 // Relation MBean 2277 Object[] params = new Object[1]; 2278 params[0] = roleList; 2279 String[] signature = new String[1]; 2280 signature[0] = "javax.management.relation.RoleList"; 2281 // Shall not throw InstanceNotFoundException or an MBeanException 2282 // or ReflectionException 2283 try { 2284 result = (RoleResult) 2285 (myMBeanServer.invoke(((ObjectName)relObj), 2286 "setRoles", 2287 params, 2288 signature)); 2289 } catch (InstanceNotFoundException exc1) { 2290 throw new RuntimeException(exc1.getMessage()); 2291 } catch (ReflectionException exc3) { 2292 throw new RuntimeException(exc3.getMessage()); 2293 } catch (MBeanException exc2) { 2294 throw new 2295 RuntimeException((exc2.getTargetException()).getMessage()); 2296 } 2297 } 2298 2299 RELATION_LOGGER.exiting(RelationService.class.getName(), "setRoles"); 2300 return result; 2301 } 2302 2303 /** 2304 * Retrieves MBeans referenced in the various roles of the relation. 2305 * 2306 * @param relationId relation id 2307 * 2308 * @return a HashMap mapping: 2309 * <P> ObjectName -> ArrayList of String (role 2310 * names) 2311 * 2312 * @exception IllegalArgumentException if null parameter 2313 * @exception RelationNotFoundException if no relation for given 2314 * relation id 2315 */ 2316 public Map<ObjectName,List<String>> 2317 getReferencedMBeans(String relationId) 2318 throws IllegalArgumentException, 2319 RelationNotFoundException { 2320 2321 if (relationId == null) { 2322 String excMsg = "Invalid parameter."; 2323 throw new IllegalArgumentException(excMsg); 2324 } 2325 2326 RELATION_LOGGER.entering(RelationService.class.getName(), 2327 "getReferencedMBeans", relationId); 2328 2329 // Can throw a RelationNotFoundException 2330 Object relObj = getRelation(relationId); 2331 2332 Map<ObjectName,List<String>> result; 2333 2334 if (relObj instanceof RelationSupport) { 2335 // Internal relation 2336 result = ((RelationSupport)relObj).getReferencedMBeans(); 2337 2338 } else { 2339 // Relation MBean 2340 // No Exception 2341 try { 2342 result = cast( 2343 myMBeanServer.getAttribute(((ObjectName)relObj), 2344 "ReferencedMBeans")); 2345 } catch (Exception exc) { 2346 throw new RuntimeException(exc.getMessage()); 2347 } 2348 } 2349 2350 RELATION_LOGGER.exiting(RelationService.class.getName(), 2351 "getReferencedMBeans"); 2352 return result; 2353 } 2354 2355 /** 2356 * Returns name of associated relation type for given relation. 2357 * 2358 * @param relationId relation id 2359 * 2360 * @return the name of the associated relation type. 2361 * 2362 * @exception IllegalArgumentException if null parameter 2363 * @exception RelationNotFoundException if no relation for given 2364 * relation id 2365 */ 2366 public String getRelationTypeName(String relationId) 2367 throws IllegalArgumentException, 2368 RelationNotFoundException { 2369 2370 if (relationId == null) { 2371 String excMsg = "Invalid parameter."; 2372 throw new IllegalArgumentException(excMsg); 2373 } 2374 2375 RELATION_LOGGER.entering(RelationService.class.getName(), 2376 "getRelationTypeName", relationId); 2377 2378 // Can throw a RelationNotFoundException 2379 Object relObj = getRelation(relationId); 2380 2381 String result; 2382 2383 if (relObj instanceof RelationSupport) { 2384 // Internal relation 2385 result = ((RelationSupport)relObj).getRelationTypeName(); 2386 2387 } else { 2388 // Relation MBean 2389 // No Exception 2390 try { 2391 result = (String) 2392 (myMBeanServer.getAttribute(((ObjectName)relObj), 2393 "RelationTypeName")); 2394 } catch (Exception exc) { 2395 throw new RuntimeException(exc.getMessage()); 2396 } 2397 } 2398 2399 RELATION_LOGGER.exiting(RelationService.class.getName(), 2400 "getRelationTypeName"); 2401 return result; 2402 } 2403 2404 // 2405 // NotificationListener Interface 2406 // 2407 2408 /** 2409 * Invoked when a JMX notification occurs. 2410 * Currently handles notifications for unregistration of MBeans, either 2411 * referenced in a relation role or being a relation itself. 2412 * 2413 * @param notif The notification. 2414 * @param handback An opaque object which helps the listener to 2415 * associate information regarding the MBean emitter (can be null). 2416 */ 2417 public void handleNotification(Notification notif, 2418 Object handback) { 2419 2420 if (notif == null) { 2421 String excMsg = "Invalid parameter."; 2422 throw new IllegalArgumentException(excMsg); 2423 } 2424 2425 RELATION_LOGGER.entering(RelationService.class.getName(), 2426 "handleNotification", notif); 2427 2428 if (notif instanceof MBeanServerNotification) { 2429 2430 MBeanServerNotification mbsNtf = (MBeanServerNotification) notif; 2431 String ntfType = notif.getType(); 2432 2433 if (ntfType.equals( 2434 MBeanServerNotification.UNREGISTRATION_NOTIFICATION )) { 2435 ObjectName mbeanName = 2436 ((MBeanServerNotification)notif).getMBeanName(); 2437 2438 // Note: use a flag to block access to 2439 // myRefedMBeanObjName2RelIdsMap only for a quick access 2440 boolean isRefedMBeanFlag = false; 2441 synchronized(myRefedMBeanObjName2RelIdsMap) { 2442 2443 if (myRefedMBeanObjName2RelIdsMap.containsKey(mbeanName)) { 2444 // Unregistration of a referenced MBean 2445 synchronized(myUnregNtfList) { 2446 myUnregNtfList.add(mbsNtf); 2447 } 2448 isRefedMBeanFlag = true; 2449 } 2450 if (isRefedMBeanFlag && myPurgeFlag) { 2451 // Immediate purge 2452 // Can throw RelationServiceNotRegisteredException 2453 // but assume that will be fine :) 2454 try { 2455 purgeRelations(); 2456 } catch (Exception exc) { 2457 throw new RuntimeException(exc.getMessage()); 2458 } 2459 } 2460 } 2461 2462 // Note: do both tests as a relation can be an MBean and be 2463 // itself referenced in another relation :) 2464 String relId; 2465 synchronized(myRelMBeanObjName2RelIdMap){ 2466 relId = myRelMBeanObjName2RelIdMap.get(mbeanName); 2467 } 2468 if (relId != null) { 2469 // Unregistration of a relation MBean 2470 // Can throw RelationTypeNotFoundException, 2471 // RelationServiceNotRegisteredException 2472 // 2473 // Shall not throw RelationTypeNotFoundException or 2474 // InstanceNotFoundException 2475 try { 2476 removeRelation(relId); 2477 } catch (Exception exc) { 2478 throw new RuntimeException(exc.getMessage()); 2479 } 2480 } 2481 } 2482 } 2483 2484 RELATION_LOGGER.exiting(RelationService.class.getName(), 2485 "handleNotification"); 2486 return; 2487 } 2488 2489 // 2490 // NotificationBroadcaster interface 2491 // 2492 2493 /** 2494 * Returns a NotificationInfo object containing the name of the Java class 2495 * of the notification and the notification types sent. 2496 */ 2497 public MBeanNotificationInfo[] getNotificationInfo() { 2498 2499 RELATION_LOGGER.entering(RelationService.class.getName(), 2500 "getNotificationInfo"); 2501 2502 String ntfClass = "javax.management.relation.RelationNotification"; 2503 2504 String[] ntfTypes = new String[] { 2505 RelationNotification.RELATION_BASIC_CREATION, 2506 RelationNotification.RELATION_MBEAN_CREATION, 2507 RelationNotification.RELATION_BASIC_UPDATE, 2508 RelationNotification.RELATION_MBEAN_UPDATE, 2509 RelationNotification.RELATION_BASIC_REMOVAL, 2510 RelationNotification.RELATION_MBEAN_REMOVAL, 2511 }; 2512 2513 String ntfDesc = "Sent when a relation is created, updated or deleted."; 2514 2515 MBeanNotificationInfo ntfInfo = 2516 new MBeanNotificationInfo(ntfTypes, ntfClass, ntfDesc); 2517 2518 RELATION_LOGGER.exiting(RelationService.class.getName(), 2519 "getNotificationInfo"); 2520 return new MBeanNotificationInfo[] {ntfInfo}; 2521 } 2522 2523 // 2524 // Misc 2525 // 2526 2527 // Adds given object as a relation type. 2528 // 2529 // -param relationTypeObj relation type object 2530 // 2531 // -exception IllegalArgumentException if null parameter 2532 // -exception InvalidRelationTypeException if there is already a relation 2533 // type with that name 2534 private void addRelationTypeInt(RelationType relationTypeObj) 2535 throws IllegalArgumentException, 2536 InvalidRelationTypeException { 2537 2538 if (relationTypeObj == null) { 2539 String excMsg = "Invalid parameter."; 2540 throw new IllegalArgumentException(excMsg); 2541 } 2542 2543 RELATION_LOGGER.entering(RelationService.class.getName(), 2544 "addRelationTypeInt"); 2545 2546 String relTypeName = relationTypeObj.getRelationTypeName(); 2547 2548 // Checks that there is not already a relation type with that name 2549 // existing in the Relation Service 2550 try { 2551 // Can throw a RelationTypeNotFoundException (in fact should ;) 2552 RelationType relType = getRelationType(relTypeName); 2553 2554 if (relType != null) { 2555 String excMsg = "There is already a relation type in the Relation Service with name "; 2556 StringBuilder excMsgStrB = new StringBuilder(excMsg); 2557 excMsgStrB.append(relTypeName); 2558 throw new InvalidRelationTypeException(excMsgStrB.toString()); 2559 } 2560 2561 } catch (RelationTypeNotFoundException exc) { 2562 // OK : The RelationType could not be found. 2563 } 2564 2565 // Adds the relation type 2566 synchronized(myRelType2ObjMap) { 2567 myRelType2ObjMap.put(relTypeName, relationTypeObj); 2568 } 2569 2570 if (relationTypeObj instanceof RelationTypeSupport) { 2571 ((RelationTypeSupport)relationTypeObj).setRelationServiceFlag(true); 2572 } 2573 2574 RELATION_LOGGER.exiting(RelationService.class.getName(), 2575 "addRelationTypeInt"); 2576 return; 2577 } 2578 2579 // Retrieves relation type with given name 2580 // 2581 // -param relationTypeName expected name of a relation type created in the 2582 // Relation Service 2583 // 2584 // -return RelationType object corresponding to given name 2585 // 2586 // -exception IllegalArgumentException if null parameter 2587 // -exception RelationTypeNotFoundException if no relation type for that 2588 // name created in Relation Service 2589 // 2590 RelationType getRelationType(String relationTypeName) 2591 throws IllegalArgumentException, 2592 RelationTypeNotFoundException { 2593 2594 if (relationTypeName == null) { 2595 String excMsg = "Invalid parameter."; 2596 throw new IllegalArgumentException(excMsg); 2597 } 2598 2599 RELATION_LOGGER.entering(RelationService.class.getName(), 2600 "getRelationType", relationTypeName); 2601 2602 // No null relation type accepted, so can use get() 2603 RelationType relType; 2604 synchronized(myRelType2ObjMap) { 2605 relType = (myRelType2ObjMap.get(relationTypeName)); 2606 } 2607 2608 if (relType == null) { 2609 String excMsg = "No relation type created in the Relation Service with the name "; 2610 StringBuilder excMsgStrB = new StringBuilder(excMsg); 2611 excMsgStrB.append(relationTypeName); 2612 throw new RelationTypeNotFoundException(excMsgStrB.toString()); 2613 } 2614 2615 RELATION_LOGGER.exiting(RelationService.class.getName(), 2616 "getRelationType"); 2617 return relType; 2618 } 2619 2620 // Retrieves relation corresponding to given relation id. 2621 // Returns either: 2622 // - a RelationSupport object if the relation is internal 2623 // or 2624 // - the ObjectName of the corresponding MBean 2625 // 2626 // -param relationId expected relation id 2627 // 2628 // -return RelationSupport object or ObjectName of relation with given id 2629 // 2630 // -exception IllegalArgumentException if null parameter 2631 // -exception RelationNotFoundException if no relation for that 2632 // relation id created in Relation Service 2633 // 2634 Object getRelation(String relationId) 2635 throws IllegalArgumentException, 2636 RelationNotFoundException { 2637 2638 if (relationId == null) { 2639 String excMsg = "Invalid parameter."; 2640 throw new IllegalArgumentException(excMsg); 2641 } 2642 2643 RELATION_LOGGER.entering(RelationService.class.getName(), 2644 "getRelation", relationId); 2645 2646 // No null relation accepted, so can use get() 2647 Object rel; 2648 synchronized(myRelId2ObjMap) { 2649 rel = myRelId2ObjMap.get(relationId); 2650 } 2651 2652 if (rel == null) { 2653 String excMsg = "No relation associated to relation id " + relationId; 2654 throw new RelationNotFoundException(excMsg); 2655 } 2656 2657 RELATION_LOGGER.exiting(RelationService.class.getName(), 2658 "getRelation"); 2659 return rel; 2660 } 2661 2662 // Adds a new MBean reference (reference to an ObjectName) in the 2663 // referenced MBean map (myRefedMBeanObjName2RelIdsMap). 2664 // 2665 // -param objectName ObjectName of new referenced MBean 2666 // -param relationId relation id of the relation where the MBean is 2667 // referenced 2668 // -param roleName name of the role where the MBean is referenced 2669 // 2670 // -return boolean: 2671 // - true if the MBean was not referenced before, so really a new 2672 // reference 2673 // - false else 2674 // 2675 // -exception IllegalArgumentException if null parameter 2676 private boolean addNewMBeanReference(ObjectName objectName, 2677 String relationId, 2678 String roleName) 2679 throws IllegalArgumentException { 2680 2681 if (objectName == null || 2682 relationId == null || 2683 roleName == null) { 2684 String excMsg = "Invalid parameter."; 2685 throw new IllegalArgumentException(excMsg); 2686 } 2687 2688 RELATION_LOGGER.entering(RelationService.class.getName(), 2689 "addNewMBeanReference", 2690 new Object[] {objectName, relationId, roleName}); 2691 2692 boolean isNewFlag = false; 2693 2694 synchronized(myRefedMBeanObjName2RelIdsMap) { 2695 2696 // Checks if the MBean was already referenced 2697 // No null value allowed, use get() directly 2698 Map<String,List<String>> mbeanRefMap = 2699 myRefedMBeanObjName2RelIdsMap.get(objectName); 2700 2701 if (mbeanRefMap == null) { 2702 // MBean not referenced in any relation yet 2703 2704 isNewFlag = true; 2705 2706 // List of roles where the MBean is referenced in given 2707 // relation 2708 List<String> roleNames = new ArrayList<String>(); 2709 roleNames.add(roleName); 2710 2711 // Map of relations where the MBean is referenced 2712 mbeanRefMap = new HashMap<String,List<String>>(); 2713 mbeanRefMap.put(relationId, roleNames); 2714 2715 myRefedMBeanObjName2RelIdsMap.put(objectName, mbeanRefMap); 2716 2717 } else { 2718 // MBean already referenced in at least another relation 2719 // Checks if already referenced in another role in current 2720 // relation 2721 List<String> roleNames = mbeanRefMap.get(relationId); 2722 2723 if (roleNames == null) { 2724 // MBean not referenced in current relation 2725 2726 // List of roles where the MBean is referenced in given 2727 // relation 2728 roleNames = new ArrayList<String>(); 2729 roleNames.add(roleName); 2730 2731 // Adds new reference done in current relation 2732 mbeanRefMap.put(relationId, roleNames); 2733 2734 } else { 2735 // MBean already referenced in current relation in another 2736 // role 2737 // Adds new reference done 2738 roleNames.add(roleName); 2739 } 2740 } 2741 } 2742 2743 RELATION_LOGGER.exiting(RelationService.class.getName(), 2744 "addNewMBeanReference"); 2745 return isNewFlag; 2746 } 2747 2748 // Removes an obsolete MBean reference (reference to an ObjectName) in 2749 // the referenced MBean map (myRefedMBeanObjName2RelIdsMap). 2750 // 2751 // -param objectName ObjectName of MBean no longer referenced 2752 // -param relationId relation id of the relation where the MBean was 2753 // referenced 2754 // -param roleName name of the role where the MBean was referenced 2755 // -param allRolesFlag flag, if true removes reference to MBean for all 2756 // roles in the relation, not only for the one above 2757 // 2758 // -return boolean: 2759 // - true if the MBean is no longer reference in any relation 2760 // - false else 2761 // 2762 // -exception IllegalArgumentException if null parameter 2763 private boolean removeMBeanReference(ObjectName objectName, 2764 String relationId, 2765 String roleName, 2766 boolean allRolesFlag) 2767 throws IllegalArgumentException { 2768 2769 if (objectName == null || 2770 relationId == null || 2771 roleName == null) { 2772 String excMsg = "Invalid parameter."; 2773 throw new IllegalArgumentException(excMsg); 2774 } 2775 2776 RELATION_LOGGER.entering(RelationService.class.getName(), 2777 "removeMBeanReference", 2778 new Object[] {objectName, relationId, roleName, allRolesFlag}); 2779 2780 boolean noLongerRefFlag = false; 2781 2782 synchronized(myRefedMBeanObjName2RelIdsMap) { 2783 2784 // Retrieves the set of relations (designed via their relation ids) 2785 // where the MBean is referenced 2786 // Note that it is possible that the MBean has already been removed 2787 // from the internal map: this is the case when the MBean is 2788 // unregistered, the role is updated, then we arrive here. 2789 Map<String,List<String>> mbeanRefMap = 2790 (myRefedMBeanObjName2RelIdsMap.get(objectName)); 2791 2792 if (mbeanRefMap == null) { 2793 // The MBean is no longer referenced 2794 RELATION_LOGGER.exiting(RelationService.class.getName(), 2795 "removeMBeanReference"); 2796 return true; 2797 } 2798 2799 List<String> roleNames = null; 2800 if (!allRolesFlag) { 2801 // Now retrieves the roles of current relation where the MBean 2802 // was referenced 2803 roleNames = mbeanRefMap.get(relationId); 2804 2805 // Removes obsolete reference to role 2806 int obsRefIdx = roleNames.indexOf(roleName); 2807 if (obsRefIdx != -1) { 2808 roleNames.remove(obsRefIdx); 2809 } 2810 } 2811 2812 // Checks if there is still at least one role in current relation 2813 // where the MBean is referenced 2814 if (roleNames.isEmpty() || allRolesFlag) { 2815 // MBean no longer referenced in current relation: removes 2816 // entry 2817 mbeanRefMap.remove(relationId); 2818 } 2819 2820 // Checks if the MBean is still referenced in at least on relation 2821 if (mbeanRefMap.isEmpty()) { 2822 // MBean no longer referenced in any relation: removes entry 2823 myRefedMBeanObjName2RelIdsMap.remove(objectName); 2824 noLongerRefFlag = true; 2825 } 2826 } 2827 2828 RELATION_LOGGER.exiting(RelationService.class.getName(), 2829 "removeMBeanReference"); 2830 return noLongerRefFlag; 2831 } 2832 2833 // Updates the listener registered to the MBean Server to be informed of 2834 // referenced MBean unregistrations 2835 // 2836 // -param newRefList ArrayList of ObjectNames for new references done 2837 // to MBeans (can be null) 2838 // -param obsoleteRefList ArrayList of ObjectNames for obsolete references 2839 // to MBeans (can be null) 2840 // 2841 // -exception RelationServiceNotRegisteredException if the Relation 2842 // Service is not registered in the MBean Server. 2843 private void updateUnregistrationListener(List<ObjectName> newRefList, 2844 List<ObjectName> obsoleteRefList) 2845 throws RelationServiceNotRegisteredException { 2846 2847 if (newRefList != null && obsoleteRefList != null) { 2848 if (newRefList.isEmpty() && obsoleteRefList.isEmpty()) { 2849 // Nothing to do :) 2850 return; 2851 } 2852 } 2853 2854 RELATION_LOGGER.entering(RelationService.class.getName(), 2855 "updateUnregistrationListener", 2856 new Object[] {newRefList, obsoleteRefList}); 2857 2858 // Can throw RelationServiceNotRegisteredException 2859 isActive(); 2860 2861 if (newRefList != null || obsoleteRefList != null) { 2862 2863 boolean newListenerFlag = false; 2864 if (myUnregNtfFilter == null) { 2865 // Initialize it to be able to synchronise it :) 2866 myUnregNtfFilter = new MBeanServerNotificationFilter(); 2867 newListenerFlag = true; 2868 } 2869 2870 synchronized(myUnregNtfFilter) { 2871 2872 // Enables ObjectNames in newRefList 2873 if (newRefList != null) { 2874 for (ObjectName newObjName : newRefList) 2875 myUnregNtfFilter.enableObjectName(newObjName); 2876 } 2877 2878 if (obsoleteRefList != null) { 2879 // Disables ObjectNames in obsoleteRefList 2880 for (ObjectName obsObjName : obsoleteRefList) 2881 myUnregNtfFilter.disableObjectName(obsObjName); 2882 } 2883 2884 // Under test 2885 if (newListenerFlag) { 2886 try { 2887 myMBeanServer.addNotificationListener( 2888 MBeanServerDelegate.DELEGATE_NAME, 2889 this, 2890 myUnregNtfFilter, 2891 null); 2892 } catch (InstanceNotFoundException exc) { 2893 throw new 2894 RelationServiceNotRegisteredException(exc.getMessage()); 2895 } 2896 } 2897 // End test 2898 2899 2900 // if (!newListenerFlag) { 2901 // The Relation Service was already registered as a 2902 // listener: 2903 // removes it 2904 // Shall not throw InstanceNotFoundException (as the 2905 // MBean Server Delegate is expected to exist) or 2906 // ListenerNotFoundException (as it has been checked above 2907 // that the Relation Service is registered) 2908 // try { 2909 // myMBeanServer.removeNotificationListener( 2910 // MBeanServerDelegate.DELEGATE_NAME, 2911 // this); 2912 // } catch (InstanceNotFoundException exc1) { 2913 // throw new RuntimeException(exc1.getMessage()); 2914 // } catch (ListenerNotFoundException exc2) { 2915 // throw new 2916 // RelationServiceNotRegisteredException(exc2.getMessage()); 2917 // } 2918 // } 2919 2920 // Adds Relation Service with current filter 2921 // Can throw InstanceNotFoundException if the Relation 2922 // Service is not registered, to be transformed into 2923 // RelationServiceNotRegisteredException 2924 // 2925 // Assume that there will not be any InstanceNotFoundException 2926 // for the MBean Server Delegate :) 2927 // try { 2928 // myMBeanServer.addNotificationListener( 2929 // MBeanServerDelegate.DELEGATE_NAME, 2930 // this, 2931 // myUnregNtfFilter, 2932 // null); 2933 // } catch (InstanceNotFoundException exc) { 2934 // throw new 2935 // RelationServiceNotRegisteredException(exc.getMessage()); 2936 // } 2937 } 2938 } 2939 2940 RELATION_LOGGER.exiting(RelationService.class.getName(), 2941 "updateUnregistrationListener"); 2942 return; 2943 } 2944 2945 // Adds a relation (being either a RelationSupport object or an MBean 2946 // referenced using its ObjectName) in the Relation Service. 2947 // Will send a notification RelationNotification with type: 2948 // - RelationNotification.RELATION_BASIC_CREATION for internal relation 2949 // creation 2950 // - RelationNotification.RELATION_MBEAN_CREATION for an MBean being added 2951 // as a relation. 2952 // 2953 // -param relationBaseFlag flag true if the relation is a RelationSupport 2954 // object, false if it is an MBean 2955 // -param relationObj RelationSupport object (if relation is internal) 2956 // -param relationObjName ObjectName of the MBean to be added as a relation 2957 // (only for the relation MBean) 2958 // -param relationId relation identifier, to uniquely identify the relation 2959 // inside the Relation Service 2960 // -param relationTypeName name of the relation type (has to be created 2961 // in the Relation Service) 2962 // -param roleList role list to initialize roles of the relation 2963 // (can be null) 2964 // 2965 // -exception IllegalArgumentException if null paramater 2966 // -exception RelationServiceNotRegisteredException if the Relation 2967 // Service is not registered in the MBean Server 2968 // -exception RoleNotFoundException if a value is provided for a role 2969 // that does not exist in the relation type 2970 // -exception InvalidRelationIdException if relation id already used 2971 // -exception RelationTypeNotFoundException if relation type not known in 2972 // Relation Service 2973 // -exception InvalidRoleValueException if: 2974 // - the same role name is used for two different roles 2975 // - the number of referenced MBeans in given value is less than 2976 // expected minimum degree 2977 // - the number of referenced MBeans in provided value exceeds expected 2978 // maximum degree 2979 // - one referenced MBean in the value is not an Object of the MBean 2980 // class expected for that role 2981 // - an MBean provided for that role does not exist 2982 private void addRelationInt(boolean relationBaseFlag, 2983 RelationSupport relationObj, 2984 ObjectName relationObjName, 2985 String relationId, 2986 String relationTypeName, 2987 RoleList roleList) 2988 throws IllegalArgumentException, 2989 RelationServiceNotRegisteredException, 2990 RoleNotFoundException, 2991 InvalidRelationIdException, 2992 RelationTypeNotFoundException, 2993 InvalidRoleValueException { 2994 2995 if (relationId == null || 2996 relationTypeName == null || 2997 (relationBaseFlag && 2998 (relationObj == null || 2999 relationObjName != null)) || 3000 (!relationBaseFlag && 3001 (relationObjName == null || 3002 relationObj != null))) { 3003 String excMsg = "Invalid parameter."; 3004 throw new IllegalArgumentException(excMsg); 3005 } 3006 3007 RELATION_LOGGER.entering(RelationService.class.getName(), 3008 "addRelationInt", new Object[] {relationBaseFlag, relationObj, 3009 relationObjName, relationId, relationTypeName, roleList}); 3010 3011 // Can throw RelationServiceNotRegisteredException 3012 isActive(); 3013 3014 // Checks if there is already a relation with given id 3015 try { 3016 // Can throw a RelationNotFoundException (in fact should :) 3017 Object rel = getRelation(relationId); 3018 3019 if (rel != null) { 3020 // There is already a relation with that id 3021 String excMsg = "There is already a relation with id "; 3022 StringBuilder excMsgStrB = new StringBuilder(excMsg); 3023 excMsgStrB.append(relationId); 3024 throw new InvalidRelationIdException(excMsgStrB.toString()); 3025 } 3026 } catch (RelationNotFoundException exc) { 3027 // OK : The Relation could not be found. 3028 } 3029 3030 // Retrieves the relation type 3031 // Can throw RelationTypeNotFoundException 3032 RelationType relType = getRelationType(relationTypeName); 3033 3034 // Checks that each provided role conforms to its role info provided in 3035 // the relation type 3036 // First retrieves a local list of the role infos of the relation type 3037 // to see which roles have not been initialized 3038 // Note: no need to test if list not null before cloning, not allowed 3039 // to have an empty relation type. 3040 List<RoleInfo> roleInfoList = new ArrayList<RoleInfo>(relType.getRoleInfos()); 3041 3042 if (roleList != null) { 3043 3044 for (Role currRole : roleList.asList()) { 3045 String currRoleName = currRole.getRoleName(); 3046 List<ObjectName> currRoleValue = currRole.getRoleValue(); 3047 // Retrieves corresponding role info 3048 // Can throw a RoleInfoNotFoundException to be converted into a 3049 // RoleNotFoundException 3050 RoleInfo roleInfo; 3051 try { 3052 roleInfo = relType.getRoleInfo(currRoleName); 3053 } catch (RoleInfoNotFoundException exc) { 3054 throw new RoleNotFoundException(exc.getMessage()); 3055 } 3056 3057 // Checks that role conforms to role info, 3058 Integer status = checkRoleInt(2, 3059 currRoleName, 3060 currRoleValue, 3061 roleInfo, 3062 false); 3063 int pbType = status.intValue(); 3064 if (pbType != 0) { 3065 // A problem has occurred: throws appropriate exception 3066 // here InvalidRoleValueException 3067 throwRoleProblemException(pbType, currRoleName); 3068 } 3069 3070 // Removes role info for that list from list of role infos for 3071 // roles to be defaulted 3072 int roleInfoIdx = roleInfoList.indexOf(roleInfo); 3073 // Note: no need to check if != -1, MUST be there :) 3074 roleInfoList.remove(roleInfoIdx); 3075 } 3076 } 3077 3078 // Initializes roles not initialized by roleList 3079 // Can throw InvalidRoleValueException 3080 initializeMissingRoles(relationBaseFlag, 3081 relationObj, 3082 relationObjName, 3083 relationId, 3084 relationTypeName, 3085 roleInfoList); 3086 3087 // Creation of relation successfull!!!! 3088 3089 // Updates internal maps 3090 // Relation id to object map 3091 synchronized(myRelId2ObjMap) { 3092 if (relationBaseFlag) { 3093 // Note: do not clone relation object, created by us :) 3094 myRelId2ObjMap.put(relationId, relationObj); 3095 } else { 3096 myRelId2ObjMap.put(relationId, relationObjName); 3097 } 3098 } 3099 3100 // Relation id to relation type name map 3101 synchronized(myRelId2RelTypeMap) { 3102 myRelId2RelTypeMap.put(relationId, 3103 relationTypeName); 3104 } 3105 3106 // Relation type to relation id map 3107 synchronized(myRelType2RelIdsMap) { 3108 List<String> relIdList = 3109 myRelType2RelIdsMap.get(relationTypeName); 3110 boolean firstRelFlag = false; 3111 if (relIdList == null) { 3112 firstRelFlag = true; 3113 relIdList = new ArrayList<String>(); 3114 } 3115 relIdList.add(relationId); 3116 if (firstRelFlag) { 3117 myRelType2RelIdsMap.put(relationTypeName, relIdList); 3118 } 3119 } 3120 3121 // Referenced MBean to relation id map 3122 // Only role list parameter used, as default initialization of roles 3123 // done automatically in initializeMissingRoles() sets each 3124 // uninitialized role to an empty value. 3125 for (Role currRole : roleList.asList()) { 3126 // Creates a dummy empty ArrayList of ObjectNames to be the old 3127 // role value :) 3128 List<ObjectName> dummyList = new ArrayList<ObjectName>(); 3129 // Will not throw a RelationNotFoundException (as the RelId2Obj map 3130 // has been updated above) so catch it :) 3131 try { 3132 updateRoleMap(relationId, currRole, dummyList); 3133 3134 } catch (RelationNotFoundException exc) { 3135 // OK : The Relation could not be found. 3136 } 3137 } 3138 3139 // Sends a notification for relation creation 3140 // Will not throw RelationNotFoundException so catch it :) 3141 try { 3142 sendRelationCreationNotification(relationId); 3143 3144 } catch (RelationNotFoundException exc) { 3145 // OK : The Relation could not be found. 3146 } 3147 3148 RELATION_LOGGER.exiting(RelationService.class.getName(), 3149 "addRelationInt"); 3150 return; 3151 } 3152 3153 // Checks that given role conforms to given role info. 3154 // 3155 // -param chkType type of check: 3156 // - 1: read, just check read access 3157 // - 2: write, check value and write access if writeChkFlag 3158 // -param roleName role name 3159 // -param roleValue role value 3160 // -param roleInfo corresponding role info 3161 // -param writeChkFlag boolean to specify a current write access and 3162 // to check it 3163 // 3164 // -return Integer with value: 3165 // - 0: ok 3166 // - RoleStatus.NO_ROLE_WITH_NAME 3167 // - RoleStatus.ROLE_NOT_READABLE 3168 // - RoleStatus.ROLE_NOT_WRITABLE 3169 // - RoleStatus.LESS_THAN_MIN_ROLE_DEGREE 3170 // - RoleStatus.MORE_THAN_MAX_ROLE_DEGREE 3171 // - RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS 3172 // - RoleStatus.REF_MBEAN_NOT_REGISTERED 3173 // 3174 // -exception IllegalArgumentException if null parameter 3175 private Integer checkRoleInt(int chkType, 3176 String roleName, 3177 List<ObjectName> roleValue, 3178 RoleInfo roleInfo, 3179 boolean writeChkFlag) 3180 throws IllegalArgumentException { 3181 3182 if (roleName == null || 3183 roleInfo == null || 3184 (chkType == 2 && roleValue == null)) { 3185 String excMsg = "Invalid parameter."; 3186 throw new IllegalArgumentException(excMsg); 3187 } 3188 3189 RELATION_LOGGER.entering(RelationService.class.getName(), 3190 "checkRoleInt", new Object[] {chkType, roleName, 3191 roleValue, roleInfo, writeChkFlag}); 3192 3193 // Compares names 3194 String expName = roleInfo.getName(); 3195 if (!(roleName.equals(expName))) { 3196 RELATION_LOGGER.exiting(RelationService.class.getName(), 3197 "checkRoleInt"); 3198 return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); 3199 } 3200 3201 // Checks read access if required 3202 if (chkType == 1) { 3203 boolean isReadable = roleInfo.isReadable(); 3204 if (!isReadable) { 3205 RELATION_LOGGER.exiting(RelationService.class.getName(), 3206 "checkRoleInt"); 3207 return Integer.valueOf(RoleStatus.ROLE_NOT_READABLE); 3208 } else { 3209 // End of check :) 3210 RELATION_LOGGER.exiting(RelationService.class.getName(), 3211 "checkRoleInt"); 3212 return new Integer(0); 3213 } 3214 } 3215 3216 // Checks write access if required 3217 if (writeChkFlag) { 3218 boolean isWritable = roleInfo.isWritable(); 3219 if (!isWritable) { 3220 RELATION_LOGGER.exiting(RelationService.class.getName(), 3221 "checkRoleInt"); 3222 return new Integer(RoleStatus.ROLE_NOT_WRITABLE); 3223 } 3224 } 3225 3226 int refNbr = roleValue.size(); 3227 3228 // Checks minimum cardinality 3229 boolean chkMinFlag = roleInfo.checkMinDegree(refNbr); 3230 if (!chkMinFlag) { 3231 RELATION_LOGGER.exiting(RelationService.class.getName(), 3232 "checkRoleInt"); 3233 return new Integer(RoleStatus.LESS_THAN_MIN_ROLE_DEGREE); 3234 } 3235 3236 // Checks maximum cardinality 3237 boolean chkMaxFlag = roleInfo.checkMaxDegree(refNbr); 3238 if (!chkMaxFlag) { 3239 RELATION_LOGGER.exiting(RelationService.class.getName(), 3240 "checkRoleInt"); 3241 return new Integer(RoleStatus.MORE_THAN_MAX_ROLE_DEGREE); 3242 } 3243 3244 // Verifies that each referenced MBean is registered in the MBean 3245 // Server and that it is an instance of the class specified in the 3246 // role info, or of a subclass of it 3247 // Note that here again this is under the assumption that 3248 // referenced MBeans, relation MBeans and the Relation Service are 3249 // registered in the same MBean Server. 3250 String expClassName = roleInfo.getRefMBeanClassName(); 3251 3252 for (ObjectName currObjName : roleValue) { 3253 3254 // Checks it is registered 3255 if (currObjName == null) { 3256 RELATION_LOGGER.exiting(RelationService.class.getName(), 3257 "checkRoleInt"); 3258 return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED); 3259 } 3260 3261 // Checks if it is of the correct class 3262 // Can throw an InstanceNotFoundException, if MBean not registered 3263 try { 3264 boolean classSts = myMBeanServer.isInstanceOf(currObjName, 3265 expClassName); 3266 if (!classSts) { 3267 RELATION_LOGGER.exiting(RelationService.class.getName(), 3268 "checkRoleInt"); 3269 return new Integer(RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS); 3270 } 3271 3272 } catch (InstanceNotFoundException exc) { 3273 RELATION_LOGGER.exiting(RelationService.class.getName(), 3274 "checkRoleInt"); 3275 return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED); 3276 } 3277 } 3278 3279 RELATION_LOGGER.exiting(RelationService.class.getName(), 3280 "checkRoleInt"); 3281 return new Integer(0); 3282 } 3283 3284 3285 // Initializes roles associated to given role infos to default value (empty 3286 // ArrayList of ObjectNames) in given relation. 3287 // It will succeed for every role except if the role info has a minimum 3288 // cardinality greater than 0. In that case, an InvalidRoleValueException 3289 // will be raised. 3290 // 3291 // -param relationBaseFlag flag true if the relation is a RelationSupport 3292 // object, false if it is an MBean 3293 // -param relationObj RelationSupport object (if relation is internal) 3294 // -param relationObjName ObjectName of the MBean to be added as a relation 3295 // (only for the relation MBean) 3296 // -param relationId relation id 3297 // -param relationTypeName name of the relation type (has to be created 3298 // in the Relation Service) 3299 // -param roleInfoList list of role infos for roles to be defaulted 3300 // 3301 // -exception IllegalArgumentException if null paramater 3302 // -exception RelationServiceNotRegisteredException if the Relation 3303 // Service is not registered in the MBean Server 3304 // -exception InvalidRoleValueException if role must have a non-empty 3305 // value 3306 3307 // Revisit [cebro] Handle CIM qualifiers as REQUIRED to detect roles which 3308 // should have been initialized by the user 3309 private void initializeMissingRoles(boolean relationBaseFlag, 3310 RelationSupport relationObj, 3311 ObjectName relationObjName, 3312 String relationId, 3313 String relationTypeName, 3314 List<RoleInfo> roleInfoList) 3315 throws IllegalArgumentException, 3316 RelationServiceNotRegisteredException, 3317 InvalidRoleValueException { 3318 3319 if ((relationBaseFlag && 3320 (relationObj == null || 3321 relationObjName != null)) || 3322 (!relationBaseFlag && 3323 (relationObjName == null || 3324 relationObj != null)) || 3325 relationId == null || 3326 relationTypeName == null || 3327 roleInfoList == null) { 3328 String excMsg = "Invalid parameter."; 3329 throw new IllegalArgumentException(excMsg); 3330 } 3331 3332 RELATION_LOGGER.entering(RelationService.class.getName(), 3333 "initializeMissingRoles", new Object[] {relationBaseFlag, 3334 relationObj, relationObjName, relationId, relationTypeName, 3335 roleInfoList}); 3336 3337 // Can throw RelationServiceNotRegisteredException 3338 isActive(); 3339 3340 // For each role info (corresponding to a role not initialized by the 3341 // role list provided by the user), try to set in the relation a role 3342 // with an empty list of ObjectNames. 3343 // A check is performed to verify that the role can be set to an 3344 // empty value, according to its minimum cardinality 3345 for (RoleInfo currRoleInfo : roleInfoList) { 3346 3347 String roleName = currRoleInfo.getName(); 3348 3349 // Creates an empty value 3350 List<ObjectName> emptyValue = new ArrayList<ObjectName>(); 3351 // Creates a role 3352 Role role = new Role(roleName, emptyValue); 3353 3354 if (relationBaseFlag) { 3355 3356 // Internal relation 3357 // Can throw InvalidRoleValueException 3358 // 3359 // Will not throw RoleNotFoundException (role to be 3360 // initialized), or RelationNotFoundException, or 3361 // RelationTypeNotFoundException 3362 try { 3363 relationObj.setRoleInt(role, true, this, false); 3364 3365 } catch (RoleNotFoundException exc1) { 3366 throw new RuntimeException(exc1.getMessage()); 3367 } catch (RelationNotFoundException exc2) { 3368 throw new RuntimeException(exc2.getMessage()); 3369 } catch (RelationTypeNotFoundException exc3) { 3370 throw new RuntimeException(exc3.getMessage()); 3371 } 3372 3373 } else { 3374 3375 // Relation is an MBean 3376 // Use standard setRole() 3377 Object[] params = new Object[1]; 3378 params[0] = role; 3379 String[] signature = new String[1]; 3380 signature[0] = "javax.management.relation.Role"; 3381 // Can throw MBeanException wrapping 3382 // InvalidRoleValueException. Returns the target exception to 3383 // be homogeneous. 3384 // 3385 // Will not throw MBeanException (wrapping 3386 // RoleNotFoundException or MBeanException) or 3387 // InstanceNotFoundException, or ReflectionException 3388 // 3389 // Again here the assumption is that the Relation Service and 3390 // the relation MBeans are registered in the same MBean Server. 3391 try { 3392 myMBeanServer.setAttribute(relationObjName, 3393 new Attribute("Role", role)); 3394 3395 } catch (InstanceNotFoundException exc1) { 3396 throw new RuntimeException(exc1.getMessage()); 3397 } catch (ReflectionException exc3) { 3398 throw new RuntimeException(exc3.getMessage()); 3399 } catch (MBeanException exc2) { 3400 Exception wrappedExc = exc2.getTargetException(); 3401 if (wrappedExc instanceof InvalidRoleValueException) { 3402 throw ((InvalidRoleValueException)wrappedExc); 3403 } else { 3404 throw new RuntimeException(wrappedExc.getMessage()); 3405 } 3406 } catch (AttributeNotFoundException exc4) { 3407 throw new RuntimeException(exc4.getMessage()); 3408 } catch (InvalidAttributeValueException exc5) { 3409 throw new RuntimeException(exc5.getMessage()); 3410 } 3411 } 3412 } 3413 3414 RELATION_LOGGER.exiting(RelationService.class.getName(), 3415 "initializeMissingRoles"); 3416 return; 3417 } 3418 3419 // Throws an exception corresponding to a given problem type 3420 // 3421 // -param pbType possible problem, defined in RoleUnresolved 3422 // -param roleName role name 3423 // 3424 // -exception IllegalArgumentException if null parameter 3425 // -exception RoleNotFoundException for problems: 3426 // - NO_ROLE_WITH_NAME 3427 // - ROLE_NOT_READABLE 3428 // - ROLE_NOT_WRITABLE 3429 // -exception InvalidRoleValueException for problems: 3430 // - LESS_THAN_MIN_ROLE_DEGREE 3431 // - MORE_THAN_MAX_ROLE_DEGREE 3432 // - REF_MBEAN_OF_INCORRECT_CLASS 3433 // - REF_MBEAN_NOT_REGISTERED 3434 static void throwRoleProblemException(int pbType, 3435 String roleName) 3436 throws IllegalArgumentException, 3437 RoleNotFoundException, 3438 InvalidRoleValueException { 3439 3440 if (roleName == null) { 3441 String excMsg = "Invalid parameter."; 3442 throw new IllegalArgumentException(excMsg); 3443 } 3444 3445 // Exception type: 1 = RoleNotFoundException 3446 // 2 = InvalidRoleValueException 3447 int excType = 0; 3448 3449 String excMsgPart = null; 3450 3451 switch (pbType) { 3452 case RoleStatus.NO_ROLE_WITH_NAME: 3453 excMsgPart = " does not exist in relation."; 3454 excType = 1; 3455 break; 3456 case RoleStatus.ROLE_NOT_READABLE: 3457 excMsgPart = " is not readable."; 3458 excType = 1; 3459 break; 3460 case RoleStatus.ROLE_NOT_WRITABLE: 3461 excMsgPart = " is not writable."; 3462 excType = 1; 3463 break; 3464 case RoleStatus.LESS_THAN_MIN_ROLE_DEGREE: 3465 excMsgPart = " has a number of MBean references less than the expected minimum degree."; 3466 excType = 2; 3467 break; 3468 case RoleStatus.MORE_THAN_MAX_ROLE_DEGREE: 3469 excMsgPart = " has a number of MBean references greater than the expected maximum degree."; 3470 excType = 2; 3471 break; 3472 case RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS: 3473 excMsgPart = " has an MBean reference to an MBean not of the expected class of references for that role."; 3474 excType = 2; 3475 break; 3476 case RoleStatus.REF_MBEAN_NOT_REGISTERED: 3477 excMsgPart = " has a reference to null or to an MBean not registered."; 3478 excType = 2; 3479 break; 3480 } 3481 // No default as we must have been in one of those cases 3482 3483 StringBuilder excMsgStrB = new StringBuilder(roleName); 3484 excMsgStrB.append(excMsgPart); 3485 String excMsg = excMsgStrB.toString(); 3486 if (excType == 1) { 3487 throw new RoleNotFoundException(excMsg); 3488 3489 } else if (excType == 2) { 3490 throw new InvalidRoleValueException(excMsg); 3491 } 3492 } 3493 3494 // Sends a notification of given type, with given parameters 3495 // 3496 // -param intNtfType integer to represent notification type: 3497 // - 1 : create 3498 // - 2 : update 3499 // - 3 : delete 3500 // -param message human-readable message 3501 // -param relationId relation id of the created/updated/deleted relation 3502 // -param unregMBeanList list of ObjectNames of referenced MBeans 3503 // expected to be unregistered due to relation removal (only for removal, 3504 // due to CIM qualifiers, can be null) 3505 // -param roleName role name 3506 // -param roleNewValue role new value (ArrayList of ObjectNames) 3507 // -param oldValue old role value (ArrayList of ObjectNames) 3508 // 3509 // -exception IllegalArgument if null parameter 3510 // -exception RelationNotFoundException if no relation for given id 3511 private void sendNotificationInt(int intNtfType, 3512 String message, 3513 String relationId, 3514 List<ObjectName> unregMBeanList, 3515 String roleName, 3516 List<ObjectName> roleNewValue, 3517 List<ObjectName> oldValue) 3518 throws IllegalArgumentException, 3519 RelationNotFoundException { 3520 3521 if (message == null || 3522 relationId == null || 3523 (intNtfType != 3 && unregMBeanList != null) || 3524 (intNtfType == 2 && 3525 (roleName == null || 3526 roleNewValue == null || 3527 oldValue == null))) { 3528 String excMsg = "Invalid parameter."; 3529 throw new IllegalArgumentException(excMsg); 3530 } 3531 3532 RELATION_LOGGER.entering(RelationService.class.getName(), 3533 "sendNotificationInt", new Object[] {intNtfType, message, 3534 relationId, unregMBeanList, roleName, roleNewValue, oldValue}); 3535 3536 // Relation type name 3537 // Note: do not use getRelationTypeName() as if it is a relation MBean 3538 // it is already unregistered. 3539 String relTypeName; 3540 synchronized(myRelId2RelTypeMap) { 3541 relTypeName = (myRelId2RelTypeMap.get(relationId)); 3542 } 3543 3544 // ObjectName (for a relation MBean) 3545 // Can also throw a RelationNotFoundException, but detected above 3546 ObjectName relObjName = isRelationMBean(relationId); 3547 3548 String ntfType = null; 3549 if (relObjName != null) { 3550 switch (intNtfType) { 3551 case 1: 3552 ntfType = RelationNotification.RELATION_MBEAN_CREATION; 3553 break; 3554 case 2: 3555 ntfType = RelationNotification.RELATION_MBEAN_UPDATE; 3556 break; 3557 case 3: 3558 ntfType = RelationNotification.RELATION_MBEAN_REMOVAL; 3559 break; 3560 } 3561 } else { 3562 switch (intNtfType) { 3563 case 1: 3564 ntfType = RelationNotification.RELATION_BASIC_CREATION; 3565 break; 3566 case 2: 3567 ntfType = RelationNotification.RELATION_BASIC_UPDATE; 3568 break; 3569 case 3: 3570 ntfType = RelationNotification.RELATION_BASIC_REMOVAL; 3571 break; 3572 } 3573 } 3574 3575 // Sequence number 3576 Long seqNo = atomicSeqNo.incrementAndGet(); 3577 3578 // Timestamp 3579 Date currDate = new Date(); 3580 long timeStamp = currDate.getTime(); 3581 3582 RelationNotification ntf = null; 3583 3584 if (ntfType.equals(RelationNotification.RELATION_BASIC_CREATION) || 3585 ntfType.equals(RelationNotification.RELATION_MBEAN_CREATION) || 3586 ntfType.equals(RelationNotification.RELATION_BASIC_REMOVAL) || 3587 ntfType.equals(RelationNotification.RELATION_MBEAN_REMOVAL)) 3588 3589 // Creation or removal 3590 ntf = new RelationNotification(ntfType, 3591 this, 3592 seqNo.longValue(), 3593 timeStamp, 3594 message, 3595 relationId, 3596 relTypeName, 3597 relObjName, 3598 unregMBeanList); 3599 3600 else if (ntfType.equals(RelationNotification.RELATION_BASIC_UPDATE) 3601 || 3602 ntfType.equals(RelationNotification.RELATION_MBEAN_UPDATE)) 3603 { 3604 // Update 3605 ntf = new RelationNotification(ntfType, 3606 this, 3607 seqNo.longValue(), 3608 timeStamp, 3609 message, 3610 relationId, 3611 relTypeName, 3612 relObjName, 3613 roleName, 3614 roleNewValue, 3615 oldValue); 3616 } 3617 3618 sendNotification(ntf); 3619 3620 RELATION_LOGGER.exiting(RelationService.class.getName(), 3621 "sendNotificationInt"); 3622 return; 3623 } 3624 3625 // Checks, for the unregistration of an MBean referenced in the roles given 3626 // in parameter, if the relation has to be removed or not, regarding 3627 // expected minimum role cardinality and current number of 3628 // references in each role after removal of the current one. 3629 // If the relation is kept, calls handleMBeanUnregistration() callback of 3630 // the relation to update it. 3631 // 3632 // -param relationId relation id 3633 // -param objectName ObjectName of the unregistered MBean 3634 // -param roleNameList list of names of roles where the unregistered 3635 // MBean is referenced. 3636 // 3637 // -exception IllegalArgumentException if null parameter 3638 // -exception RelationServiceNotRegisteredException if the Relation 3639 // Service is not registered in the MBean Server 3640 // -exception RelationNotFoundException if unknown relation id 3641 // -exception RoleNotFoundException if one role given as parameter does 3642 // not exist in the relation 3643 private void handleReferenceUnregistration(String relationId, 3644 ObjectName objectName, 3645 List<String> roleNameList) 3646 throws IllegalArgumentException, 3647 RelationServiceNotRegisteredException, 3648 RelationNotFoundException, 3649 RoleNotFoundException { 3650 3651 if (relationId == null || 3652 roleNameList == null || 3653 objectName == null) { 3654 String excMsg = "Invalid parameter."; 3655 throw new IllegalArgumentException(excMsg); 3656 } 3657 3658 RELATION_LOGGER.entering(RelationService.class.getName(), 3659 "handleReferenceUnregistration", 3660 new Object[] {relationId, objectName, roleNameList}); 3661 3662 // Can throw RelationServiceNotRegisteredException 3663 isActive(); 3664 3665 // Retrieves the relation type name of the relation 3666 // Can throw RelationNotFoundException 3667 String currRelTypeName = getRelationTypeName(relationId); 3668 3669 // Retrieves the relation 3670 // Can throw RelationNotFoundException, but already detected above 3671 Object relObj = getRelation(relationId); 3672 3673 // Flag to specify if the relation has to be deleted 3674 boolean deleteRelFlag = false; 3675 3676 for (String currRoleName : roleNameList) { 3677 3678 if (deleteRelFlag) { 3679 break; 3680 } 3681 3682 // Retrieves number of MBeans currently referenced in role 3683 // BEWARE! Do not use getRole() as role may be not readable 3684 // 3685 // Can throw RelationNotFoundException (but already checked), 3686 // RoleNotFoundException 3687 int currRoleRefNbr = 3688 (getRoleCardinality(relationId, currRoleName)).intValue(); 3689 3690 // Retrieves new number of element in role 3691 int currRoleNewRefNbr = currRoleRefNbr - 1; 3692 3693 // Retrieves role info for that role 3694 // 3695 // Shall not throw RelationTypeNotFoundException or 3696 // RoleInfoNotFoundException 3697 RoleInfo currRoleInfo; 3698 try { 3699 currRoleInfo = getRoleInfo(currRelTypeName, 3700 currRoleName); 3701 } catch (RelationTypeNotFoundException exc1) { 3702 throw new RuntimeException(exc1.getMessage()); 3703 } catch (RoleInfoNotFoundException exc2) { 3704 throw new RuntimeException(exc2.getMessage()); 3705 } 3706 3707 // Checks with expected minimum number of elements 3708 boolean chkMinFlag = currRoleInfo.checkMinDegree(currRoleNewRefNbr); 3709 3710 if (!chkMinFlag) { 3711 // The relation has to be deleted 3712 deleteRelFlag = true; 3713 } 3714 } 3715 3716 if (deleteRelFlag) { 3717 // Removes the relation 3718 removeRelation(relationId); 3719 3720 } else { 3721 3722 // Updates each role in the relation using 3723 // handleMBeanUnregistration() callback 3724 // 3725 // BEWARE: this roleNameList list MUST BE A COPY of a role name 3726 // list for a referenced MBean in a relation, NOT a 3727 // reference to an original one part of the 3728 // myRefedMBeanObjName2RelIdsMap!!!! Because each role 3729 // which name is in that list will be updated (potentially 3730 // using setRole(). So the Relation Service will update the 3731 // myRefedMBeanObjName2RelIdsMap to refelect the new role 3732 // value! 3733 for (String currRoleName : roleNameList) { 3734 3735 if (relObj instanceof RelationSupport) { 3736 // Internal relation 3737 // Can throw RoleNotFoundException (but already checked) 3738 // 3739 // Shall not throw 3740 // RelationTypeNotFoundException, 3741 // InvalidRoleValueException (value was correct, removing 3742 // one reference shall not invalidate it, else detected 3743 // above) 3744 try { 3745 ((RelationSupport)relObj).handleMBeanUnregistrationInt( 3746 objectName, 3747 currRoleName, 3748 true, 3749 this); 3750 } catch (RelationTypeNotFoundException exc3) { 3751 throw new RuntimeException(exc3.getMessage()); 3752 } catch (InvalidRoleValueException exc4) { 3753 throw new RuntimeException(exc4.getMessage()); 3754 } 3755 3756 } else { 3757 // Relation MBean 3758 Object[] params = new Object[2]; 3759 params[0] = objectName; 3760 params[1] = currRoleName; 3761 String[] signature = new String[2]; 3762 signature[0] = "javax.management.ObjectName"; 3763 signature[1] = "java.lang.String"; 3764 // Shall not throw InstanceNotFoundException, or 3765 // MBeanException (wrapping RoleNotFoundException or 3766 // MBeanException or InvalidRoleValueException) or 3767 // ReflectionException 3768 try { 3769 myMBeanServer.invoke(((ObjectName)relObj), 3770 "handleMBeanUnregistration", 3771 params, 3772 signature); 3773 } catch (InstanceNotFoundException exc1) { 3774 throw new RuntimeException(exc1.getMessage()); 3775 } catch (ReflectionException exc3) { 3776 throw new RuntimeException(exc3.getMessage()); 3777 } catch (MBeanException exc2) { 3778 Exception wrappedExc = exc2.getTargetException(); 3779 throw new RuntimeException(wrappedExc.getMessage()); 3780 } 3781 3782 } 3783 } 3784 } 3785 3786 RELATION_LOGGER.exiting(RelationService.class.getName(), 3787 "handleReferenceUnregistration"); 3788 return; 3789 } 3790 }