/*
 * Copyright 2000-2006 Sun Microsystems, Inc.  All Rights Reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Sun designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Sun in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
 * CA 95054 USA or visit www.sun.com if you need additional information or
 * have any questions.
 */

package javax.management.relation;

import static com.sun.jmx.defaults.JmxProperties.RELATION_LOGGER;
import static com.sun.jmx.mbeanserver.Util.cast;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;

import javax.management.Attribute;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceNotFoundException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
import javax.management.MBeanServerNotification;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.ReflectionException;

/**
 * The Relation Service is in charge of creating and deleting relation types
 * and relations, of handling the consistency and of providing query
 * mechanisms.
 * <P>It implements the NotificationBroadcaster by extending
 * NotificationBroadcasterSupport to send notifications when a relation is
 * removed from it.
 * <P>It implements the NotificationListener interface to be able to receive
 * notifications concerning unregistration of MBeans referenced in relation
 * roles and of relation MBeans.
 * <P>It implements the MBeanRegistration interface to be able to retrieve
 * its ObjectName and MBean Server.
 *
 * @since 1.5
 */
public class RelationService extends NotificationBroadcasterSupport
    implements RelationServiceMBean, MBeanRegistration, NotificationListener {

    //
    // Private members
    //

    // Map associating:
    //      <relation id> -> <RelationSupport object/ObjectName>
    // depending if the relation has been created using createRelation()
    // method (so internally handled) or is an MBean added as a relation by the
    // user
    private Map<String,Object> myRelId2ObjMap = new HashMap<String,Object>();

    // Map associating:
    //      <relation id> -> <relation type name>
    private Map<String,String> myRelId2RelTypeMap = new HashMap<String,String>();

    // Map associating:
    //      <relation MBean Object Name> -> <relation id>
    private Map<ObjectName,String> myRelMBeanObjName2RelIdMap =
        new HashMap<ObjectName,String>();

    // Map associating:
    //       <relation type name> -> <RelationType object>
    private Map<String,RelationType> myRelType2ObjMap =
        new HashMap<String,RelationType>();

    // Map associating:
    //       <relation type name> -> ArrayList of <relation id>
    // to list all the relations of a given type
    private Map<String,List<String>> myRelType2RelIdsMap =
        new HashMap<String,List<String>>();

    // Map associating:
    //       <ObjectName> -> HashMap
    // the value HashMap mapping:
    //       <relation id> -> ArrayList of <role name>
    // to track where a given MBean is referenced.
    private Map<ObjectName,Map<String,List<String>>>
        myRefedMBeanObjName2RelIdsMap =
            new HashMap<ObjectName,Map<String,List<String>>>();

    // Flag to indicate if, when a notification is received for the
    // unregistration of an MBean referenced in a relation, if an immediate
    // "purge" of the relations (look for the relations no
    // longer valid) has to be performed , or if that will be performed only
    // when the purgeRelations method will be explicitly called.
    // true is immediate purge.
    private boolean myPurgeFlag = true;

    // Internal counter to provide sequence numbers for notifications sent by:
    // - the Relation Service
    // - a relation handled by the Relation Service
    private Long myNtfSeqNbrCounter = new Long(0);

    // ObjectName used to register the Relation Service in the MBean Server
    private ObjectName myObjName = null;

    // MBean Server where the Relation Service is registered
    private MBeanServer myMBeanServer = null;

    // Filter registered in the MBean Server with the Relation Service to be
    // informed of referenced MBean unregistrations
    private MBeanServerNotificationFilter myUnregNtfFilter = null;

    // List of unregistration notifications received (storage used if purge
    // of relations when unregistering a referenced MBean is not immediate but
    // on user request)
    private List<MBeanServerNotification> myUnregNtfList =
        new ArrayList<MBeanServerNotification>();

    //
    // Constructor
    //

    /**
     * Constructor.
     *
     * @param immediatePurgeFlag  flag to indicate when a notification is
     * received for the unregistration of an MBean referenced in a relation, if
     * an immediate "purge" of the relations (look for the relations no
     * longer valid) has to be performed , or if that will be performed only
     * when the purgeRelations method will be explicitly called.
     * <P>true is immediate purge.
     */
    public RelationService(boolean immediatePurgeFlag) {

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "RelationService");

        setPurgeFlag(immediatePurgeFlag);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "RelationService");
        return;
    }

    /**
     * Checks if the Relation Service is active.
     * Current condition is that the Relation Service must be registered in the
     * MBean Server
     *
     * @exception RelationServiceNotRegisteredException  if it is not
     * registered
     */
    public void isActive()
        throws RelationServiceNotRegisteredException {
        if (myMBeanServer == null) {
            // MBean Server not set by preRegister(): relation service not
            // registered
            String excMsg =
                "Relation Service not registered in the MBean Server.";
            throw new RelationServiceNotRegisteredException(excMsg);
        }
        return;
    }

    //
    // MBeanRegistration interface
    //

    // Pre-registration: retrieves its ObjectName and MBean Server
    //
    // No exception thrown.
    public ObjectName preRegister(MBeanServer server,
                                  ObjectName name)
        throws Exception {

        myMBeanServer = server;
        myObjName = name;
        return name;
    }

    // Post-registration: does nothing
    public void postRegister(Boolean registrationDone) {
        return;
    }

    // Pre-unregistration: does nothing
    public void preDeregister()
        throws Exception {
        return;
    }

    // Post-unregistration: does nothing
    public void postDeregister() {
        return;
    }

    //
    // Accessors
    //

    /**
     * Returns the flag to indicate if when a notification is received for the
     * unregistration of an MBean referenced in a relation, if an immediate
     * "purge" of the relations (look for the relations no longer valid)
     * has to be performed , or if that will be performed only when the
     * purgeRelations method will be explicitly called.
     * <P>true is immediate purge.
     *
     * @return true if purges are automatic.
     *
     * @see #setPurgeFlag
     */
    public boolean getPurgeFlag() {
        return myPurgeFlag;
    }

    /**
     * Sets the flag to indicate if when a notification is received for the
     * unregistration of an MBean referenced in a relation, if an immediate
     * "purge" of the relations (look for the relations no longer valid)
     * has to be performed , or if that will be performed only when the
     * purgeRelations method will be explicitly called.
     * <P>true is immediate purge.
     *
     * @param purgeFlag  flag
     *
     * @see #getPurgeFlag
     */
    public void setPurgeFlag(boolean purgeFlag) {

        myPurgeFlag = purgeFlag;
        return;
    }

    // Returns internal counter to be used for Sequence Numbers of
    // notifications to be raised by:
    // - a relation handled by this Relation Service (when updated)
    // - the Relation Service
    private Long getNotificationSequenceNumber() {
        Long result = null;
        synchronized(myNtfSeqNbrCounter) {
            result = new Long(myNtfSeqNbrCounter.longValue() + 1);
            myNtfSeqNbrCounter = new Long(result.longValue());
        }
        return result;
    }

    //
    // Relation type handling
    //

    /**
     * Creates a relation type (a RelationTypeSupport object) with given
     * role infos (provided by the RoleInfo objects), and adds it in the
     * Relation Service.
     *
     * @param relationTypeName  name of the relation type
     * @param roleInfoArray  array of role infos
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception InvalidRelationTypeException  If:
     * <P>- there is already a relation type with that name
     * <P>- the same name has been used for two different role infos
     * <P>- no role info provided
     * <P>- one null role info provided
     */
    public void createRelationType(String relationTypeName,
                                   RoleInfo[] roleInfoArray)
        throws IllegalArgumentException,
               InvalidRelationTypeException {

        if (relationTypeName == null || roleInfoArray == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "createRelationType", relationTypeName);

        // Can throw an InvalidRelationTypeException
        RelationType relType =
            new RelationTypeSupport(relationTypeName, roleInfoArray);

        addRelationTypeInt(relType);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "createRelationType");
        return;
    }

    /**
     * Adds given object as a relation type. The object is expected to
     * implement the RelationType interface.
     *
     * @param relationTypeObj  relation type object (implementing the
     * RelationType interface)
     *
     * @exception IllegalArgumentException  if null parameter or if
     * {@link RelationType#getRelationTypeName
     * relationTypeObj.getRelationTypeName()} returns null.
     * @exception InvalidRelationTypeException  if:
     * <P>- the same name has been used for two different roles
     * <P>- no role info provided
     * <P>- one null role info provided
     * <P>- there is already a relation type with that name
     */
    public void addRelationType(RelationType relationTypeObj)
        throws IllegalArgumentException,
               InvalidRelationTypeException {

        if (relationTypeObj == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "addRelationType");

        // Checks the role infos
        List<RoleInfo> roleInfoList = relationTypeObj.getRoleInfos();
        if (roleInfoList == null) {
            String excMsg = "No role info provided.";
            throw new InvalidRelationTypeException(excMsg);
        }

        RoleInfo[] roleInfoArray = new RoleInfo[roleInfoList.size()];
        int i = 0;
        for (RoleInfo currRoleInfo : roleInfoList) {
            roleInfoArray[i] = currRoleInfo;
            i++;
        }
        // Can throw InvalidRelationTypeException
        RelationTypeSupport.checkRoleInfos(roleInfoArray);

        addRelationTypeInt(relationTypeObj);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "addRelationType");
        return;
     }

    /**
     * Retrieves names of all known relation types.
     *
     * @return ArrayList of relation type names (Strings)
     */
    public List<String> getAllRelationTypeNames() {
        ArrayList<String> result = null;
        synchronized(myRelType2ObjMap) {
            result = new ArrayList<String>(myRelType2ObjMap.keySet());
        }
        return result;
    }

    /**
     * Retrieves list of role infos (RoleInfo objects) of a given relation
     * type.
     *
     * @param relationTypeName  name of relation type
     *
     * @return ArrayList of RoleInfo.
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationTypeNotFoundException  if there is no relation type
     * with that name.
     */
    public List<RoleInfo> getRoleInfos(String relationTypeName)
        throws IllegalArgumentException,
               RelationTypeNotFoundException {

        if (relationTypeName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRoleInfos", relationTypeName);

        // Can throw a RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getRoleInfos");
        return relType.getRoleInfos();
    }

    /**
     * Retrieves role info for given role name of a given relation type.
     *
     * @param relationTypeName  name of relation type
     * @param roleInfoName  name of role
     *
     * @return RoleInfo object.
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationTypeNotFoundException  if the relation type is not
     * known in the Relation Service
     * @exception RoleInfoNotFoundException  if the role is not part of the
     * relation type.
     */
    public RoleInfo getRoleInfo(String relationTypeName,
                                String roleInfoName)
        throws IllegalArgumentException,
               RelationTypeNotFoundException,
               RoleInfoNotFoundException {

        if (relationTypeName == null || roleInfoName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRoleInfo", new Object[] {relationTypeName, roleInfoName});

        // Can throw a RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        // Can throw a RoleInfoNotFoundException
        RoleInfo roleInfo = relType.getRoleInfo(roleInfoName);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getRoleInfo");
        return roleInfo;
    }

    /**
     * Removes given relation type from Relation Service.
     * <P>The relation objects of that type will be removed from the
     * Relation Service.
     *
     * @param relationTypeName  name of the relation type to be removed
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationTypeNotFoundException  If there is no relation type
     * with that name
     */
    public void removeRelationType(String relationTypeName)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RelationTypeNotFoundException {

        // Can throw RelationServiceNotRegisteredException
        isActive();

        if (relationTypeName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "removeRelationType", relationTypeName);

        // Checks if the relation type to be removed exists
        // Can throw a RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        // Retrieves the relation ids for relations of that type
        List<String> relIdList = null;
        synchronized(myRelType2RelIdsMap) {
            // Note: take a copy of the list as it is a part of a map that
            //       will be updated by removeRelation() below.
            List<String> relIdList1 =
                myRelType2RelIdsMap.get(relationTypeName);
            if (relIdList1 != null) {
                relIdList = new ArrayList<String>(relIdList1);
            }
        }

        // Removes the relation type from all maps
        synchronized(myRelType2ObjMap) {
            myRelType2ObjMap.remove(relationTypeName);
        }
        synchronized(myRelType2RelIdsMap) {
            myRelType2RelIdsMap.remove(relationTypeName);
        }

        // Removes all relations of that type
        if (relIdList != null) {
            for (String currRelId : relIdList) {
                // Note: will remove it from myRelId2RelTypeMap :)
                //
                // Can throw RelationServiceNotRegisteredException (detected
                // above)
                // Shall not throw a RelationNotFoundException
                try {
                    removeRelation(currRelId);
                } catch (RelationNotFoundException exc1) {
                    throw new RuntimeException(exc1.getMessage());
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "removeRelationType");
        return;
    }

    //
    // Relation handling
    //

    /**
     * Creates a simple relation (represented by a RelationSupport object) of
     * given relation type, and adds it in the Relation Service.
     * <P>Roles are initialized according to the role list provided in
     * parameter. The ones not initialized in this way are set to an empty
     * ArrayList of ObjectNames.
     * <P>A RelationNotification, with type RELATION_BASIC_CREATION, is sent.
     *
     * @param relationId  relation identifier, to identify uniquely the relation
     * inside the Relation Service
     * @param relationTypeName  name of the relation type (has to be created
     * in the Relation Service)
     * @param roleList  role list to initialize roles of the relation (can
     * be null).
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception IllegalArgumentException  if null parameter, except the role
     * list which can be null if no role initialization
     * @exception RoleNotFoundException  if a value is provided for a role
     * that does not exist in the relation type
     * @exception InvalidRelationIdException  if relation id already used
     * @exception RelationTypeNotFoundException  if relation type not known in
     * Relation Service
     * @exception InvalidRoleValueException if:
     * <P>- the same role name is used for two different roles
     * <P>- the number of referenced MBeans in given value is less than
     * expected minimum degree
     * <P>- the number of referenced MBeans in provided value exceeds expected
     * maximum degree
     * <P>- one referenced MBean in the value is not an Object of the MBean
     * class expected for that role
     * <P>- an MBean provided for that role does not exist
     */
    public void createRelation(String relationId,
                               String relationTypeName,
                               RoleList roleList)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RoleNotFoundException,
               InvalidRelationIdException,
               RelationTypeNotFoundException,
               InvalidRoleValueException {

        // Can throw RelationServiceNotRegisteredException
        isActive();

        if (relationId == null ||
            relationTypeName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "createRelation",
                new Object[] {relationId, relationTypeName, roleList});

        // Creates RelationSupport object
        // Can throw InvalidRoleValueException
        RelationSupport relObj = new RelationSupport(relationId,
                                               myObjName,
                                               relationTypeName,
                                               roleList);

        // Adds relation object as a relation into the Relation Service
        // Can throw RoleNotFoundException, InvalidRelationId,
        // RelationTypeNotFoundException, InvalidRoleValueException
        //
        // Cannot throw MBeanException
        addRelationInt(true,
                       relObj,
                       null,
                       relationId,
                       relationTypeName,
                       roleList);
        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "createRelation");
        return;
    }

    /**
     * Adds an MBean created by the user (and registered by him in the MBean
     * Server) as a relation in the Relation Service.
     * <P>To be added as a relation, the MBean must conform to the
     * following:
     * <P>- implement the Relation interface
     * <P>- have for RelationService ObjectName the ObjectName of current
     * Relation Service
     * <P>- have a relation id unique and unused in current Relation Service
     * <P>- have for relation type a relation type created in the Relation
     * Service
     * <P>- have roles conforming to the role info provided in the relation
     * type.
     *
     * @param relationObjectName  ObjectName of the relation MBean to be added.
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception NoSuchMethodException  If the MBean does not implement the
     * Relation interface
     * @exception InvalidRelationIdException  if:
     * <P>- no relation identifier in MBean
     * <P>- the relation identifier is already used in the Relation Service
     * @exception InstanceNotFoundException  if the MBean for given ObjectName
     * has not been registered
     * @exception InvalidRelationServiceException  if:
     * <P>- no Relation Service name in MBean
     * <P>- the Relation Service name in the MBean is not the one of the
     * current Relation Service
     * @exception RelationTypeNotFoundException  if:
     * <P>- no relation type name in MBean
     * <P>- the relation type name in MBean does not correspond to a relation
     * type created in the Relation Service
     * @exception InvalidRoleValueException  if:
     * <P>- the number of referenced MBeans in a role is less than
     * expected minimum degree
     * <P>- the number of referenced MBeans in a role exceeds expected
     * maximum degree
     * <P>- one referenced MBean in the value is not an Object of the MBean
     * class expected for that role
     * <P>- an MBean provided for a role does not exist
     * @exception RoleNotFoundException  if a value is provided for a role
     * that does not exist in the relation type
     */
    public void addRelation(ObjectName relationObjectName)
        throws IllegalArgumentException,
               RelationServiceNotRegisteredException,
               NoSuchMethodException,
               InvalidRelationIdException,
               InstanceNotFoundException,
               InvalidRelationServiceException,
               RelationTypeNotFoundException,
               RoleNotFoundException,
               InvalidRoleValueException {

        if (relationObjectName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "addRelation", relationObjectName);

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Checks that the relation MBean implements the Relation interface.
        // It will also check that the provided ObjectName corresponds to a
        // registered MBean (else will throw an InstanceNotFoundException)
        if ((!(myMBeanServer.isInstanceOf(relationObjectName, "javax.management.relation.Relation")))) {
            String excMsg = "This MBean does not implement the Relation interface.";
            throw new NoSuchMethodException(excMsg);
        }
        // Checks there is a relation id in the relation MBean (its uniqueness
        // is checked in addRelationInt())
        // Can throw InstanceNotFoundException (but detected above)
        // No MBeanException as no exception raised by this method, and no
        // ReflectionException
        String relId = null;
        try {
            relId = (String)(myMBeanServer.getAttribute(relationObjectName,
                                                        "RelationId"));

        } catch (MBeanException exc1) {
            throw new RuntimeException(
                                     (exc1.getTargetException()).getMessage());
        } catch (ReflectionException exc2) {
            throw new RuntimeException(exc2.getMessage());
        } catch (AttributeNotFoundException exc3) {
            throw new RuntimeException(exc3.getMessage());
        }

        if (relId == null) {
            String excMsg = "This MBean does not provide a relation id.";
            throw new InvalidRelationIdException(excMsg);
        }
        // Checks that the Relation Service where the relation MBean is
        // expected to be added is the current one
        // Can throw InstanceNotFoundException (but detected above)
        // No MBeanException as no exception raised by this method, no
        // ReflectionException
        ObjectName relServObjName = null;
        try {
            relServObjName = (ObjectName)
                (myMBeanServer.getAttribute(relationObjectName,
                                            "RelationServiceName"));

        } catch (MBeanException exc1) {
            throw new RuntimeException(
                                     (exc1.getTargetException()).getMessage());
        } catch (ReflectionException exc2) {
            throw new RuntimeException(exc2.getMessage());
        } catch (AttributeNotFoundException exc3) {
            throw new RuntimeException(exc3.getMessage());
        }

        boolean badRelServFlag = false;
        if (relServObjName == null) {
            badRelServFlag = true;

        } else if (!(relServObjName.equals(myObjName))) {
            badRelServFlag = true;
        }
        if (badRelServFlag) {
            String excMsg = "The Relation Service referenced in the MBean is not the current one.";
            throw new InvalidRelationServiceException(excMsg);
        }
        // Checks that a relation type has been specified for the relation
        // Can throw InstanceNotFoundException (but detected above)
        // No MBeanException as no exception raised by this method, no
        // ReflectionException
        String relTypeName = null;
        try {
            relTypeName = (String)(myMBeanServer.getAttribute(relationObjectName,
                                                              "RelationTypeName"));

        } catch (MBeanException exc1) {
            throw new RuntimeException(
                                     (exc1.getTargetException()).getMessage());
        }catch (ReflectionException exc2) {
            throw new RuntimeException(exc2.getMessage());
        } catch (AttributeNotFoundException exc3) {
            throw new RuntimeException(exc3.getMessage());
        }
        if (relTypeName == null) {
            String excMsg = "No relation type provided.";
            throw new RelationTypeNotFoundException(excMsg);
        }
        // Retrieves all roles without considering read mode
        // Can throw InstanceNotFoundException (but detected above)
        // No MBeanException as no exception raised by this method, no
        // ReflectionException
        RoleList roleList = null;
        try {
            roleList = (RoleList)(myMBeanServer.invoke(relationObjectName,
                                                       "retrieveAllRoles",
                                                       null,
                                                       null));
        } catch (MBeanException exc1) {
            throw new RuntimeException(
                                     (exc1.getTargetException()).getMessage());
        } catch (ReflectionException exc2) {
            throw new RuntimeException(exc2.getMessage());
        }

        // Can throw RoleNotFoundException, InvalidRelationIdException,
        // RelationTypeNotFoundException, InvalidRoleValueException
        addRelationInt(false,
                       null,
                       relationObjectName,
                       relId,
                       relTypeName,
                       roleList);
        // Adds relation MBean ObjectName in map
        synchronized(myRelMBeanObjName2RelIdMap) {
            myRelMBeanObjName2RelIdMap.put(relationObjectName, relId);
        }

        // Updates flag to specify that the relation is managed by the Relation
        // Service
        // This flag and setter are inherited from RelationSupport and not parts
        // of the Relation interface, so may be not supported.
        try {
            myMBeanServer.setAttribute(relationObjectName,
                                       new Attribute(
                                         "RelationServiceManagementFlag",
                                         Boolean.TRUE));
        } catch (Exception exc) {
            // OK : The flag is not supported.
        }

        // Updates listener information to received notification for
        // unregistration of this MBean
        List<ObjectName> newRefList = new ArrayList<ObjectName>();
        newRefList.add(relationObjectName);
        updateUnregistrationListener(newRefList, null);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "addRelation");
        return;
    }

    /**
     * If the relation is represented by an MBean (created by the user and
     * added as a relation in the Relation Service), returns the ObjectName of
     * the MBean.
     *
     * @param relationId  relation id identifying the relation
     *
     * @return ObjectName of the corresponding relation MBean, or null if
     * the relation is not an MBean.
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException there is no relation associated
     * to that id
     */
    public ObjectName isRelationMBean(String relationId)
        throws IllegalArgumentException,
               RelationNotFoundException{

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "isRelationMBean", relationId);

        // Can throw RelationNotFoundException
        Object result = getRelation(relationId);
        if (result instanceof ObjectName) {
            return ((ObjectName)result);
        } else {
            return null;
        }
    }

    /**
     * Returns the relation id associated to the given ObjectName if the
     * MBean has been added as a relation in the Relation Service.
     *
     * @param objectName  ObjectName of supposed relation
     *
     * @return relation id (String) or null (if the ObjectName is not a
     * relation handled by the Relation Service)
     *
     * @exception IllegalArgumentException  if null parameter
     */
    public String isRelation(ObjectName objectName)
        throws IllegalArgumentException {

        if (objectName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "isRelation", objectName);

        String result = null;
        synchronized(myRelMBeanObjName2RelIdMap) {
            String relId = myRelMBeanObjName2RelIdMap.get(objectName);
            if (relId != null) {
                result = relId;
            }
        }
        return result;
    }

    /**
     * Checks if there is a relation identified in Relation Service with given
     * relation id.
     *
     * @param relationId  relation id identifying the relation
     *
     * @return boolean: true if there is a relation, false else
     *
     * @exception IllegalArgumentException  if null parameter
     */
    public Boolean hasRelation(String relationId)
        throws IllegalArgumentException {

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "hasRelation", relationId);

        try {
            // Can throw RelationNotFoundException
            Object result = getRelation(relationId);
            return true;
        } catch (RelationNotFoundException exc) {
            return false;
        }
    }

    /**
     * Returns all the relation ids for all the relations handled by the
     * Relation Service.
     *
     * @return ArrayList of String
     */
    public List<String> getAllRelationIds() {
        List<String> result = null;
        synchronized(myRelId2ObjMap) {
            result = new ArrayList<String>(myRelId2ObjMap.keySet());
        }
        return result;
    }

    /**
     * Checks if given Role can be read in a relation of the given type.
     *
     * @param roleName  name of role to be checked
     * @param relationTypeName  name of the relation type
     *
     * @return an Integer wrapping an integer corresponding to possible
     * problems represented as constants in RoleUnresolved:
     * <P>- 0 if role can be read
     * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME
     * <P>- integer corresponding to RoleStatus.ROLE_NOT_READABLE
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationTypeNotFoundException  if the relation type is not
     * known in the Relation Service
     */
    public Integer checkRoleReading(String roleName,
                                    String relationTypeName)
        throws IllegalArgumentException,
               RelationTypeNotFoundException {

        if (roleName == null || relationTypeName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "checkRoleReading", new Object[] {roleName, relationTypeName});

        Integer result = null;

        // Can throw a RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        try {
            // Can throw a RoleInfoNotFoundException to be transformed into
            // returned value RoleStatus.NO_ROLE_WITH_NAME
            RoleInfo roleInfo = relType.getRoleInfo(roleName);

            result =  checkRoleInt(1,
                                   roleName,
                                   null,
                                   roleInfo,
                                   false);

        } catch (RoleInfoNotFoundException exc) {
            result = new Integer(RoleStatus.NO_ROLE_WITH_NAME);
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "checkRoleReading");
        return result;
    }

    /**
     * Checks if given Role can be set in a relation of given type.
     *
     * @param role  role to be checked
     * @param relationTypeName  name of relation type
     * @param initFlag  flag to specify that the checking is done for the
     * initialization of a role, write access shall not be verified.
     *
     * @return an Integer wrapping an integer corresponding to possible
     * problems represented as constants in RoleUnresolved:
     * <P>- 0 if role can be set
     * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME
     * <P>- integer for RoleStatus.ROLE_NOT_WRITABLE
     * <P>- integer for RoleStatus.LESS_THAN_MIN_ROLE_DEGREE
     * <P>- integer for RoleStatus.MORE_THAN_MAX_ROLE_DEGREE
     * <P>- integer for RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS
     * <P>- integer for RoleStatus.REF_MBEAN_NOT_REGISTERED
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationTypeNotFoundException  if unknown relation type
     */
    public Integer checkRoleWriting(Role role,
                                    String relationTypeName,
                                    Boolean initFlag)
        throws IllegalArgumentException,
               RelationTypeNotFoundException {

        if (role == null ||
            relationTypeName == null ||
            initFlag == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "checkRoleWriting",
                new Object[] {role, relationTypeName, initFlag});

        // Can throw a RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        String roleName = role.getRoleName();
        List<ObjectName> roleValue = role.getRoleValue();
        boolean writeChkFlag = true;
        if (initFlag.booleanValue()) {
            writeChkFlag = false;
        }

        RoleInfo roleInfo = null;
        try {
            roleInfo = relType.getRoleInfo(roleName);
        } catch (RoleInfoNotFoundException exc) {
            RELATION_LOGGER.exiting(RelationService.class.getName(),
                    "checkRoleWriting");
            return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
        }

        Integer result = checkRoleInt(2,
                                      roleName,
                                      roleValue,
                                      roleInfo,
                                      writeChkFlag);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "checkRoleWriting");
        return result;
    }

    /**
     * Sends a notification (RelationNotification) for a relation creation.
     * The notification type is:
     * <P>- RelationNotification.RELATION_BASIC_CREATION if the relation is an
     * object internal to the Relation Service
     * <P>- RelationNotification.RELATION_MBEAN_CREATION if the relation is a
     * MBean added as a relation.
     * <P>The source object is the Relation Service itself.
     * <P>It is called in Relation Service createRelation() and
     * addRelation() methods.
     *
     * @param relationId  relation identifier of the updated relation
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if there is no relation for given
     * relation id
     */
    public void sendRelationCreationNotification(String relationId)
        throws IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "sendRelationCreationNotification", relationId);

        // Message
        StringBuilder ntfMsg = new StringBuilder("Creation of relation ");
        ntfMsg.append(relationId);

        // Can throw RelationNotFoundException
        sendNotificationInt(1,
                            ntfMsg.toString(),
                            relationId,
                            null,
                            null,
                            null,
                            null);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "sendRelationCreationNotification");
        return;
    }

    /**
     * Sends a notification (RelationNotification) for a role update in the
     * given relation. The notification type is:
     * <P>- RelationNotification.RELATION_BASIC_UPDATE if the relation is an
     * object internal to the Relation Service
     * <P>- RelationNotification.RELATION_MBEAN_UPDATE if the relation is a
     * MBean added as a relation.
     * <P>The source object is the Relation Service itself.
     * <P>It is called in relation MBean setRole() (for given role) and
     * setRoles() (for each role) methods (implementation provided in
     * RelationSupport class).
     * <P>It is also called in Relation Service setRole() (for given role) and
     * setRoles() (for each role) methods.
     *
     * @param relationId  relation identifier of the updated relation
     * @param newRole  new role (name and new value)
     * @param oldValue  old role value (List of ObjectName objects)
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if there is no relation for given
     * relation id
     */
    public void sendRoleUpdateNotification(String relationId,
                                           Role newRole,
                                           List<ObjectName> oldValue)
        throws IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null ||
            newRole == null ||
            oldValue == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        if (!(oldValue instanceof ArrayList))
            oldValue = new ArrayList<ObjectName>(oldValue);

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "sendRoleUpdateNotification",
                new Object[] {relationId, newRole, oldValue});

        String roleName = newRole.getRoleName();
        List<ObjectName> newRoleVal = newRole.getRoleValue();

        // Message
        String newRoleValString = Role.roleValueToString(newRoleVal);
        String oldRoleValString = Role.roleValueToString(oldValue);
        StringBuilder ntfMsg = new StringBuilder("Value of role ");
        ntfMsg.append(roleName);
        ntfMsg.append(" has changed\nOld value:\n");
        ntfMsg.append(oldRoleValString);
        ntfMsg.append("\nNew value:\n");
        ntfMsg.append(newRoleValString);

        // Can throw a RelationNotFoundException
        sendNotificationInt(2,
                            ntfMsg.toString(),
                            relationId,
                            null,
                            roleName,
                            newRoleVal,
                            oldValue);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "sendRoleUpdateNotification");
    }

    /**
     * Sends a notification (RelationNotification) for a relation removal.
     * The notification type is:
     * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation is an
     * object internal to the Relation Service
     * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is a
     * MBean added as a relation.
     * <P>The source object is the Relation Service itself.
     * <P>It is called in Relation Service removeRelation() method.
     *
     * @param relationId  relation identifier of the updated relation
     * @param unregMBeanList  List of ObjectNames of MBeans expected
     * to be unregistered due to relation removal (can be null)
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if there is no relation for given
     * relation id
     */
    public void sendRelationRemovalNotification(String relationId,
                                                List<ObjectName> unregMBeanList)
        throws IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null) {
            String excMsg = "Invalid parameter";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "sendRelationRemovalNotification",
                new Object[] {relationId, unregMBeanList});

        // Can throw RelationNotFoundException
        sendNotificationInt(3,
                            "Removal of relation " + relationId,
                            relationId,
                            unregMBeanList,
                            null,
                            null,
                            null);


        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "sendRelationRemovalNotification");
        return;
    }

    /**
     * Handles update of the Relation Service role map for the update of given
     * role in given relation.
     * <P>It is called in relation MBean setRole() (for given role) and
     * setRoles() (for each role) methods (implementation provided in
     * RelationSupport class).
     * <P>It is also called in Relation Service setRole() (for given role) and
     * setRoles() (for each role) methods.
     * <P>To allow the Relation Service to maintain the consistency (in case
     * of MBean unregistration) and to be able to perform queries, this method
     * must be called when a role is updated.
     *
     * @param relationId  relation identifier of the updated relation
     * @param newRole  new role (name and new value)
     * @param oldValue  old role value (List of ObjectName objects)
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception RelationNotFoundException  if no relation for given id.
     */
    public void updateRoleMap(String relationId,
                              Role newRole,
                              List<ObjectName> oldValue)
        throws IllegalArgumentException,
               RelationServiceNotRegisteredException,
               RelationNotFoundException {

        if (relationId == null ||
            newRole == null ||
            oldValue == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "updateRoleMap", new Object[] {relationId, newRole, oldValue});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Verifies the relation has been added in the Relation Service
        // Can throw a RelationNotFoundException
        Object result = getRelation(relationId);

        String roleName = newRole.getRoleName();
        List<ObjectName> newRoleValue = newRole.getRoleValue();
        // Note: no need to test if oldValue not null before cloning,
        //       tested above.
        List<ObjectName> oldRoleValue =
            new ArrayList<ObjectName>(oldValue);

        // List of ObjectNames of new referenced MBeans
        List<ObjectName> newRefList = new ArrayList<ObjectName>();

        for (ObjectName currObjName : newRoleValue) {

            // Checks if this ObjectName was already present in old value
            // Note: use copy (oldRoleValue) instead of original
            //       oldValue to speed up, as oldRoleValue is decreased
            //       by removing unchanged references :)
            int currObjNamePos = oldRoleValue.indexOf(currObjName);

            if (currObjNamePos == -1) {
                // New reference to an ObjectName

                // Stores this reference into map
                // Returns true if new reference, false if MBean already
                // referenced
                boolean isNewFlag = addNewMBeanReference(currObjName,
                                                        relationId,
                                                        roleName);

                if (isNewFlag) {
                    // Adds it into list of new reference
                    newRefList.add(currObjName);
                }

            } else {
                // MBean was already referenced in old value

                // Removes it from old value (local list) to ignore it when
                // looking for remove MBean references
                oldRoleValue.remove(currObjNamePos);
            }
        }

        // List of ObjectNames of MBeans no longer referenced
        List<ObjectName> obsRefList = new ArrayList<ObjectName>();

        // Each ObjectName remaining in oldRoleValue is an ObjectName no longer
        // referenced in new value
        for (ObjectName currObjName : oldRoleValue) {
            // Removes MBean reference from map
            // Returns true if the MBean is no longer referenced in any
            // relation
            boolean noLongerRefFlag = removeMBeanReference(currObjName,
                                                          relationId,
                                                          roleName,
                                                          false);

            if (noLongerRefFlag) {
                // Adds it into list of references to be removed
                obsRefList.add(currObjName);
            }
        }

        // To avoid having one listener per ObjectName of referenced MBean,
        // and to increase performances, there is only one listener recording
        // all ObjectNames of interest
        updateUnregistrationListener(newRefList, obsRefList);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "updateRoleMap");
        return;
    }

    /**
     * Removes given relation from the Relation Service.
     * <P>A RelationNotification notification is sent, its type being:
     * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation was
     * only internal to the Relation Service
     * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is
     * registered as an MBean.
     * <P>For MBeans referenced in such relation, nothing will be done,
     *
     * @param relationId  relation id of the relation to be removed
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation corresponding to
     * given relation id
     */
    public void removeRelation(String relationId)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RelationNotFoundException {

        // Can throw RelationServiceNotRegisteredException
        isActive();

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "removeRelation", relationId);

        // Checks there is a relation with this id
        // Can throw RelationNotFoundException
        Object result = getRelation(relationId);

        // Removes it from listener filter
        if (result instanceof ObjectName) {
            List<ObjectName> obsRefList = new ArrayList<ObjectName>();
            obsRefList.add((ObjectName)result);
            // Can throw a RelationServiceNotRegisteredException
            updateUnregistrationListener(null, obsRefList);
        }

        // Sends a notification
        // Note: has to be done FIRST as needs the relation to be still in the
        //       Relation Service
        // No RelationNotFoundException as checked above

        // Revisit [cebro] Handle CIM "Delete" and "IfDeleted" qualifiers:
        //   deleting the relation can mean to delete referenced MBeans. In
        //   that case, MBeans to be unregistered are put in a list sent along
        //   with the notification below

        // Can throw a RelationNotFoundException (but detected above)
        sendRelationRemovalNotification(relationId, null);

        // Removes the relation from various internal maps

        //  - MBean reference map
        // Retrieves the MBeans referenced in this relation
        // Note: here we cannot use removeMBeanReference() because it would
        //       require to know the MBeans referenced in the relation. For
        //       that it would be necessary to call 'getReferencedMBeans()'
        //       on the relation itself. Ok if it is an internal one, but if
        //       it is an MBean, it is possible it is already unregistered, so
        //       not available through the MBean Server.
        List<ObjectName> refMBeanList = new ArrayList<ObjectName>();
        // List of MBeans no longer referenced in any relation, to be
        // removed fom the map
        List<ObjectName> nonRefObjNameList = new ArrayList<ObjectName>();

        synchronized(myRefedMBeanObjName2RelIdsMap) {

            for (ObjectName currRefObjName :
                     myRefedMBeanObjName2RelIdsMap.keySet()) {

                // Retrieves relations where the MBean is referenced
                Map<String,List<String>> relIdMap =
                    myRefedMBeanObjName2RelIdsMap.get(currRefObjName);

                if (relIdMap.containsKey(relationId)) {
                    relIdMap.remove(relationId);
                    refMBeanList.add(currRefObjName);
                }

                if (relIdMap.isEmpty()) {
                    // MBean no longer referenced
                    // Note: do not remove it here because pointed by the
                    //       iterator!
                    nonRefObjNameList.add(currRefObjName);
                }
            }

            // Cleans MBean reference map by removing MBeans no longer
            // referenced
            for (ObjectName currRefObjName : nonRefObjNameList) {
                myRefedMBeanObjName2RelIdsMap.remove(currRefObjName);
            }
        }

        // - Relation id to object map
        synchronized(myRelId2ObjMap) {
            myRelId2ObjMap.remove(relationId);
        }

        if (result instanceof ObjectName) {
            // - ObjectName to relation id map
            synchronized(myRelMBeanObjName2RelIdMap) {
                myRelMBeanObjName2RelIdMap.remove((ObjectName)result);
            }
        }

        // Relation id to relation type name map
        // First retrieves the relation type name
        String relTypeName = null;
        synchronized(myRelId2RelTypeMap) {
            relTypeName = myRelId2RelTypeMap.get(relationId);
            myRelId2RelTypeMap.remove(relationId);
        }
        // - Relation type name to relation id map
        synchronized(myRelType2RelIdsMap) {
            List<String> relIdList = myRelType2RelIdsMap.get(relTypeName);
            if (relIdList != null) {
                // Can be null if called from removeRelationType()
                relIdList.remove(relationId);
                if (relIdList.isEmpty()) {
                    // No other relation of that type
                    myRelType2RelIdsMap.remove(relTypeName);
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "removeRelation");
        return;
    }

    /**
     * Purges the relations.
     *
     * <P>Depending on the purgeFlag value, this method is either called
     * automatically when a notification is received for the unregistration of
     * an MBean referenced in a relation (if the flag is set to true), or not
     * (if the flag is set to false).
     * <P>In that case it is up to the user to call it to maintain the
     * consistency of the relations. To be kept in mind that if an MBean is
     * unregistered and the purge not done immediately, if the ObjectName is
     * reused and assigned to another MBean referenced in a relation, calling
     * manually this purgeRelations() method will cause trouble, as will
     * consider the ObjectName as corresponding to the unregistered MBean, not
     * seeing the new one.
     *
     * <P>The behavior depends on the cardinality of the role where the
     * unregistered MBean is referenced:
     * <P>- if removing one MBean reference in the role makes its number of
     * references less than the minimum degree, the relation has to be removed.
     * <P>- if the remaining number of references after removing the MBean
     * reference is still in the cardinality range, keep the relation and
     * update it calling its handleMBeanUnregistration() callback.
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server.
     */
    public void purgeRelations()
        throws RelationServiceNotRegisteredException {

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "purgeRelations");

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Revisit [cebro] Handle the CIM "Delete" and "IfDeleted" qualifier:
        //    if the unregistered MBean has the "IfDeleted" qualifier,
        //    possible that the relation itself or other referenced MBeans
        //    have to be removed (then a notification would have to be sent
        //    to inform that they should be unregistered.


        // Clones the list of notifications to be able to still receive new
        // notifications while proceeding those ones
        List<MBeanServerNotification> localUnregNtfList;
        synchronized(myUnregNtfList) {
            localUnregNtfList =
                new ArrayList<MBeanServerNotification>(myUnregNtfList);
            // Resets list
            myUnregNtfList = new ArrayList<MBeanServerNotification>();
        }


        // Updates the listener filter to avoid receiving notifications for
        // those MBeans again
        // Makes also a local "myRefedMBeanObjName2RelIdsMap" map, mapping
        // ObjectName -> relId -> roles, to remove the MBean from the global
        // map
        // List of references to be removed from the listener filter
        List<ObjectName> obsRefList = new ArrayList<ObjectName>();
        // Map including ObjectNames for unregistered MBeans, with
        // referencing relation ids and roles
        Map<ObjectName,Map<String,List<String>>> localMBean2RelIdMap =
            new HashMap<ObjectName,Map<String,List<String>>>();

        synchronized(myRefedMBeanObjName2RelIdsMap) {
            for (MBeanServerNotification currNtf : localUnregNtfList) {

                ObjectName unregMBeanName = currNtf.getMBeanName();

                // Adds the unregsitered MBean in the list of references to
                // remove from the listener filter
                obsRefList.add(unregMBeanName);

                // Retrieves the associated map of relation ids and roles
                Map<String,List<String>> relIdMap =
                    myRefedMBeanObjName2RelIdsMap.get(unregMBeanName);
                localMBean2RelIdMap.put(unregMBeanName, relIdMap);

                myRefedMBeanObjName2RelIdsMap.remove(unregMBeanName);
            }
        }

        // Updates the listener
        // Can throw RelationServiceNotRegisteredException
        updateUnregistrationListener(null, obsRefList);

        for (MBeanServerNotification currNtf : localUnregNtfList) {

            ObjectName unregMBeanName = currNtf.getMBeanName();

            // Retrieves the relations where the MBean is referenced
            Map<String,List<String>> localRelIdMap =
                    localMBean2RelIdMap.get(unregMBeanName);

            // List of relation ids where the unregistered MBean is
            // referenced
            for (Map.Entry<String,List<String>> currRel :
                        localRelIdMap.entrySet()) {
                final String currRelId = currRel.getKey();
                // List of roles of the relation where the MBean is
                // referenced
                List<String> localRoleNameList = currRel.getValue();

                // Checks if the relation has to be removed or not,
                // regarding expected minimum role cardinality and current
                // number of references after removal of the current one
                // If the relation is kept, calls
                // handleMBeanUnregistration() callback of the relation to
                // update it
                //
                // Can throw RelationServiceNotRegisteredException
                //
                // Shall not throw RelationNotFoundException,
                // RoleNotFoundException, MBeanException
                try {
                    handleReferenceUnregistration(currRelId,
                                                  unregMBeanName,
                                                  localRoleNameList);
                } catch (RelationNotFoundException exc1) {
                    throw new RuntimeException(exc1.getMessage());
                } catch (RoleNotFoundException exc2) {
                    throw new RuntimeException(exc2.getMessage());
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "purgeRelations");
        return;
    }

    /**
     * Retrieves the relations where a given MBean is referenced.
     * <P>This corresponds to the CIM "References" and "ReferenceNames"
     * operations.
     *
     * @param mbeanName  ObjectName of MBean
     * @param relationTypeName  can be null; if specified, only the relations
     * of that type will be considered in the search. Else all relation types
     * are considered.
     * @param roleName  can be null; if specified, only the relations
     * where the MBean is referenced in that role will be returned. Else all
     * roles are considered.
     *
     * @return an HashMap, where the keys are the relation ids of the relations
     * where the MBean is referenced, and the value is, for each key,
     * an ArrayList of role names (as an MBean can be referenced in several
     * roles in the same relation).
     *
     * @exception IllegalArgumentException  if null parameter
     */
    public Map<String,List<String>>
        findReferencingRelations(ObjectName mbeanName,
                                 String relationTypeName,
                                 String roleName)
            throws IllegalArgumentException {

        if (mbeanName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "findReferencingRelations",
                new Object[] {mbeanName, relationTypeName, roleName});

        Map<String,List<String>> result = new HashMap<String,List<String>>();

        synchronized(myRefedMBeanObjName2RelIdsMap) {

            // Retrieves the relations referencing the MBean
            Map<String,List<String>> relId2RoleNamesMap =
                myRefedMBeanObjName2RelIdsMap.get(mbeanName);

            if (relId2RoleNamesMap != null) {

                // Relation Ids where the MBean is referenced
                Set<String> allRelIdSet = relId2RoleNamesMap.keySet();

                // List of relation ids of interest regarding the selected
                // relation type
                List<String> relIdList = null;
                if (relationTypeName == null) {
                    // Considers all relations
                    relIdList = new ArrayList<String>(allRelIdSet);

                } else {

                    relIdList = new ArrayList<String>();

                    // Considers only the relation ids for relations of given
                    // type
                    for (String currRelId : allRelIdSet) {

                        // Retrieves its relation type
                        String currRelTypeName = null;
                        synchronized(myRelId2RelTypeMap) {
                            currRelTypeName =
                                myRelId2RelTypeMap.get(currRelId);
                        }

                        if (currRelTypeName.equals(relationTypeName)) {

                            relIdList.add(currRelId);

                        }
                    }
                }

                // Now looks at the roles where the MBean is expected to be
                // referenced

                for (String currRelId : relIdList) {
                    // Retrieves list of role names where the MBean is
                    // referenced
                    List<String> currRoleNameList =
                        relId2RoleNamesMap.get(currRelId);

                    if (roleName == null) {
                        // All roles to be considered
                        // Note: no need to test if list not null before
                        //       cloning, MUST be not null else bug :(
                        result.put(currRelId,
                                   new ArrayList<String>(currRoleNameList));

                    }  else if (currRoleNameList.contains(roleName)) {
                        // Filters only the relations where the MBean is
                        // referenced in // given role
                        List<String> dummyList = new ArrayList<String>();
                        dummyList.add(roleName);
                        result.put(currRelId, dummyList);
                    }
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "findReferencingRelations");
        return result;
    }

    /**
     * Retrieves the MBeans associated to given one in a relation.
     * <P>This corresponds to CIM Associators and AssociatorNames operations.
     *
     * @param mbeanName  ObjectName of MBean
     * @param relationTypeName  can be null; if specified, only the relations
     * of that type will be considered in the search. Else all
     * relation types are considered.
     * @param roleName  can be null; if specified, only the relations
     * where the MBean is referenced in that role will be considered. Else all
     * roles are considered.
     *
     * @return an HashMap, where the keys are the ObjectNames of the MBeans
     * associated to given MBean, and the value is, for each key, an ArrayList
     * of the relation ids of the relations where the key MBean is
     * associated to given one (as they can be associated in several different
     * relations).
     *
     * @exception IllegalArgumentException  if null parameter
     */
    public Map<ObjectName,List<String>>
        findAssociatedMBeans(ObjectName mbeanName,
                             String relationTypeName,
                             String roleName)
            throws IllegalArgumentException {

        if (mbeanName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "findAssociatedMBeans",
                new Object[] {mbeanName, relationTypeName, roleName});

        // Retrieves the map <relation id> -> <role names> for those
        // criterias
        Map<String,List<String>> relId2RoleNamesMap =
            findReferencingRelations(mbeanName,
                                     relationTypeName,
                                     roleName);

        Map<ObjectName,List<String>> result =
            new HashMap<ObjectName,List<String>>();

        for (String currRelId : relId2RoleNamesMap.keySet()) {

            // Retrieves ObjectNames of MBeans referenced in this relation
            //
            // Shall not throw a RelationNotFoundException if incorrect status
            // of maps :(
            Map<ObjectName,List<String>> objName2RoleNamesMap;
            try {
                objName2RoleNamesMap = getReferencedMBeans(currRelId);
            } catch (RelationNotFoundException exc) {
                throw new RuntimeException(exc.getMessage());
            }

            // For each MBean associated to given one in a relation, adds the
            // association <ObjectName> -> <relation id> into result map
            for (ObjectName currObjName : objName2RoleNamesMap.keySet()) {

                if (!(currObjName.equals(mbeanName))) {

                    // Sees if this MBean is already associated to the given
                    // one in another relation
                    List<String> currRelIdList = result.get(currObjName);
                    if (currRelIdList == null) {

                        currRelIdList = new ArrayList<String>();
                        currRelIdList.add(currRelId);
                        result.put(currObjName, currRelIdList);

                    } else {
                        currRelIdList.add(currRelId);
                    }
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "findAssociatedMBeans");
        return result;
    }

    /**
     * Returns the relation ids for relations of the given type.
     *
     * @param relationTypeName  relation type name
     *
     * @return an ArrayList of relation ids.
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationTypeNotFoundException  if there is no relation type
     * with that name.
     */
    public List<String> findRelationsOfType(String relationTypeName)
        throws IllegalArgumentException,
               RelationTypeNotFoundException {

        if (relationTypeName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "findRelationsOfType");

        // Can throw RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        List<String> result;
        synchronized(myRelType2RelIdsMap) {
            List<String> result1 = myRelType2RelIdsMap.get(relationTypeName);
            if (result1 == null)
                result = new ArrayList<String>();
            else
                result = new ArrayList<String>(result1);
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "findRelationsOfType");
        return result;
    }

    /**
     * Retrieves role value for given role name in given relation.
     *
     * @param relationId  relation id
     * @param roleName  name of role
     *
     * @return the ArrayList of ObjectName objects being the role value
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation with given id
     * @exception RoleNotFoundException  if:
     * <P>- there is no role with given name
     * <P>or
     * <P>- the role is not readable.
     *
     * @see #setRole
     */
    public List<ObjectName> getRole(String relationId,
                                    String roleName)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RelationNotFoundException,
               RoleNotFoundException {

        if (relationId == null || roleName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRole", new Object[] {relationId, roleName});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        List<ObjectName> result;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            // Can throw RoleNotFoundException
            result = cast(
                ((RelationSupport)relObj).getRoleInt(roleName,
                                                     true,
                                                     this,
                                                     false));

        } else {
            // Relation MBean
            Object[] params = new Object[1];
            params[0] = roleName;
            String[] signature = new String[1];
            signature[0] = "java.lang.String";
            // Can throw MBeanException wrapping a RoleNotFoundException:
            // throw wrapped exception
            //
            // Shall not throw InstanceNotFoundException or ReflectionException
            try {
                List<ObjectName> invokeResult = cast(
                    myMBeanServer.invoke(((ObjectName)relObj),
                                         "getRole",
                                         params,
                                         signature));
                if (invokeResult == null || invokeResult instanceof ArrayList)
                    result = invokeResult;
                else
                    result = new ArrayList<ObjectName>(invokeResult);
            } catch (InstanceNotFoundException exc1) {
                throw new RuntimeException(exc1.getMessage());
            } catch (ReflectionException exc2) {
                throw new RuntimeException(exc2.getMessage());
            } catch (MBeanException exc3) {
                Exception wrappedExc = exc3.getTargetException();
                if (wrappedExc instanceof RoleNotFoundException) {
                    throw ((RoleNotFoundException)wrappedExc);
                } else {
                    throw new RuntimeException(wrappedExc.getMessage());
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(), "getRole");
        return result;
    }

    /**
     * Retrieves values of roles with given names in given relation.
     *
     * @param relationId  relation id
     * @param roleNameArray  array of names of roles to be retrieved
     *
     * @return a RoleResult object, including a RoleList (for roles
     * successfully retrieved) and a RoleUnresolvedList (for roles not
     * retrieved).
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation with given id
     *
     * @see #setRoles
     */
    public RoleResult getRoles(String relationId,
                               String[] roleNameArray)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null || roleNameArray == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRoles", relationId);

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        RoleResult result = null;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            result = ((RelationSupport)relObj).getRolesInt(roleNameArray,
                                                        true,
                                                        this);
        } else {
            // Relation MBean
            Object[] params = new Object[1];
            params[0] = roleNameArray;
            String[] signature = new String[1];
            try {
                signature[0] = (roleNameArray.getClass()).getName();
            } catch (Exception exc) {
                // OK : This is an array of java.lang.String
                //      so this should never happen...
            }
            // Shall not throw InstanceNotFoundException, ReflectionException
            // or MBeanException
            try {
                result = (RoleResult)
                    (myMBeanServer.invoke(((ObjectName)relObj),
                                          "getRoles",
                                          params,
                                          signature));
            } catch (InstanceNotFoundException exc1) {
                throw new RuntimeException(exc1.getMessage());
            } catch (ReflectionException exc2) {
                throw new RuntimeException(exc2.getMessage());
            } catch (MBeanException exc3) {
                throw new
                    RuntimeException((exc3.getTargetException()).getMessage());
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles");
        return result;
    }

    /**
     * Returns all roles present in the relation.
     *
     * @param relationId  relation id
     *
     * @return a RoleResult object, including a RoleList (for roles
     * successfully retrieved) and a RoleUnresolvedList (for roles not
     * readable).
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation for given id
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     */
    public RoleResult getAllRoles(String relationId)
        throws IllegalArgumentException,
               RelationNotFoundException,
               RelationServiceNotRegisteredException {

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRoles", relationId);

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        RoleResult result = null;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            result = ((RelationSupport)relObj).getAllRolesInt(true, this);

        } else {
            // Relation MBean
            // Shall not throw any Exception
            try {
                result = (RoleResult)
                    (myMBeanServer.getAttribute(((ObjectName)relObj),
                                                "AllRoles"));
            } catch (Exception exc) {
                throw new RuntimeException(exc.getMessage());
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles");
        return result;
    }

    /**
     * Retrieves the number of MBeans currently referenced in the given role.
     *
     * @param relationId  relation id
     * @param roleName  name of role
     *
     * @return the number of currently referenced MBeans in that role
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation with given id
     * @exception RoleNotFoundException  if there is no role with given name
     */
    public Integer getRoleCardinality(String relationId,
                                      String roleName)
        throws IllegalArgumentException,
               RelationNotFoundException,
               RoleNotFoundException {

        if (relationId == null || roleName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRoleCardinality", new Object[] {relationId, roleName});

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        Integer result = null;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            // Can throw RoleNotFoundException
            result = ((RelationSupport)relObj).getRoleCardinality(roleName);

        } else {
            // Relation MBean
            Object[] params = new Object[1];
            params[0] = roleName;
            String[] signature = new String[1];
            signature[0] = "java.lang.String";
            // Can throw MBeanException wrapping RoleNotFoundException:
            // throw wrapped exception
            //
            // Shall not throw InstanceNotFoundException or ReflectionException
            try {
                result = (Integer)
                    (myMBeanServer.invoke(((ObjectName)relObj),
                                          "getRoleCardinality",
                                          params,
                                          signature));
            } catch (InstanceNotFoundException exc1) {
                throw new RuntimeException(exc1.getMessage());
            } catch (ReflectionException exc2) {
                throw new RuntimeException(exc2.getMessage());
            } catch (MBeanException exc3) {
                Exception wrappedExc = exc3.getTargetException();
                if (wrappedExc instanceof RoleNotFoundException) {
                    throw ((RoleNotFoundException)wrappedExc);
                } else {
                    throw new RuntimeException(wrappedExc.getMessage());
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getRoleCardinality");
        return result;
    }

    /**
     * Sets the given role in given relation.
     * <P>Will check the role according to its corresponding role definition
     * provided in relation's relation type
     * <P>The Relation Service will keep track of the change to keep the
     * consistency of relations by handling referenced MBean unregistrations.
     *
     * @param relationId  relation id
     * @param role  role to be set (name and new value)
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation with given id
     * @exception RoleNotFoundException  if the role does not exist or is not
     * writable
     * @exception InvalidRoleValueException  if value provided for role is not
     * valid:
     * <P>- the number of referenced MBeans in given value is less than
     * expected minimum degree
     * <P>or
     * <P>- the number of referenced MBeans in provided value exceeds expected
     * maximum degree
     * <P>or
     * <P>- one referenced MBean in the value is not an Object of the MBean
     * class expected for that role
     * <P>or
     * <P>- an MBean provided for that role does not exist
     *
     * @see #getRole
     */
    public void setRole(String relationId,
                        Role role)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RelationNotFoundException,
               RoleNotFoundException,
               InvalidRoleValueException {

        if (relationId == null || role == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "setRole", new Object[] {relationId, role});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        if (relObj instanceof RelationSupport) {
            // Internal relation
            // Can throw RoleNotFoundException,
            // InvalidRoleValueException and
            // RelationServiceNotRegisteredException
            //
            // Shall not throw RelationTypeNotFoundException
            // (as relation exists in the RS, its relation type is known)
            try {
                ((RelationSupport)relObj).setRoleInt(role,
                                                  true,
                                                  this,
                                                  false);

            } catch (RelationTypeNotFoundException exc) {
                throw new RuntimeException(exc.getMessage());
            }

        } else {
            // Relation MBean
            Object[] params = new Object[1];
            params[0] = role;
            String[] signature = new String[1];
            signature[0] = "javax.management.relation.Role";
            // Can throw MBeanException wrapping RoleNotFoundException,
            // InvalidRoleValueException
            //
            // Shall not MBeanException wrapping an MBeanException wrapping
            // RelationTypeNotFoundException, or ReflectionException, or
            // InstanceNotFoundException
            try {
                myMBeanServer.setAttribute(((ObjectName)relObj),
                                           new Attribute("Role", role));

            } catch (InstanceNotFoundException exc1) {
                throw new RuntimeException(exc1.getMessage());
            } catch (ReflectionException exc3) {
                throw new RuntimeException(exc3.getMessage());
            } catch (MBeanException exc2) {
                Exception wrappedExc = exc2.getTargetException();
                if (wrappedExc instanceof RoleNotFoundException) {
                    throw ((RoleNotFoundException)wrappedExc);
                } else if (wrappedExc instanceof InvalidRoleValueException) {
                    throw ((InvalidRoleValueException)wrappedExc);
                } else {
                    throw new RuntimeException(wrappedExc.getMessage());

                }
            } catch (AttributeNotFoundException exc4) {
              throw new RuntimeException(exc4.getMessage());
            } catch (InvalidAttributeValueException exc5) {
              throw new RuntimeException(exc5.getMessage());
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(), "setRole");
        return;
    }

    /**
     * Sets the given roles in given relation.
     * <P>Will check the role according to its corresponding role definition
     * provided in relation's relation type
     * <P>The Relation Service keeps track of the changes to keep the
     * consistency of relations by handling referenced MBean unregistrations.
     *
     * @param relationId  relation id
     * @param roleList  list of roles to be set
     *
     * @return a RoleResult object, including a RoleList (for roles
     * successfully set) and a RoleUnresolvedList (for roles not
     * set).
     *
     * @exception RelationServiceNotRegisteredException  if the Relation
     * Service is not registered in the MBean Server
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation with given id
     *
     * @see #getRoles
     */
    public RoleResult setRoles(String relationId,
                               RoleList roleList)
        throws RelationServiceNotRegisteredException,
               IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null || roleList == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "setRoles", new Object[] {relationId, roleList});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        RoleResult result = null;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            // Can throw RelationServiceNotRegisteredException
            //
            // Shall not throw RelationTypeNotFoundException (as relation is
            // known, its relation type exists)
            try {
                result = ((RelationSupport)relObj).setRolesInt(roleList,
                                                            true,
                                                            this);
            } catch (RelationTypeNotFoundException exc) {
                throw new RuntimeException(exc.getMessage());
            }

        } else {
            // Relation MBean
            Object[] params = new Object[1];
            params[0] = roleList;
            String[] signature = new String[1];
            signature[0] = "javax.management.relation.RoleList";
            // Shall not throw InstanceNotFoundException or an MBeanException
            // or ReflectionException
            try {
                result = (RoleResult)
                    (myMBeanServer.invoke(((ObjectName)relObj),
                                          "setRoles",
                                          params,
                                          signature));
            } catch (InstanceNotFoundException exc1) {
                throw new RuntimeException(exc1.getMessage());
            } catch (ReflectionException exc3) {
                throw new RuntimeException(exc3.getMessage());
            } catch (MBeanException exc2) {
                throw new
                    RuntimeException((exc2.getTargetException()).getMessage());
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(), "setRoles");
        return result;
    }

    /**
     * Retrieves MBeans referenced in the various roles of the relation.
     *
     * @param relationId  relation id
     *
     * @return a HashMap mapping:
     * <P> ObjectName -> ArrayList of String (role
     * names)
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation for given
     * relation id
     */
    public Map<ObjectName,List<String>>
        getReferencedMBeans(String relationId)
            throws IllegalArgumentException,
        RelationNotFoundException {

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getReferencedMBeans", relationId);

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        Map<ObjectName,List<String>> result;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            result = ((RelationSupport)relObj).getReferencedMBeans();

        } else {
            // Relation MBean
            // No Exception
            try {
                result = cast(
                    myMBeanServer.getAttribute(((ObjectName)relObj),
                                               "ReferencedMBeans"));
            } catch (Exception exc) {
                throw new RuntimeException(exc.getMessage());
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getReferencedMBeans");
        return result;
    }

    /**
     * Returns name of associated relation type for given relation.
     *
     * @param relationId  relation id
     *
     * @return the name of the associated relation type.
     *
     * @exception IllegalArgumentException  if null parameter
     * @exception RelationNotFoundException  if no relation for given
     * relation id
     */
    public String getRelationTypeName(String relationId)
        throws IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRelationTypeName", relationId);

        // Can throw a RelationNotFoundException
        Object relObj = getRelation(relationId);

        String result = null;

        if (relObj instanceof RelationSupport) {
            // Internal relation
            result = ((RelationSupport)relObj).getRelationTypeName();

        } else {
            // Relation MBean
            // No Exception
            try {
                result = (String)
                    (myMBeanServer.getAttribute(((ObjectName)relObj),
                                                "RelationTypeName"));
            } catch (Exception exc) {
                throw new RuntimeException(exc.getMessage());
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getRelationTypeName");
        return result;
    }

    //
    // NotificationListener Interface
    //

    /**
     * Invoked when a JMX notification occurs.
     * Currently handles notifications for unregistration of MBeans, either
     * referenced in a relation role or being a relation itself.
     *
     * @param notif  The notification.
     * @param handback  An opaque object which helps the listener to
     * associate information regarding the MBean emitter (can be null).
     */
    public void handleNotification(Notification notif,
                                   Object handback) {

        if (notif == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "handleNotification", notif);

        if (notif instanceof MBeanServerNotification) {

            MBeanServerNotification mbsNtf = (MBeanServerNotification) notif;
            String ntfType = notif.getType();

            if (ntfType.equals(
                       MBeanServerNotification.UNREGISTRATION_NOTIFICATION )) {
                ObjectName mbeanName =
                    ((MBeanServerNotification)notif).getMBeanName();

                // Note: use a flag to block access to
                // myRefedMBeanObjName2RelIdsMap only for a quick access
                boolean isRefedMBeanFlag = false;
                synchronized(myRefedMBeanObjName2RelIdsMap) {

                    if (myRefedMBeanObjName2RelIdsMap.containsKey(mbeanName)) {
                        // Unregistration of a referenced MBean
                        synchronized(myUnregNtfList) {
                            myUnregNtfList.add(mbsNtf);
                        }
                        isRefedMBeanFlag = true;
                    }
                    if (isRefedMBeanFlag && myPurgeFlag) {
                        // Immediate purge
                        // Can throw RelationServiceNotRegisteredException
                        // but assume that will be fine :)
                        try {
                            purgeRelations();
                        } catch (Exception exc) {
                            throw new RuntimeException(exc.getMessage());
                        }
                    }
                }

                // Note: do both tests as a relation can be an MBean and be
                //       itself referenced in another relation :)
                String relId = null;
                synchronized(myRelMBeanObjName2RelIdMap){
                    relId = myRelMBeanObjName2RelIdMap.get(mbeanName);
                }
                if (relId != null) {
                    // Unregistration of a relation MBean
                    // Can throw RelationTypeNotFoundException,
                    // RelationServiceNotRegisteredException
                    //
                    // Shall not throw RelationTypeNotFoundException or
                    // InstanceNotFoundException
                    try {
                        removeRelation(relId);
                    } catch (Exception exc) {
                        throw new RuntimeException(exc.getMessage());
                    }
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "handleNotification");
        return;
    }

    //
    // NotificationBroadcaster interface
    //

    /**
     * Returns a NotificationInfo object containing the name of the Java class
     * of the notification and the notification types sent.
     */
    public MBeanNotificationInfo[] getNotificationInfo() {

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getNotificationInfo");

        MBeanNotificationInfo[] ntfInfoArray =
            new MBeanNotificationInfo[1];

        String ntfClass = "javax.management.relation.RelationNotification";

        String[] ntfTypes = new String[] {
            RelationNotification.RELATION_BASIC_CREATION,
            RelationNotification.RELATION_MBEAN_CREATION,
            RelationNotification.RELATION_BASIC_UPDATE,
            RelationNotification.RELATION_MBEAN_UPDATE,
            RelationNotification.RELATION_BASIC_REMOVAL,
            RelationNotification.RELATION_MBEAN_REMOVAL,
        };

        String ntfDesc = "Sent when a relation is created, updated or deleted.";

        MBeanNotificationInfo ntfInfo =
            new MBeanNotificationInfo(ntfTypes, ntfClass, ntfDesc);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getNotificationInfo");
        return new MBeanNotificationInfo[] {ntfInfo};
    }

    //
    // Misc
    //

    // Adds given object as a relation type.
    //
    // -param relationTypeObj  relation type object
    //
    // -exception IllegalArgumentException  if null parameter
    // -exception InvalidRelationTypeException  if there is already a relation
    //  type with that name
    private void addRelationTypeInt(RelationType relationTypeObj)
        throws IllegalArgumentException,
               InvalidRelationTypeException {

        if (relationTypeObj == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "addRelationTypeInt");

        String relTypeName = relationTypeObj.getRelationTypeName();

        // Checks that there is not already a relation type with that name
        // existing in the Relation Service
        try {
            // Can throw a RelationTypeNotFoundException (in fact should ;)
            RelationType relType = getRelationType(relTypeName);

            if (relType != null) {
                String excMsg = "There is already a relation type in the Relation Service with name ";
                StringBuilder excMsgStrB = new StringBuilder(excMsg);
                excMsgStrB.append(relTypeName);
                throw new InvalidRelationTypeException(excMsgStrB.toString());
            }

        } catch (RelationTypeNotFoundException exc) {
            // OK : The RelationType could not be found.
        }

        // Adds the relation type
        synchronized(myRelType2ObjMap) {
            myRelType2ObjMap.put(relTypeName, relationTypeObj);
        }

        if (relationTypeObj instanceof RelationTypeSupport) {
            ((RelationTypeSupport)relationTypeObj).setRelationServiceFlag(true);
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "addRelationTypeInt");
        return;
     }

    // Retrieves relation type with given name
    //
    // -param relationTypeName  expected name of a relation type created in the
    //  Relation Service
    //
    // -return RelationType object corresponding to given name
    //
    // -exception IllegalArgumentException  if null parameter
    // -exception RelationTypeNotFoundException  if no relation type for that
    //  name created in Relation Service
    //
    RelationType getRelationType(String relationTypeName)
        throws IllegalArgumentException,
               RelationTypeNotFoundException {

        if (relationTypeName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRelationType", relationTypeName);

        // No null relation type accepted, so can use get()
        RelationType relType = null;
        synchronized(myRelType2ObjMap) {
            relType = (myRelType2ObjMap.get(relationTypeName));
        }

        if (relType == null) {
            String excMsg = "No relation type created in the Relation Service with the name ";
            StringBuilder excMsgStrB = new StringBuilder(excMsg);
            excMsgStrB.append(relationTypeName);
            throw new RelationTypeNotFoundException(excMsgStrB.toString());
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getRelationType");
        return relType;
    }

    // Retrieves relation corresponding to given relation id.
    // Returns either:
    // - a RelationSupport object if the relation is internal
    // or
    // - the ObjectName of the corresponding MBean
    //
    // -param relationId  expected relation id
    //
    // -return RelationSupport object or ObjectName of relation with given id
    //
    // -exception IllegalArgumentException  if null parameter
    // -exception RelationNotFoundException  if no relation for that
    //  relation id created in Relation Service
    //
    Object getRelation(String relationId)
        throws IllegalArgumentException,
               RelationNotFoundException {

        if (relationId == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "getRelation", relationId);

        // No null relation  accepted, so can use get()
        Object rel = null;
        synchronized(myRelId2ObjMap) {
            rel = myRelId2ObjMap.get(relationId);
        }

        if (rel == null) {
            String excMsg = "No relation associated to relation id " + relationId;
            throw new RelationNotFoundException(excMsg);
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "getRelation");
        return rel;
    }

    // Adds a new MBean reference (reference to an ObjectName) in the
    // referenced MBean map (myRefedMBeanObjName2RelIdsMap).
    //
    // -param objectName  ObjectName of new referenced MBean
    // -param relationId  relation id of the relation where the MBean is
    //  referenced
    // -param roleName  name of the role where the MBean is referenced
    //
    // -return boolean:
    //  - true  if the MBean was not referenced before, so really a new
    //    reference
    //  - false else
    //
    // -exception IllegalArgumentException  if null parameter
    private boolean addNewMBeanReference(ObjectName objectName,
                                         String relationId,
                                         String roleName)
        throws IllegalArgumentException {

        if (objectName == null ||
            relationId == null ||
            roleName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "addNewMBeanReference",
                new Object[] {objectName, relationId, roleName});

        boolean isNewFlag = false;

        synchronized(myRefedMBeanObjName2RelIdsMap) {

            // Checks if the MBean was already referenced
            // No null value allowed, use get() directly
            Map<String,List<String>> mbeanRefMap =
                myRefedMBeanObjName2RelIdsMap.get(objectName);

            if (mbeanRefMap == null) {
                // MBean not referenced in any relation yet

                isNewFlag = true;

                // List of roles where the MBean is referenced in given
                // relation
                List<String> roleNames = new ArrayList<String>();
                roleNames.add(roleName);

                // Map of relations where the MBean is referenced
                mbeanRefMap = new HashMap<String,List<String>>();
                mbeanRefMap.put(relationId, roleNames);

                myRefedMBeanObjName2RelIdsMap.put(objectName, mbeanRefMap);

            } else {
                // MBean already referenced in at least another relation
                // Checks if already referenced in another role in current
                // relation
                List<String> roleNames = mbeanRefMap.get(relationId);

                if (roleNames == null) {
                    // MBean not referenced in current relation

                    // List of roles where the MBean is referenced in given
                    // relation
                    roleNames = new ArrayList<String>();
                    roleNames.add(roleName);

                    // Adds new reference done in current relation
                    mbeanRefMap.put(relationId, roleNames);

                } else {
                    // MBean already referenced in current relation in another
                    // role
                    // Adds new reference done
                    roleNames.add(roleName);
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "addNewMBeanReference");
        return isNewFlag;
    }

    // Removes an obsolete MBean reference (reference to an ObjectName) in
    // the referenced MBean map (myRefedMBeanObjName2RelIdsMap).
    //
    // -param objectName  ObjectName of MBean no longer referenced
    // -param relationId  relation id of the relation where the MBean was
    //  referenced
    // -param roleName  name of the role where the MBean was referenced
    // -param allRolesFlag  flag, if true removes reference to MBean for all
    //  roles in the relation, not only for the one above
    //
    // -return boolean:
    //  - true  if the MBean is no longer reference in any relation
    //  - false else
    //
    // -exception IllegalArgumentException  if null parameter
    private boolean removeMBeanReference(ObjectName objectName,
                                         String relationId,
                                         String roleName,
                                         boolean allRolesFlag)
        throws IllegalArgumentException {

        if (objectName == null ||
            relationId == null ||
            roleName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "removeMBeanReference",
                new Object[] {objectName, relationId, roleName, allRolesFlag});

        boolean noLongerRefFlag = false;

        synchronized(myRefedMBeanObjName2RelIdsMap) {

            // Retrieves the set of relations (designed via their relation ids)
            // where the MBean is referenced
            // Note that it is possible that the MBean has already been removed
            // from the internal map: this is the case when the MBean is
            // unregistered, the role is updated, then we arrive here.
            HashMap mbeanRefMap = (HashMap)
                (myRefedMBeanObjName2RelIdsMap.get(objectName));

            if (mbeanRefMap == null) {
                // The MBean is no longer referenced
                RELATION_LOGGER.exiting(RelationService.class.getName(),
                        "removeMBeanReference");
                return true;
            }

            ArrayList roleNames = new ArrayList();
            if (!allRolesFlag) {
                // Now retrieves the roles of current relation where the MBean
                // was referenced
                roleNames = (ArrayList)(mbeanRefMap.get(relationId));

                // Removes obsolete reference to role
                int obsRefIdx = roleNames.indexOf(roleName);
                if (obsRefIdx != -1) {
                    roleNames.remove(obsRefIdx);
                }
            }

            // Checks if there is still at least one role in current relation
            // where the MBean is referenced
            if (roleNames.isEmpty() || allRolesFlag) {
                // MBean no longer referenced in current relation: removes
                // entry
                mbeanRefMap.remove(relationId);
            }

            // Checks if the MBean is still referenced in at least on relation
            if (mbeanRefMap.isEmpty()) {
                // MBean no longer referenced in any relation: removes entry
                myRefedMBeanObjName2RelIdsMap.remove(objectName);
                noLongerRefFlag = true;
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "removeMBeanReference");
        return noLongerRefFlag;
    }

    // Updates the listener registered to the MBean Server to be informed of
    // referenced MBean unregistrations
    //
    // -param newRefList  ArrayList of ObjectNames for new references done
    //  to MBeans (can be null)
    // -param obsoleteRefList  ArrayList of ObjectNames for obsolete references
    //  to MBeans (can be null)
    //
    // -exception RelationServiceNotRegisteredException  if the Relation
    //  Service is not registered in the MBean Server.
    private void updateUnregistrationListener(List newRefList,
                                              List obsoleteRefList)
        throws RelationServiceNotRegisteredException {

        if (newRefList != null && obsoleteRefList != null) {
            if (newRefList.isEmpty() && obsoleteRefList.isEmpty()) {
                // Nothing to do :)
                return;
            }
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "updateUnregistrationListener",
                new Object[] {newRefList, obsoleteRefList});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        if (newRefList != null || obsoleteRefList != null) {

            boolean newListenerFlag = false;
            if (myUnregNtfFilter == null) {
                // Initialize it to be able to synchronise it :)
                myUnregNtfFilter = new MBeanServerNotificationFilter();
                newListenerFlag = true;
            }

            synchronized(myUnregNtfFilter) {

                // Enables ObjectNames in newRefList
                if (newRefList != null) {
                    for (Iterator newRefIter = newRefList.iterator();
                         newRefIter.hasNext();) {

                        ObjectName newObjName = (ObjectName)
                            (newRefIter.next());
                        myUnregNtfFilter.enableObjectName(newObjName);
                    }
                }

                if (obsoleteRefList != null) {
                    // Disables ObjectNames in obsoleteRefList
                    for (Iterator obsRefIter = obsoleteRefList.iterator();
                         obsRefIter.hasNext();) {

                        ObjectName obsObjName = (ObjectName)
                            (obsRefIter.next());
                        myUnregNtfFilter.disableObjectName(obsObjName);
                    }
                }

// Under test
                if (newListenerFlag) {
                    try {
                        myMBeanServer.addNotificationListener(
                                MBeanServerDelegate.DELEGATE_NAME,
                                this,
                                myUnregNtfFilter,
                                null);
                    } catch (InstanceNotFoundException exc) {
                        throw new
                       RelationServiceNotRegisteredException(exc.getMessage());
                    }
                }
// End test


//              if (!newListenerFlag) {
                    // The Relation Service was already registered as a
                    // listener:
                    // removes it
                    // Shall not throw InstanceNotFoundException (as the
                    // MBean Server Delegate is expected to exist) or
                    // ListenerNotFoundException (as it has been checked above
                    // that the Relation Service is registered)
//                  try {
//                      myMBeanServer.removeNotificationListener(
//                              MBeanServerDelegate.DELEGATE_NAME,
//                              this);
//                  } catch (InstanceNotFoundException exc1) {
//                      throw new RuntimeException(exc1.getMessage());
//                  } catch (ListenerNotFoundException exc2) {
//                      throw new
//                          RelationServiceNotRegisteredException(exc2.getMessage());
//                  }
//              }

                // Adds Relation Service with current filter
                // Can throw InstanceNotFoundException if the Relation
                // Service is not registered, to be transformed into
                // RelationServiceNotRegisteredException
                //
                // Assume that there will not be any InstanceNotFoundException
                // for the MBean Server Delegate :)
//              try {
//                  myMBeanServer.addNotificationListener(
//                              MBeanServerDelegate.DELEGATE_NAME,
//                              this,
//                              myUnregNtfFilter,
//                              null);
//              } catch (InstanceNotFoundException exc) {
//                  throw new
//                     RelationServiceNotRegisteredException(exc.getMessage());
//              }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "updateUnregistrationListener");
        return;
    }

    // Adds a relation (being either a RelationSupport object or an MBean
    // referenced using its ObjectName) in the Relation Service.
    // Will send a notification RelationNotification with type:
    // - RelationNotification.RELATION_BASIC_CREATION for internal relation
    //   creation
    // - RelationNotification.RELATION_MBEAN_CREATION for an MBean being added
    //   as a relation.
    //
    // -param relationBaseFlag  flag true if the relation is a RelationSupport
    //  object, false if it is an MBean
    // -param relationObj  RelationSupport object (if relation is internal)
    // -param relationObjName  ObjectName of the MBean to be added as a relation
    //  (only for the relation MBean)
    // -param relationId  relation identifier, to uniquely identify the relation
    //  inside the Relation Service
    // -param relationTypeName  name of the relation type (has to be created
    //  in the Relation Service)
    // -param roleList  role list to initialize roles of the relation
    //  (can be null)
    //
    // -exception IllegalArgumentException  if null paramater
    // -exception RelationServiceNotRegisteredException  if the Relation
    //  Service is not registered in the MBean Server
    // -exception RoleNotFoundException  if a value is provided for a role
    //  that does not exist in the relation type
    // -exception InvalidRelationIdException  if relation id already used
    // -exception RelationTypeNotFoundException  if relation type not known in
    //  Relation Service
    // -exception InvalidRoleValueException if:
    //  - the same role name is used for two different roles
    //  - the number of referenced MBeans in given value is less than
    //    expected minimum degree
    //  - the number of referenced MBeans in provided value exceeds expected
    //    maximum degree
    //  - one referenced MBean in the value is not an Object of the MBean
    //    class expected for that role
    //  - an MBean provided for that role does not exist
    private void addRelationInt(boolean relationBaseFlag,
                                RelationSupport relationObj,
                                ObjectName relationObjName,
                                String relationId,
                                String relationTypeName,
                                RoleList roleList)
        throws IllegalArgumentException,
               RelationServiceNotRegisteredException,
               RoleNotFoundException,
               InvalidRelationIdException,
               RelationTypeNotFoundException,
               InvalidRoleValueException {

        if (relationId == null ||
            relationTypeName == null ||
            (relationBaseFlag &&
             (relationObj == null ||
              relationObjName != null)) ||
            (!relationBaseFlag &&
             (relationObjName == null ||
              relationObj != null))) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "addRelationInt", new Object[] {relationBaseFlag, relationObj,
                relationObjName, relationId, relationTypeName, roleList});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Checks if there is already a relation with given id
        try {
            // Can throw a RelationNotFoundException (in fact should :)
            Object rel = getRelation(relationId);

            if (rel != null) {
                // There is already a relation with that id
                String excMsg = "There is already a relation with id ";
                StringBuilder excMsgStrB = new StringBuilder(excMsg);
                excMsgStrB.append(relationId);
                throw new InvalidRelationIdException(excMsgStrB.toString());
            }
        } catch (RelationNotFoundException exc) {
            // OK : The Relation could not be found.
        }

        // Retrieves the relation type
        // Can throw RelationTypeNotFoundException
        RelationType relType = getRelationType(relationTypeName);

        // Checks that each provided role conforms to its role info provided in
        // the relation type
        // First retrieves a local list of the role infos of the relation type
        // to see which roles have not been initialized
        // Note: no need to test if list not null before cloning, not allowed
        //       to have an empty relation type.
        ArrayList roleInfoList = (ArrayList)
            (((ArrayList)(relType.getRoleInfos())).clone());

        if (roleList != null) {

            for (Iterator roleIter = roleList.iterator();
                 roleIter.hasNext();) {

                Role currRole = (Role)(roleIter.next());
                String currRoleName = currRole.getRoleName();
                ArrayList currRoleValue = (ArrayList)
                    (currRole.getRoleValue());
                // Retrieves corresponding role info
                // Can throw a RoleInfoNotFoundException to be converted into a
                // RoleNotFoundException
                RoleInfo roleInfo = null;
                try {
                    roleInfo = relType.getRoleInfo(currRoleName);
                } catch (RoleInfoNotFoundException exc) {
                    throw new RoleNotFoundException(exc.getMessage());
                }

                // Checks that role conforms to role info,
                Integer status = checkRoleInt(2,
                                              currRoleName,
                                              currRoleValue,
                                              roleInfo,
                                              false);
                int pbType = status.intValue();
                if (pbType != 0) {
                    // A problem has occurred: throws appropriate exception
                    // here InvalidRoleValueException
                    throwRoleProblemException(pbType, currRoleName);
                }

                // Removes role info for that list from list of role infos for
                // roles to be defaulted
                int roleInfoIdx = roleInfoList.indexOf(roleInfo);
                // Note: no need to check if != -1, MUST be there :)
                roleInfoList.remove(roleInfoIdx);
            }
        }

        // Initializes roles not initialized by roleList
        // Can throw InvalidRoleValueException
        initializeMissingRoles(relationBaseFlag,
                               relationObj,
                               relationObjName,
                               relationId,
                               relationTypeName,
                               roleInfoList);

        // Creation of relation successfull!!!!

        // Updates internal maps
        // Relation id to object map
        synchronized(myRelId2ObjMap) {
            if (relationBaseFlag) {
                // Note: do not clone relation object, created by us :)
                myRelId2ObjMap.put(relationId, relationObj);
            } else {
                myRelId2ObjMap.put(relationId, relationObjName);
            }
        }

        // Relation id to relation type name map
        synchronized(myRelId2RelTypeMap) {
            myRelId2RelTypeMap.put(relationId,
                                   relationTypeName);
        }

        // Relation type to relation id map
        synchronized(myRelType2RelIdsMap) {
            List<String> relIdList =
                myRelType2RelIdsMap.get(relationTypeName);
            boolean firstRelFlag = false;
            if (relIdList == null) {
                firstRelFlag = true;
                relIdList = new ArrayList<String>();
            }
            relIdList.add(relationId);
            if (firstRelFlag) {
                myRelType2RelIdsMap.put(relationTypeName, relIdList);
            }
        }

        // Referenced MBean to relation id map
        // Only role list parameter used, as default initialization of roles
        // done automatically in initializeMissingRoles() sets each
        // uninitialized role to an empty value.
        for (Iterator roleIter = roleList.iterator();
             roleIter.hasNext();) {
            Role currRole = (Role)(roleIter.next());
            // Creates a dummy empty ArrayList of ObjectNames to be the old
            // role value :)
            List<ObjectName> dummyList = new ArrayList<ObjectName>();
            // Will not throw a RelationNotFoundException (as the RelId2Obj map
            // has been updated above) so catch it :)
            try {
                updateRoleMap(relationId, currRole, dummyList);

            } catch (RelationNotFoundException exc) {
                // OK : The Relation could not be found.
            }
        }

        // Sends a notification for relation creation
        // Will not throw RelationNotFoundException so catch it :)
        try {
            sendRelationCreationNotification(relationId);

        } catch (RelationNotFoundException exc) {
            // OK : The Relation could not be found.
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "addRelationInt");
        return;
    }

    // Checks that given role conforms to given role info.
    //
    // -param chkType  type of check:
    //  - 1: read, just check read access
    //  - 2: write, check value and write access if writeChkFlag
    // -param roleName  role name
    // -param roleValue  role value
    // -param roleInfo  corresponding role info
    // -param writeChkFlag  boolean to specify a current write access and
    //  to check it
    //
    // -return Integer with value:
    //  - 0: ok
    //  - RoleStatus.NO_ROLE_WITH_NAME
    //  - RoleStatus.ROLE_NOT_READABLE
    //  - RoleStatus.ROLE_NOT_WRITABLE
    //  - RoleStatus.LESS_THAN_MIN_ROLE_DEGREE
    //  - RoleStatus.MORE_THAN_MAX_ROLE_DEGREE
    //  - RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS
    //  - RoleStatus.REF_MBEAN_NOT_REGISTERED
    //
    // -exception IllegalArgumentException  if null parameter
    private Integer checkRoleInt(int chkType,
                                 String roleName,
                                 List roleValue,
                                 RoleInfo roleInfo,
                                 boolean writeChkFlag)
        throws IllegalArgumentException {

        if (roleName == null ||
            roleInfo == null ||
            (chkType == 2 && roleValue == null)) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "checkRoleInt", new Object[] {chkType, roleName,
                roleValue, roleInfo, writeChkFlag});

        // Compares names
        String expName = roleInfo.getName();
        if (!(roleName.equals(expName))) {
            RELATION_LOGGER.exiting(RelationService.class.getName(),
                    "checkRoleInt");
            return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
        }

        // Checks read access if required
        if (chkType == 1) {
            boolean isReadable = roleInfo.isReadable();
            if (!isReadable) {
                RELATION_LOGGER.exiting(RelationService.class.getName(),
                        "checkRoleInt");
                return new Integer(RoleStatus.ROLE_NOT_READABLE);
            } else {
                // End of check :)
                RELATION_LOGGER.exiting(RelationService.class.getName(),
                        "checkRoleInt");
                return new Integer(0);
            }
        }

        // Checks write access if required
        if (writeChkFlag) {
            boolean isWritable = roleInfo.isWritable();
            if (!isWritable) {
                RELATION_LOGGER.exiting(RelationService.class.getName(),
                        "checkRoleInt");
                return new Integer(RoleStatus.ROLE_NOT_WRITABLE);
            }
        }

        int refNbr = roleValue.size();

        // Checks minimum cardinality
        boolean chkMinFlag = roleInfo.checkMinDegree(refNbr);
        if (!chkMinFlag) {
            RELATION_LOGGER.exiting(RelationService.class.getName(),
                    "checkRoleInt");
            return new Integer(RoleStatus.LESS_THAN_MIN_ROLE_DEGREE);
        }

        // Checks maximum cardinality
        boolean chkMaxFlag = roleInfo.checkMaxDegree(refNbr);
        if (!chkMaxFlag) {
            RELATION_LOGGER.exiting(RelationService.class.getName(),
                    "checkRoleInt");
            return new Integer(RoleStatus.MORE_THAN_MAX_ROLE_DEGREE);
        }

        // Verifies that each referenced MBean is registered in the MBean
        // Server and that it is an instance of the class specified in the
        // role info, or of a subclass of it
        // Note that here again this is under the assumption that
        // referenced MBeans, relation MBeans and the Relation Service are
        // registered in the same MBean Server.
        String expClassName = roleInfo.getRefMBeanClassName();

        for (Iterator refMBeanIter = roleValue.iterator();
             refMBeanIter.hasNext();) {
            ObjectName currObjName = (ObjectName)(refMBeanIter.next());

            // Checks it is registered
            if (currObjName == null) {
                RELATION_LOGGER.exiting(RelationService.class.getName(),
                        "checkRoleInt");
                return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
            }

            // Checks if it is of the correct class
            // Can throw an InstanceNotFoundException, if MBean not registered
            try {
                boolean classSts = myMBeanServer.isInstanceOf(currObjName,
                                                              expClassName);
                if (!classSts) {
                    RELATION_LOGGER.exiting(RelationService.class.getName(),
                            "checkRoleInt");
                    return new Integer(RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS);
                }

            } catch (InstanceNotFoundException exc) {
                RELATION_LOGGER.exiting(RelationService.class.getName(),
                        "checkRoleInt");
                return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "checkRoleInt");
        return new Integer(0);
    }


    // Initializes roles associated to given role infos to default value (empty
    // ArrayList of ObjectNames) in given relation.
    // It will succeed for every role except if the role info has a minimum
    // cardinality greater than 0. In that case, an InvalidRoleValueException
    // will be raised.
    //
    // -param relationBaseFlag  flag true if the relation is a RelationSupport
    //  object, false if it is an MBean
    // -param relationObj  RelationSupport object (if relation is internal)
    // -param relationObjName  ObjectName of the MBean to be added as a relation
    //  (only for the relation MBean)
    // -param relationId  relation id
    // -param relationTypeName  name of the relation type (has to be created
    //  in the Relation Service)
    // -param roleInfoList  list of role infos for roles to be defaulted
    //
    // -exception IllegalArgumentException  if null paramater
    // -exception RelationServiceNotRegisteredException  if the Relation
    //  Service is not registered in the MBean Server
    // -exception InvalidRoleValueException  if role must have a non-empty
    //  value

    // Revisit [cebro] Handle CIM qualifiers as REQUIRED to detect roles which
    //    should have been initialized by the user
    private void initializeMissingRoles(boolean relationBaseFlag,
                                        RelationSupport relationObj,
                                        ObjectName relationObjName,
                                        String relationId,
                                        String relationTypeName,
                                        List roleInfoList)
        throws IllegalArgumentException,
               RelationServiceNotRegisteredException,
               InvalidRoleValueException {

        if ((relationBaseFlag &&
             (relationObj == null ||
              relationObjName != null)) ||
            (!relationBaseFlag &&
             (relationObjName == null ||
              relationObj != null)) ||
            relationId == null ||
            relationTypeName == null ||
            roleInfoList == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "initializeMissingRoles", new Object[] {relationBaseFlag,
                relationObj, relationObjName, relationId, relationTypeName,
                roleInfoList});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // For each role info (corresponding to a role not initialized by the
        // role list provided by the user), try to set in the relation a role
        // with an empty list of ObjectNames.
        // A check is performed to verify that the role can be set to an
        // empty value, according to its minimum cardinality
        for (Iterator roleInfoIter = roleInfoList.iterator();
             roleInfoIter.hasNext();) {

            RoleInfo currRoleInfo = (RoleInfo)(roleInfoIter.next());
            String roleName = currRoleInfo.getName();

            // Creates an empty value
            List<ObjectName> emptyValue = new ArrayList<ObjectName>();
            // Creates a role
            Role role = new Role(roleName, emptyValue);

            if (relationBaseFlag) {

                // Internal relation
                // Can throw InvalidRoleValueException
                //
                // Will not throw RoleNotFoundException (role to be
                // initialized), or RelationNotFoundException, or
                // RelationTypeNotFoundException
                try {
                    relationObj.setRoleInt(role, true, this, false);

                } catch (RoleNotFoundException exc1) {
                    throw new RuntimeException(exc1.getMessage());
                } catch (RelationNotFoundException exc2) {
                    throw new RuntimeException(exc2.getMessage());
                } catch (RelationTypeNotFoundException exc3) {
                    throw new RuntimeException(exc3.getMessage());
                }

            } else {

                // Relation is an MBean
                // Use standard setRole()
                Object[] params = new Object[1];
                params[0] = role;
                String[] signature = new String[1];
                signature[0] = "javax.management.relation.Role";
                // Can throw MBeanException wrapping
                // InvalidRoleValueException. Returns the target exception to
                // be homogeneous.
                //
                // Will not throw MBeanException (wrapping
                // RoleNotFoundException or MBeanException) or
                // InstanceNotFoundException, or ReflectionException
                //
                // Again here the assumption is that the Relation Service and
                // the relation MBeans are registered in the same MBean Server.
                try {
                    myMBeanServer.setAttribute(relationObjName,
                                               new Attribute("Role", role));

                } catch (InstanceNotFoundException exc1) {
                    throw new RuntimeException(exc1.getMessage());
                } catch (ReflectionException exc3) {
                    throw new RuntimeException(exc3.getMessage());
                } catch (MBeanException exc2) {
                    Exception wrappedExc = exc2.getTargetException();
                    if (wrappedExc instanceof InvalidRoleValueException) {
                        throw ((InvalidRoleValueException)wrappedExc);
                    } else {
                        throw new RuntimeException(wrappedExc.getMessage());
                    }
                } catch (AttributeNotFoundException exc4) {
                  throw new RuntimeException(exc4.getMessage());
                } catch (InvalidAttributeValueException exc5) {
                  throw new RuntimeException(exc5.getMessage());
                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "initializeMissingRoles");
        return;
    }

    // Throws an exception corresponding to a given problem type
    //
    // -param pbType  possible problem, defined in RoleUnresolved
    // -param roleName  role name
    //
    // -exception IllegalArgumentException  if null parameter
    // -exception RoleNotFoundException  for problems:
    //  - NO_ROLE_WITH_NAME
    //  - ROLE_NOT_READABLE
    //  - ROLE_NOT_WRITABLE
    // -exception InvalidRoleValueException  for problems:
    //  - LESS_THAN_MIN_ROLE_DEGREE
    //  - MORE_THAN_MAX_ROLE_DEGREE
    //  - REF_MBEAN_OF_INCORRECT_CLASS
    //  - REF_MBEAN_NOT_REGISTERED
    static void throwRoleProblemException(int pbType,
                                          String roleName)
        throws IllegalArgumentException,
               RoleNotFoundException,
               InvalidRoleValueException {

        if (roleName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        // Exception type: 1 = RoleNotFoundException
        //                 2 = InvalidRoleValueException
        int excType = 0;

        String excMsgPart = null;

        switch (pbType) {
        case RoleStatus.NO_ROLE_WITH_NAME:
            excMsgPart = " does not exist in relation.";
            excType = 1;
            break;
        case RoleStatus.ROLE_NOT_READABLE:
            excMsgPart = " is not readable.";
            excType = 1;
            break;
        case RoleStatus.ROLE_NOT_WRITABLE:
            excMsgPart = " is not writable.";
            excType = 1;
            break;
        case RoleStatus.LESS_THAN_MIN_ROLE_DEGREE:
            excMsgPart = " has a number of MBean references less than the expected minimum degree.";
            excType = 2;
            break;
        case RoleStatus.MORE_THAN_MAX_ROLE_DEGREE:
            excMsgPart = " has a number of MBean references greater than the expected maximum degree.";
            excType = 2;
            break;
        case RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS:
            excMsgPart = " has an MBean reference to an MBean not of the expected class of references for that role.";
            excType = 2;
            break;
        case RoleStatus.REF_MBEAN_NOT_REGISTERED:
            excMsgPart = " has a reference to null or to an MBean not registered.";
            excType = 2;
            break;
        }
        // No default as we must have been in one of those cases

        StringBuilder excMsgStrB = new StringBuilder(roleName);
        excMsgStrB.append(excMsgPart);
        String excMsg = excMsgStrB.toString();
        if (excType == 1) {
            throw new RoleNotFoundException(excMsg);

        } else if (excType == 2) {
            throw new InvalidRoleValueException(excMsg);
        }
    }

    // Sends a notification of given type, with given parameters
    //
    // -param intNtfType  integer to represent notification type:
    //  - 1 : create
    //  - 2 : update
    //  - 3 : delete
    // -param message  human-readable message
    // -param relationId  relation id of the created/updated/deleted relation
    // -param unregMBeanList  list of ObjectNames of referenced MBeans
    //  expected to be unregistered due to relation removal (only for removal,
    //  due to CIM qualifiers, can be null)
    // -param roleName  role name
    // -param roleNewValue  role new value (ArrayList of ObjectNames)
    // -param oldValue  old role value (ArrayList of ObjectNames)
    //
    // -exception IllegalArgument  if null parameter
    // -exception RelationNotFoundException  if no relation for given id
    private void sendNotificationInt(int intNtfType,
                                     String message,
                                     String relationId,
                                     List<ObjectName> unregMBeanList,
                                     String roleName,
                                     List<ObjectName> roleNewValue,
                                     List<ObjectName> oldValue)
        throws IllegalArgumentException,
               RelationNotFoundException {

        if (message == null ||
            relationId == null ||
            (intNtfType != 3 && unregMBeanList != null) ||
            (intNtfType == 2 &&
             (roleName == null ||
              roleNewValue == null ||
              oldValue == null))) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "sendNotificationInt", new Object[] {intNtfType, message,
                relationId, unregMBeanList, roleName, roleNewValue, oldValue});

        // Relation type name
        // Note: do not use getRelationTypeName() as if it is a relation MBean
        //       it is already unregistered.
        String relTypeName = null;
        synchronized(myRelId2RelTypeMap) {
            relTypeName = (myRelId2RelTypeMap.get(relationId));
        }

        // ObjectName (for a relation MBean)
        // Can also throw a RelationNotFoundException, but detected above
        ObjectName relObjName = isRelationMBean(relationId);

        String ntfType = null;
        if (relObjName != null) {
            switch (intNtfType) {
            case 1:
                ntfType = RelationNotification.RELATION_MBEAN_CREATION;
                break;
            case 2:
                ntfType = RelationNotification.RELATION_MBEAN_UPDATE;
                break;
            case 3:
                ntfType = RelationNotification.RELATION_MBEAN_REMOVAL;
                break;
            }
        } else {
            switch (intNtfType) {
            case 1:
                ntfType = RelationNotification.RELATION_BASIC_CREATION;
                break;
            case 2:
                ntfType = RelationNotification.RELATION_BASIC_UPDATE;
                break;
            case 3:
                ntfType = RelationNotification.RELATION_BASIC_REMOVAL;
                break;
            }
        }

        // Sequence number
        Long seqNbr = getNotificationSequenceNumber();

        // Timestamp
        Date currDate = new Date();
        long timeStamp = currDate.getTime();

        RelationNotification ntf = null;

        if (ntfType.equals(RelationNotification.RELATION_BASIC_CREATION) ||
            ntfType.equals(RelationNotification.RELATION_MBEAN_CREATION) ||
            ntfType.equals(RelationNotification.RELATION_BASIC_REMOVAL) ||
            ntfType.equals(RelationNotification.RELATION_MBEAN_REMOVAL))

            // Creation or removal
            ntf = new RelationNotification(ntfType,
                                           this,
                                           seqNbr.longValue(),
                                           timeStamp,
                                           message,
                                           relationId,
                                           relTypeName,
                                           relObjName,
                                           unregMBeanList);

        else if (ntfType.equals(RelationNotification.RELATION_BASIC_UPDATE)
                 ||
                 ntfType.equals(RelationNotification.RELATION_MBEAN_UPDATE))
            {
                // Update
                ntf = new RelationNotification(ntfType,
                                               this,
                                               seqNbr.longValue(),
                                               timeStamp,
                                               message,
                                               relationId,
                                               relTypeName,
                                               relObjName,
                                               roleName,
                                               roleNewValue,
                                               oldValue);
            }

        sendNotification(ntf);

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "sendNotificationInt");
        return;
    }

    // Checks, for the unregistration of an MBean referenced in the roles given
    // in parameter, if the relation has to be removed or not, regarding
    // expected minimum role cardinality and current number of
    // references in each role after removal of the current one.
    // If the relation is kept, calls handleMBeanUnregistration() callback of
    // the relation to update it.
    //
    // -param relationId  relation id
    // -param objectName  ObjectName of the unregistered MBean
    // -param roleNameList  list of names of roles where the unregistered
    //  MBean is referenced.
    //
    // -exception IllegalArgumentException  if null parameter
    // -exception RelationServiceNotRegisteredException  if the Relation
    //  Service is not registered in the MBean Server
    // -exception RelationNotFoundException  if unknown relation id
    // -exception RoleNotFoundException  if one role given as parameter does
    //  not exist in the relation
    private void handleReferenceUnregistration(String relationId,
                                               ObjectName objectName,
                                               List roleNameList)
        throws IllegalArgumentException,
               RelationServiceNotRegisteredException,
               RelationNotFoundException,
               RoleNotFoundException {

        if (relationId == null ||
            roleNameList == null ||
            objectName == null) {
            String excMsg = "Invalid parameter.";
            throw new IllegalArgumentException(excMsg);
        }

        RELATION_LOGGER.entering(RelationService.class.getName(),
                "handleReferenceUnregistration",
                new Object[] {relationId, objectName, roleNameList});

        // Can throw RelationServiceNotRegisteredException
        isActive();

        // Retrieves the relation type name of the relation
        // Can throw RelationNotFoundException
        String currRelTypeName = getRelationTypeName(relationId);

        // Retrieves the relation
        // Can throw RelationNotFoundException, but already detected above
        Object relObj = getRelation(relationId);

        // Flag to specify if the relation has to be deleted
        boolean deleteRelFlag = false;

        for (Iterator roleNameIter = roleNameList.iterator();
             roleNameIter.hasNext();) {

            if (deleteRelFlag) {
                break;
            }

            String currRoleName = (String)(roleNameIter.next());
            // Retrieves number of MBeans currently referenced in role
            // BEWARE! Do not use getRole() as role may be not readable
            //
            // Can throw RelationNotFoundException (but already checked),
            // RoleNotFoundException
            int currRoleRefNbr =
                (getRoleCardinality(relationId, currRoleName)).intValue();

            // Retrieves new number of element in role
            int currRoleNewRefNbr = currRoleRefNbr - 1;

            // Retrieves role info for that role
            //
            // Shall not throw RelationTypeNotFoundException or
            // RoleInfoNotFoundException
            RoleInfo currRoleInfo = null;
            try {
                currRoleInfo = getRoleInfo(currRelTypeName,
                                           currRoleName);
            } catch (RelationTypeNotFoundException exc1) {
                throw new RuntimeException(exc1.getMessage());
            } catch (RoleInfoNotFoundException exc2) {
                throw new RuntimeException(exc2.getMessage());
            }

            // Checks with expected minimum number of elements
            boolean chkMinFlag = currRoleInfo.checkMinDegree(currRoleNewRefNbr);

            if (!chkMinFlag) {
                // The relation has to be deleted
                deleteRelFlag = true;
            }
        }

        if (deleteRelFlag) {
            // Removes the relation
            removeRelation(relationId);

        } else {

            // Updates each role in the relation using
            // handleMBeanUnregistration() callback
            //
            // BEWARE: this roleNameList list MUST BE A COPY of a role name
            //         list for a referenced MBean in a relation, NOT a
            //         reference to an original one part of the
            //         myRefedMBeanObjName2RelIdsMap!!!! Because each role
            //         which name is in that list will be updated (potentially
            //         using setRole(). So the Relation Service will update the
            //         myRefedMBeanObjName2RelIdsMap to refelect the new role
            //         value!
            for (Iterator roleNameIter = roleNameList.iterator();
                 roleNameIter.hasNext();) {

                String currRoleName = (String)(roleNameIter.next());

                if (relObj instanceof RelationSupport) {
                    // Internal relation
                    // Can throw RoleNotFoundException (but already checked)
                    //
                    // Shall not throw
                    // RelationTypeNotFoundException,
                    // InvalidRoleValueException (value was correct, removing
                    // one reference shall not invalidate it, else detected
                    // above)
                    try {
                        ((RelationSupport)relObj).handleMBeanUnregistrationInt(
                                                  objectName,
                                                  currRoleName,
                                                  true,
                                                  this);
                    } catch (RelationTypeNotFoundException exc3) {
                        throw new RuntimeException(exc3.getMessage());
                    } catch (InvalidRoleValueException exc4) {
                        throw new RuntimeException(exc4.getMessage());
                    }

                } else {
                    // Relation MBean
                    Object[] params = new Object[2];
                    params[0] = objectName;
                    params[1] = currRoleName;
                    String[] signature = new String[2];
                    signature[0] = "javax.management.ObjectName";
                    signature[1] = "java.lang.String";
                    // Shall not throw InstanceNotFoundException, or
                    // MBeanException (wrapping RoleNotFoundException or
                    // MBeanException or InvalidRoleValueException) or
                    // ReflectionException
                    try {
                        myMBeanServer.invoke(((ObjectName)relObj),
                                             "handleMBeanUnregistration",
                                             params,
                                             signature);
                    } catch (InstanceNotFoundException exc1) {
                        throw new RuntimeException(exc1.getMessage());
                    } catch (ReflectionException exc3) {
                        throw new RuntimeException(exc3.getMessage());
                    } catch (MBeanException exc2) {
                        Exception wrappedExc = exc2.getTargetException();
                        throw new RuntimeException(wrappedExc.getMessage());
                    }

                }
            }
        }

        RELATION_LOGGER.exiting(RelationService.class.getName(),
                "handleReferenceUnregistration");
        return;
    }
}
