| /* | |
| * Copyright (c) 2000, 2022, 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.List; | |
| import java.util.Map; | |
| import java.util.Set; | |
| import java.util.concurrent.atomic.AtomicLong; | |
| import java.lang.System.Logger.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<>(); | |
| // Map associating: | |
| // <relation id> -> <relation type name> | |
| private Map<String,String> myRelId2RelTypeMap = new HashMap<>(); | |
| // Map associating: | |
| // <relation MBean Object Name> -> <relation id> | |
| private Map<ObjectName,String> myRelMBeanObjName2RelIdMap = | |
| new HashMap<>(); | |
| // Map associating: | |
| // <relation type name> -> <RelationType object> | |
| private Map<String,RelationType> myRelType2ObjMap = | |
| new HashMap<>(); | |
| // 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<>(); | |
| // 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<>(); | |
| // 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 deregistrations | |
| 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<>(); | |
| // | |
| // 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.log(Level.TRACE, "ENTRY"); | |
| setPurgeFlag(immediatePurgeFlag); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", relationTypeName); | |
| // Can throw an InvalidRelationTypeException | |
| RelationType relType = | |
| new RelationTypeSupport(relationTypeName, roleInfoArray); | |
| addRelationTypeInt(relType); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY"); | |
| // 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.log(Level.TRACE, "RETURN"); | |
| 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<>(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.log(Level.TRACE, "ENTRY {0}", relationTypeName); | |
| // Can throw a RelationTypeNotFoundException | |
| RelationType relType = getRelationType(relationTypeName); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1}", | |
| relationTypeName, roleInfoName); | |
| // Can throw a RelationTypeNotFoundException | |
| RelationType relType = getRelationType(relationTypeName); | |
| // Can throw a RoleInfoNotFoundException | |
| RoleInfo roleInfo = relType.getRoleInfo(roleInfoName); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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<>(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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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 | AttributeNotFoundException exc2) { | |
| throw new RuntimeException(exc2.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 | AttributeNotFoundException exc2) { | |
| throw new RuntimeException(exc2.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 | AttributeNotFoundException exc2) { | |
| throw new RuntimeException(exc2.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<>(); | |
| newRefList.add(relationObjectName); | |
| updateUnregistrationListener(newRefList, null); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "ENTRY {0}", 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<>(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.log(Level.TRACE, "ENTRY {0} {1}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); | |
| } | |
| Integer result = checkRoleInt(2, | |
| roleName, | |
| roleValue, | |
| roleInfo, | |
| writeChkFlag); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "RETURN"); | |
| 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<>(oldValue); | |
| RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| } | |
| /** | |
| * 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.log(Level.TRACE, "ENTRY {0} {1}", | |
| relationId, unregMBeanList); | |
| // Can throw RelationNotFoundException | |
| sendNotificationInt(3, | |
| "Removal of relation " + relationId, | |
| relationId, | |
| unregMBeanList, | |
| null, | |
| null, | |
| null); | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| 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<>(oldValue); | |
| // List of ObjectNames of new referenced MBeans | |
| List<ObjectName> newRefList = new ArrayList<>(); | |
| 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<>(); | |
| // 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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<>(); | |
| 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<>(); | |
| // List of MBeans no longer referenced in any relation, to be | |
| // removed fom the map | |
| List<ObjectName> nonRefObjNameList = new ArrayList<>(); | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY"); | |
| // 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<>(myUnregNtfList); | |
| // Resets list | |
| myUnregNtfList = new ArrayList<>(); | |
| } | |
| // 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<>(); | |
| // Map including ObjectNames for unregistered MBeans, with | |
| // referencing relation ids and roles | |
| Map<ObjectName,Map<String,List<String>>> localMBean2RelIdMap = | |
| new HashMap<>(); | |
| synchronized(myRefedMBeanObjName2RelIdsMap) { | |
| for (MBeanServerNotification currNtf : localUnregNtfList) { | |
| ObjectName unregMBeanName = currNtf.getMBeanName(); | |
| // Adds the unregistered 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 | RoleNotFoundException exc) { | |
| throw new RuntimeException(exc.getMessage()); | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| mbeanName, relationTypeName, roleName); | |
| Map<String,List<String>> result = new HashMap<>(); | |
| 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<>(allRelIdSet); | |
| } else { | |
| relIdList = new ArrayList<>(); | |
| // 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<>(currRoleNameList)); | |
| } else if (currRoleNameList.contains(roleName)) { | |
| // Filters only the relations where the MBean is | |
| // referenced in // given role | |
| List<String> dummyList = new ArrayList<>(); | |
| dummyList.add(roleName); | |
| result.put(currRelId, dummyList); | |
| } | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| mbeanName, relationTypeName, roleName); | |
| // Retrieves the map <relation id> -> <role names> for those | |
| // criteria | |
| Map<String,List<String>> relId2RoleNamesMap = | |
| findReferencingRelations(mbeanName, | |
| relationTypeName, | |
| roleName); | |
| Map<ObjectName,List<String>> result = new HashMap<>(); | |
| 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<>(); | |
| currRelIdList.add(currRelId); | |
| result.put(currObjName, currRelIdList); | |
| } else { | |
| currRelIdList.add(currRelId); | |
| } | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY"); | |
| // Can throw RelationTypeNotFoundException | |
| RelationType relType = getRelationType(relationTypeName); | |
| List<String> result; | |
| synchronized(myRelType2RelIdsMap) { | |
| List<String> result1 = myRelType2RelIdsMap.get(relationTypeName); | |
| if (result1 == null) | |
| result = new ArrayList<>(); | |
| else | |
| result = new ArrayList<>(result1); | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1}", | |
| 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<>(invokeResult); | |
| } catch (InstanceNotFoundException | ReflectionException exc1) { | |
| throw new RuntimeException(exc1.getMessage()); | |
| } catch (MBeanException exc2) { | |
| Exception wrappedExc = exc2.getTargetException(); | |
| if (wrappedExc instanceof RoleNotFoundException) { | |
| throw ((RoleNotFoundException)wrappedExc); | |
| } else { | |
| throw new RuntimeException(wrappedExc.getMessage()); | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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 | ReflectionException exc1) { | |
| throw new RuntimeException(exc1.getMessage()); | |
| } catch (MBeanException exc2) { | |
| throw new | |
| RuntimeException((exc2.getTargetException()).getMessage()); | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1}", | |
| 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 | ReflectionException exc1) { | |
| throw new RuntimeException(exc1.getMessage()); | |
| } catch (MBeanException exc2) { | |
| Exception wrappedExc = exc2.getTargetException(); | |
| if (wrappedExc instanceof RoleNotFoundException) { | |
| throw ((RoleNotFoundException)wrappedExc); | |
| } else { | |
| throw new RuntimeException(wrappedExc.getMessage()); | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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 deregistrations. | |
| * | |
| * @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.log(Level.TRACE, "ENTRY {0} {1}", | |
| 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 | ReflectionException | | |
| AttributeNotFoundException | InvalidAttributeValueException exc1) { | |
| throw new RuntimeException(exc1.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()); | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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 deregistrations. | |
| * | |
| * @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.log(Level.TRACE, "ENTRY {0} {1}", | |
| 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 | ReflectionException exc1) { | |
| throw new RuntimeException(exc1.getMessage()); | |
| } catch (MBeanException exc2) { | |
| throw new | |
| RuntimeException((exc2.getTargetException()).getMessage()); | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return result; | |
| } | |
| /** | |
| * Retrieves MBeans referenced in the various roles of the relation. | |
| * | |
| * @param relationId relation id | |
| * | |
| * @return a HashMap mapping: | |
| * <P> ObjectName {@literal ->} 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.log(Level.TRACE, "ENTRY {0}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY"); | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY"); | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0}", 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| 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<>(); | |
| roleNames.add(roleName); | |
| // Map of relations where the MBean is referenced | |
| mbeanRefMap = new HashMap<>(); | |
| 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<>(); | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2} {3}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "RETURN"); | |
| return noLongerRefFlag; | |
| } | |
| // Updates the listener registered to the MBean Server to be informed of | |
| // referenced MBean deregistrations | |
| // | |
| // -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.log(Level.TRACE, "ENTRY {0} {1}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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 parameter | |
| // -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.log(Level.TRACE, | |
| "ENTRY {0} {1} {2} {3} {4} {5}", | |
| 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<>(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 successful!!!! | |
| // 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<>(); | |
| } | |
| 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<>(); | |
| // 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2} {3} {4}", | |
| chkType, roleName, roleValue, roleInfo, writeChkFlag); | |
| // Compares names | |
| String expName = roleInfo.getName(); | |
| if (!(roleName.equals(expName))) { | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); | |
| } | |
| // Checks read access if required | |
| if (chkType == 1) { | |
| boolean isReadable = roleInfo.isReadable(); | |
| if (!isReadable) { | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return Integer.valueOf(RoleStatus.ROLE_NOT_READABLE); | |
| } else { | |
| // End of check :) | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return 0; | |
| } | |
| } | |
| // Checks write access if required | |
| if (writeChkFlag) { | |
| boolean isWritable = roleInfo.isWritable(); | |
| if (!isWritable) { | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return RoleStatus.ROLE_NOT_WRITABLE; | |
| } | |
| } | |
| int refNbr = roleValue.size(); | |
| // Checks minimum cardinality | |
| boolean chkMinFlag = roleInfo.checkMinDegree(refNbr); | |
| if (!chkMinFlag) { | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return RoleStatus.LESS_THAN_MIN_ROLE_DEGREE; | |
| } | |
| // Checks maximum cardinality | |
| boolean chkMaxFlag = roleInfo.checkMaxDegree(refNbr); | |
| if (!chkMaxFlag) { | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return 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.log(Level.TRACE, "RETURN"); | |
| return 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.log(Level.TRACE, "RETURN"); | |
| return RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS; | |
| } | |
| } catch (InstanceNotFoundException exc) { | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return RoleStatus.REF_MBEAN_NOT_REGISTERED; | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return 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 parameter | |
| // -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.log(Level.TRACE, "ENTRY {0} {1} {2} {3} {4} {5}", | |
| 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<>(); | |
| // 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 | RelationTypeNotFoundException | | |
| RelationNotFoundException exc) { | |
| throw new RuntimeException(exc.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 | InvalidAttributeValueException | | |
| AttributeNotFoundException | ReflectionException exc1) { | |
| throw new RuntimeException(exc1.getMessage()); | |
| } catch (MBeanException exc2) { | |
| Exception wrappedExc = exc2.getTargetException(); | |
| if (wrappedExc instanceof InvalidRoleValueException) { | |
| throw ((InvalidRoleValueException)wrappedExc); | |
| } else { | |
| throw new RuntimeException(wrappedExc.getMessage()); | |
| } | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2} {3} {4} {5} {6}", | |
| 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.log(Level.TRACE, "RETURN"); | |
| 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.log(Level.TRACE, "ENTRY {0} {1} {2}", | |
| 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 | RoleInfoNotFoundException exc) { | |
| throw new RuntimeException(exc.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 | InvalidRoleValueException exc) { | |
| throw new RuntimeException(exc.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 | ReflectionException exc1) { | |
| throw new RuntimeException(exc1.getMessage()); | |
| } catch (MBeanException exc2) { | |
| Exception wrappedExc = exc2.getTargetException(); | |
| throw new RuntimeException(wrappedExc.getMessage()); | |
| } | |
| } | |
| } | |
| } | |
| RELATION_LOGGER.log(Level.TRACE, "RETURN"); | |
| return; | |
| } | |
| } |