Home » openjdk-7 » javax » management » relation » [javadoc | source]

    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   }

Home » openjdk-7 » javax » management » relation » [javadoc | source]