/*
 * Copyright (c) 2000, 2008, Oracle and/or its affiliates. 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.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle 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 Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.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.concurrent.atomic.AtomicLong;
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 final 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 final AtomicLong atomicSeqNo = new AtomicLong();

    // 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;
    }

    //
    // 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;
        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;
        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;
        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;
        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;
        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;
        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;

        // 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 = Integer.valueOf(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;
        try {
            roleInfo = relType.getRoleInfo(roleName);
        } catch (RoleInfoNotFoundException exc) {
            RELATION_LOGGER.exiting(RelationService.class.getName(),
                    "checkRoleWriting");
            return Integer.valueOf(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;
        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(myRefedMBeanObjName2RelIdsMap) {
            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;
                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;
                        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;

        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;

        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;

        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;

        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;

        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;
                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");

        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;
        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;
        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.
            Map<String,List<String>> mbeanRefMap =
                (myRefedMBeanObjName2RelIdsMap.get(objectName));

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

            List<String> roleNames = null;
            if (!allRolesFlag) {
                // Now retrieves the roles of current relation where the MBean
                // was referenced
                roleNames = 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<ObjectName> newRefList,
                                              List<ObjectName> 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 (ObjectName newObjName : newRefList)
                        myUnregNtfFilter.enableObjectName(newObjName);
                }

                if (obsoleteRefList != null) {
                    // Disables ObjectNames in obsoleteRefList
                    for (ObjectName obsObjName : obsoleteRefList)
                        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.
        List<RoleInfo> roleInfoList = new ArrayList<RoleInfo>(relType.getRoleInfos());

        if (roleList != null) {

            for (Role currRole : roleList.asList()) {
                String currRoleName = currRole.getRoleName();
                List<ObjectName> currRoleValue = currRole.getRoleValue();
                // Retrieves corresponding role info
                // Can throw a RoleInfoNotFoundException to be converted into a
                // RoleNotFoundException
                RoleInfo roleInfo;
                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 (Role currRole : roleList.asList()) {
            // 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<ObjectName> 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 Integer.valueOf(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 Integer.valueOf(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 (ObjectName currObjName : roleValue) {

            // 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<RoleInfo> 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 (RoleInfo currRoleInfo : roleInfoList) {

            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;
        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 seqNo = atomicSeqNo.incrementAndGet();

        // 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,
                                           seqNo.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,
                                               seqNo.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<String> 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 (String currRoleName : roleNameList) {

            if (deleteRelFlag) {
                break;
            }

            // 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;
            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 (String currRoleName : roleNameList) {

                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;
    }
}
