| /* |
| * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. Oracle designates this |
| * particular file as subject to the "Classpath" exception as provided |
| * by Oracle in the LICENSE file that accompanied this code. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| |
| package javax.management.relation; |
| |
| import static com.sun.jmx.defaults.JmxProperties.RELATION_LOGGER; |
| import static com.sun.jmx.mbeanserver.Util.cast; |
| |
| import java.util.ArrayList; |
| import java.util.Date; |
| import java.util.HashMap; |
| import java.util.Iterator; |
| import java.util.List; |
| import java.util.Map; |
| import java.util.Set; |
| import java.util.concurrent.atomic.AtomicLong; |
| import java.util.logging.Level; |
| |
| import javax.management.Attribute; |
| import javax.management.AttributeNotFoundException; |
| import javax.management.InstanceNotFoundException; |
| import javax.management.InvalidAttributeValueException; |
| import javax.management.MBeanException; |
| import javax.management.MBeanNotificationInfo; |
| import javax.management.MBeanRegistration; |
| import javax.management.MBeanServer; |
| import javax.management.MBeanServerDelegate; |
| import javax.management.MBeanServerNotification; |
| import javax.management.Notification; |
| import javax.management.NotificationBroadcasterSupport; |
| import javax.management.NotificationListener; |
| import javax.management.ObjectName; |
| import javax.management.ReflectionException; |
| |
| /** |
| * The Relation Service is in charge of creating and deleting relation types |
| * and relations, of handling the consistency and of providing query |
| * mechanisms. |
| * <P>It implements the NotificationBroadcaster by extending |
| * NotificationBroadcasterSupport to send notifications when a relation is |
| * removed from it. |
| * <P>It implements the NotificationListener interface to be able to receive |
| * notifications concerning unregistration of MBeans referenced in relation |
| * roles and of relation MBeans. |
| * <P>It implements the MBeanRegistration interface to be able to retrieve |
| * its ObjectName and MBean Server. |
| * |
| * @since 1.5 |
| */ |
| public class RelationService extends NotificationBroadcasterSupport |
| implements RelationServiceMBean, MBeanRegistration, NotificationListener { |
| |
| // |
| // Private members |
| // |
| |
| // Map associating: |
| // <relation id> -> <RelationSupport object/ObjectName> |
| // depending if the relation has been created using createRelation() |
| // method (so internally handled) or is an MBean added as a relation by the |
| // user |
| private Map<String,Object> myRelId2ObjMap = new HashMap<String,Object>(); |
| |
| // Map associating: |
| // <relation id> -> <relation type name> |
| private Map<String,String> myRelId2RelTypeMap = new HashMap<String,String>(); |
| |
| // Map associating: |
| // <relation MBean Object Name> -> <relation id> |
| private Map<ObjectName,String> myRelMBeanObjName2RelIdMap = |
| new HashMap<ObjectName,String>(); |
| |
| // Map associating: |
| // <relation type name> -> <RelationType object> |
| private Map<String,RelationType> myRelType2ObjMap = |
| new HashMap<String,RelationType>(); |
| |
| // Map associating: |
| // <relation type name> -> ArrayList of <relation id> |
| // to list all the relations of a given type |
| private Map<String,List<String>> myRelType2RelIdsMap = |
| new HashMap<String,List<String>>(); |
| |
| // Map associating: |
| // <ObjectName> -> HashMap |
| // the value HashMap mapping: |
| // <relation id> -> ArrayList of <role name> |
| // to track where a given MBean is referenced. |
| private final Map<ObjectName,Map<String,List<String>>> |
| myRefedMBeanObjName2RelIdsMap = |
| new HashMap<ObjectName,Map<String,List<String>>>(); |
| |
| // Flag to indicate if, when a notification is received for the |
| // unregistration of an MBean referenced in a relation, if an immediate |
| // "purge" of the relations (look for the relations no |
| // longer valid) has to be performed , or if that will be performed only |
| // when the purgeRelations method will be explicitly called. |
| // true is immediate purge. |
| private boolean myPurgeFlag = true; |
| |
| // Internal counter to provide sequence numbers for notifications sent by: |
| // - the Relation Service |
| // - a relation handled by the Relation Service |
| private final AtomicLong atomicSeqNo = new AtomicLong(); |
| |
| // ObjectName used to register the Relation Service in the MBean Server |
| private ObjectName myObjName = null; |
| |
| // MBean Server where the Relation Service is registered |
| private MBeanServer myMBeanServer = null; |
| |
| // Filter registered in the MBean Server with the Relation Service to be |
| // informed of referenced MBean unregistrations |
| private MBeanServerNotificationFilter myUnregNtfFilter = null; |
| |
| // List of unregistration notifications received (storage used if purge |
| // of relations when unregistering a referenced MBean is not immediate but |
| // on user request) |
| private List<MBeanServerNotification> myUnregNtfList = |
| new ArrayList<MBeanServerNotification>(); |
| |
| // |
| // Constructor |
| // |
| |
| /** |
| * Constructor. |
| * |
| * @param immediatePurgeFlag flag to indicate when a notification is |
| * received for the unregistration of an MBean referenced in a relation, if |
| * an immediate "purge" of the relations (look for the relations no |
| * longer valid) has to be performed , or if that will be performed only |
| * when the purgeRelations method will be explicitly called. |
| * <P>true is immediate purge. |
| */ |
| public RelationService(boolean immediatePurgeFlag) { |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "RelationService"); |
| |
| setPurgeFlag(immediatePurgeFlag); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "RelationService"); |
| return; |
| } |
| |
| /** |
| * Checks if the Relation Service is active. |
| * Current condition is that the Relation Service must be registered in the |
| * MBean Server |
| * |
| * @exception RelationServiceNotRegisteredException if it is not |
| * registered |
| */ |
| public void isActive() |
| throws RelationServiceNotRegisteredException { |
| if (myMBeanServer == null) { |
| // MBean Server not set by preRegister(): relation service not |
| // registered |
| String excMsg = |
| "Relation Service not registered in the MBean Server."; |
| throw new RelationServiceNotRegisteredException(excMsg); |
| } |
| return; |
| } |
| |
| // |
| // MBeanRegistration interface |
| // |
| |
| // Pre-registration: retrieves its ObjectName and MBean Server |
| // |
| // No exception thrown. |
| public ObjectName preRegister(MBeanServer server, |
| ObjectName name) |
| throws Exception { |
| |
| myMBeanServer = server; |
| myObjName = name; |
| return name; |
| } |
| |
| // Post-registration: does nothing |
| public void postRegister(Boolean registrationDone) { |
| return; |
| } |
| |
| // Pre-unregistration: does nothing |
| public void preDeregister() |
| throws Exception { |
| return; |
| } |
| |
| // Post-unregistration: does nothing |
| public void postDeregister() { |
| return; |
| } |
| |
| // |
| // Accessors |
| // |
| |
| /** |
| * Returns the flag to indicate if when a notification is received for the |
| * unregistration of an MBean referenced in a relation, if an immediate |
| * "purge" of the relations (look for the relations no longer valid) |
| * has to be performed , or if that will be performed only when the |
| * purgeRelations method will be explicitly called. |
| * <P>true is immediate purge. |
| * |
| * @return true if purges are automatic. |
| * |
| * @see #setPurgeFlag |
| */ |
| public boolean getPurgeFlag() { |
| return myPurgeFlag; |
| } |
| |
| /** |
| * Sets the flag to indicate if when a notification is received for the |
| * unregistration of an MBean referenced in a relation, if an immediate |
| * "purge" of the relations (look for the relations no longer valid) |
| * has to be performed , or if that will be performed only when the |
| * purgeRelations method will be explicitly called. |
| * <P>true is immediate purge. |
| * |
| * @param purgeFlag flag |
| * |
| * @see #getPurgeFlag |
| */ |
| public void setPurgeFlag(boolean purgeFlag) { |
| |
| myPurgeFlag = purgeFlag; |
| return; |
| } |
| |
| // |
| // Relation type handling |
| // |
| |
| /** |
| * Creates a relation type (a RelationTypeSupport object) with given |
| * role infos (provided by the RoleInfo objects), and adds it in the |
| * Relation Service. |
| * |
| * @param relationTypeName name of the relation type |
| * @param roleInfoArray array of role infos |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception InvalidRelationTypeException If: |
| * <P>- there is already a relation type with that name |
| * <P>- the same name has been used for two different role infos |
| * <P>- no role info provided |
| * <P>- one null role info provided |
| */ |
| public void createRelationType(String relationTypeName, |
| RoleInfo[] roleInfoArray) |
| throws IllegalArgumentException, |
| InvalidRelationTypeException { |
| |
| if (relationTypeName == null || roleInfoArray == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "createRelationType", relationTypeName); |
| |
| // Can throw an InvalidRelationTypeException |
| RelationType relType = |
| new RelationTypeSupport(relationTypeName, roleInfoArray); |
| |
| addRelationTypeInt(relType); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "createRelationType"); |
| return; |
| } |
| |
| /** |
| * Adds given object as a relation type. The object is expected to |
| * implement the RelationType interface. |
| * |
| * @param relationTypeObj relation type object (implementing the |
| * RelationType interface) |
| * |
| * @exception IllegalArgumentException if null parameter or if |
| * {@link RelationType#getRelationTypeName |
| * relationTypeObj.getRelationTypeName()} returns null. |
| * @exception InvalidRelationTypeException if: |
| * <P>- the same name has been used for two different roles |
| * <P>- no role info provided |
| * <P>- one null role info provided |
| * <P>- there is already a relation type with that name |
| */ |
| public void addRelationType(RelationType relationTypeObj) |
| throws IllegalArgumentException, |
| InvalidRelationTypeException { |
| |
| if (relationTypeObj == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "addRelationType"); |
| |
| // Checks the role infos |
| List<RoleInfo> roleInfoList = relationTypeObj.getRoleInfos(); |
| if (roleInfoList == null) { |
| String excMsg = "No role info provided."; |
| throw new InvalidRelationTypeException(excMsg); |
| } |
| |
| RoleInfo[] roleInfoArray = new RoleInfo[roleInfoList.size()]; |
| int i = 0; |
| for (RoleInfo currRoleInfo : roleInfoList) { |
| roleInfoArray[i] = currRoleInfo; |
| i++; |
| } |
| // Can throw InvalidRelationTypeException |
| RelationTypeSupport.checkRoleInfos(roleInfoArray); |
| |
| addRelationTypeInt(relationTypeObj); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "addRelationType"); |
| return; |
| } |
| |
| /** |
| * Retrieves names of all known relation types. |
| * |
| * @return ArrayList of relation type names (Strings) |
| */ |
| public List<String> getAllRelationTypeNames() { |
| ArrayList<String> result; |
| synchronized(myRelType2ObjMap) { |
| result = new ArrayList<String>(myRelType2ObjMap.keySet()); |
| } |
| return result; |
| } |
| |
| /** |
| * Retrieves list of role infos (RoleInfo objects) of a given relation |
| * type. |
| * |
| * @param relationTypeName name of relation type |
| * |
| * @return ArrayList of RoleInfo. |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationTypeNotFoundException if there is no relation type |
| * with that name. |
| */ |
| public List<RoleInfo> getRoleInfos(String relationTypeName) |
| throws IllegalArgumentException, |
| RelationTypeNotFoundException { |
| |
| if (relationTypeName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRoleInfos", relationTypeName); |
| |
| // Can throw a RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getRoleInfos"); |
| return relType.getRoleInfos(); |
| } |
| |
| /** |
| * Retrieves role info for given role name of a given relation type. |
| * |
| * @param relationTypeName name of relation type |
| * @param roleInfoName name of role |
| * |
| * @return RoleInfo object. |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationTypeNotFoundException if the relation type is not |
| * known in the Relation Service |
| * @exception RoleInfoNotFoundException if the role is not part of the |
| * relation type. |
| */ |
| public RoleInfo getRoleInfo(String relationTypeName, |
| String roleInfoName) |
| throws IllegalArgumentException, |
| RelationTypeNotFoundException, |
| RoleInfoNotFoundException { |
| |
| if (relationTypeName == null || roleInfoName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRoleInfo", new Object[] {relationTypeName, roleInfoName}); |
| |
| // Can throw a RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| // Can throw a RoleInfoNotFoundException |
| RoleInfo roleInfo = relType.getRoleInfo(roleInfoName); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getRoleInfo"); |
| return roleInfo; |
| } |
| |
| /** |
| * Removes given relation type from Relation Service. |
| * <P>The relation objects of that type will be removed from the |
| * Relation Service. |
| * |
| * @param relationTypeName name of the relation type to be removed |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationTypeNotFoundException If there is no relation type |
| * with that name |
| */ |
| public void removeRelationType(String relationTypeName) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RelationTypeNotFoundException { |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| if (relationTypeName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "removeRelationType", relationTypeName); |
| |
| // Checks if the relation type to be removed exists |
| // Can throw a RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| // Retrieves the relation ids for relations of that type |
| List<String> relIdList = null; |
| synchronized(myRelType2RelIdsMap) { |
| // Note: take a copy of the list as it is a part of a map that |
| // will be updated by removeRelation() below. |
| List<String> relIdList1 = |
| myRelType2RelIdsMap.get(relationTypeName); |
| if (relIdList1 != null) { |
| relIdList = new ArrayList<String>(relIdList1); |
| } |
| } |
| |
| // Removes the relation type from all maps |
| synchronized(myRelType2ObjMap) { |
| myRelType2ObjMap.remove(relationTypeName); |
| } |
| synchronized(myRelType2RelIdsMap) { |
| myRelType2RelIdsMap.remove(relationTypeName); |
| } |
| |
| // Removes all relations of that type |
| if (relIdList != null) { |
| for (String currRelId : relIdList) { |
| // Note: will remove it from myRelId2RelTypeMap :) |
| // |
| // Can throw RelationServiceNotRegisteredException (detected |
| // above) |
| // Shall not throw a RelationNotFoundException |
| try { |
| removeRelation(currRelId); |
| } catch (RelationNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "removeRelationType"); |
| return; |
| } |
| |
| // |
| // Relation handling |
| // |
| |
| /** |
| * Creates a simple relation (represented by a RelationSupport object) of |
| * given relation type, and adds it in the Relation Service. |
| * <P>Roles are initialized according to the role list provided in |
| * parameter. The ones not initialized in this way are set to an empty |
| * ArrayList of ObjectNames. |
| * <P>A RelationNotification, with type RELATION_BASIC_CREATION, is sent. |
| * |
| * @param relationId relation identifier, to identify uniquely the relation |
| * inside the Relation Service |
| * @param relationTypeName name of the relation type (has to be created |
| * in the Relation Service) |
| * @param roleList role list to initialize roles of the relation (can |
| * be null). |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception IllegalArgumentException if null parameter, except the role |
| * list which can be null if no role initialization |
| * @exception RoleNotFoundException if a value is provided for a role |
| * that does not exist in the relation type |
| * @exception InvalidRelationIdException if relation id already used |
| * @exception RelationTypeNotFoundException if relation type not known in |
| * Relation Service |
| * @exception InvalidRoleValueException if: |
| * <P>- the same role name is used for two different roles |
| * <P>- the number of referenced MBeans in given value is less than |
| * expected minimum degree |
| * <P>- the number of referenced MBeans in provided value exceeds expected |
| * maximum degree |
| * <P>- one referenced MBean in the value is not an Object of the MBean |
| * class expected for that role |
| * <P>- an MBean provided for that role does not exist |
| */ |
| public void createRelation(String relationId, |
| String relationTypeName, |
| RoleList roleList) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RoleNotFoundException, |
| InvalidRelationIdException, |
| RelationTypeNotFoundException, |
| InvalidRoleValueException { |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| if (relationId == null || |
| relationTypeName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "createRelation", |
| new Object[] {relationId, relationTypeName, roleList}); |
| |
| // Creates RelationSupport object |
| // Can throw InvalidRoleValueException |
| RelationSupport relObj = new RelationSupport(relationId, |
| myObjName, |
| relationTypeName, |
| roleList); |
| |
| // Adds relation object as a relation into the Relation Service |
| // Can throw RoleNotFoundException, InvalidRelationId, |
| // RelationTypeNotFoundException, InvalidRoleValueException |
| // |
| // Cannot throw MBeanException |
| addRelationInt(true, |
| relObj, |
| null, |
| relationId, |
| relationTypeName, |
| roleList); |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "createRelation"); |
| return; |
| } |
| |
| /** |
| * Adds an MBean created by the user (and registered by him in the MBean |
| * Server) as a relation in the Relation Service. |
| * <P>To be added as a relation, the MBean must conform to the |
| * following: |
| * <P>- implement the Relation interface |
| * <P>- have for RelationService ObjectName the ObjectName of current |
| * Relation Service |
| * <P>- have a relation id unique and unused in current Relation Service |
| * <P>- have for relation type a relation type created in the Relation |
| * Service |
| * <P>- have roles conforming to the role info provided in the relation |
| * type. |
| * |
| * @param relationObjectName ObjectName of the relation MBean to be added. |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception NoSuchMethodException If the MBean does not implement the |
| * Relation interface |
| * @exception InvalidRelationIdException if: |
| * <P>- no relation identifier in MBean |
| * <P>- the relation identifier is already used in the Relation Service |
| * @exception InstanceNotFoundException if the MBean for given ObjectName |
| * has not been registered |
| * @exception InvalidRelationServiceException if: |
| * <P>- no Relation Service name in MBean |
| * <P>- the Relation Service name in the MBean is not the one of the |
| * current Relation Service |
| * @exception RelationTypeNotFoundException if: |
| * <P>- no relation type name in MBean |
| * <P>- the relation type name in MBean does not correspond to a relation |
| * type created in the Relation Service |
| * @exception InvalidRoleValueException if: |
| * <P>- the number of referenced MBeans in a role is less than |
| * expected minimum degree |
| * <P>- the number of referenced MBeans in a role exceeds expected |
| * maximum degree |
| * <P>- one referenced MBean in the value is not an Object of the MBean |
| * class expected for that role |
| * <P>- an MBean provided for a role does not exist |
| * @exception RoleNotFoundException if a value is provided for a role |
| * that does not exist in the relation type |
| */ |
| public void addRelation(ObjectName relationObjectName) |
| throws IllegalArgumentException, |
| RelationServiceNotRegisteredException, |
| NoSuchMethodException, |
| InvalidRelationIdException, |
| InstanceNotFoundException, |
| InvalidRelationServiceException, |
| RelationTypeNotFoundException, |
| RoleNotFoundException, |
| InvalidRoleValueException { |
| |
| if (relationObjectName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "addRelation", relationObjectName); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Checks that the relation MBean implements the Relation interface. |
| // It will also check that the provided ObjectName corresponds to a |
| // registered MBean (else will throw an InstanceNotFoundException) |
| if ((!(myMBeanServer.isInstanceOf(relationObjectName, "javax.management.relation.Relation")))) { |
| String excMsg = "This MBean does not implement the Relation interface."; |
| throw new NoSuchMethodException(excMsg); |
| } |
| // Checks there is a relation id in the relation MBean (its uniqueness |
| // is checked in addRelationInt()) |
| // Can throw InstanceNotFoundException (but detected above) |
| // No MBeanException as no exception raised by this method, and no |
| // ReflectionException |
| String relId; |
| try { |
| relId = (String)(myMBeanServer.getAttribute(relationObjectName, |
| "RelationId")); |
| |
| } catch (MBeanException exc1) { |
| throw new RuntimeException( |
| (exc1.getTargetException()).getMessage()); |
| } catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (AttributeNotFoundException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } |
| |
| if (relId == null) { |
| String excMsg = "This MBean does not provide a relation id."; |
| throw new InvalidRelationIdException(excMsg); |
| } |
| // Checks that the Relation Service where the relation MBean is |
| // expected to be added is the current one |
| // Can throw InstanceNotFoundException (but detected above) |
| // No MBeanException as no exception raised by this method, no |
| // ReflectionException |
| ObjectName relServObjName; |
| try { |
| relServObjName = (ObjectName) |
| (myMBeanServer.getAttribute(relationObjectName, |
| "RelationServiceName")); |
| |
| } catch (MBeanException exc1) { |
| throw new RuntimeException( |
| (exc1.getTargetException()).getMessage()); |
| } catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (AttributeNotFoundException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } |
| |
| boolean badRelServFlag = false; |
| if (relServObjName == null) { |
| badRelServFlag = true; |
| |
| } else if (!(relServObjName.equals(myObjName))) { |
| badRelServFlag = true; |
| } |
| if (badRelServFlag) { |
| String excMsg = "The Relation Service referenced in the MBean is not the current one."; |
| throw new InvalidRelationServiceException(excMsg); |
| } |
| // Checks that a relation type has been specified for the relation |
| // Can throw InstanceNotFoundException (but detected above) |
| // No MBeanException as no exception raised by this method, no |
| // ReflectionException |
| String relTypeName; |
| try { |
| relTypeName = (String)(myMBeanServer.getAttribute(relationObjectName, |
| "RelationTypeName")); |
| |
| } catch (MBeanException exc1) { |
| throw new RuntimeException( |
| (exc1.getTargetException()).getMessage()); |
| }catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (AttributeNotFoundException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } |
| if (relTypeName == null) { |
| String excMsg = "No relation type provided."; |
| throw new RelationTypeNotFoundException(excMsg); |
| } |
| // Retrieves all roles without considering read mode |
| // Can throw InstanceNotFoundException (but detected above) |
| // No MBeanException as no exception raised by this method, no |
| // ReflectionException |
| RoleList roleList; |
| try { |
| roleList = (RoleList)(myMBeanServer.invoke(relationObjectName, |
| "retrieveAllRoles", |
| null, |
| null)); |
| } catch (MBeanException exc1) { |
| throw new RuntimeException( |
| (exc1.getTargetException()).getMessage()); |
| } catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } |
| |
| // Can throw RoleNotFoundException, InvalidRelationIdException, |
| // RelationTypeNotFoundException, InvalidRoleValueException |
| addRelationInt(false, |
| null, |
| relationObjectName, |
| relId, |
| relTypeName, |
| roleList); |
| // Adds relation MBean ObjectName in map |
| synchronized(myRelMBeanObjName2RelIdMap) { |
| myRelMBeanObjName2RelIdMap.put(relationObjectName, relId); |
| } |
| |
| // Updates flag to specify that the relation is managed by the Relation |
| // Service |
| // This flag and setter are inherited from RelationSupport and not parts |
| // of the Relation interface, so may be not supported. |
| try { |
| myMBeanServer.setAttribute(relationObjectName, |
| new Attribute( |
| "RelationServiceManagementFlag", |
| Boolean.TRUE)); |
| } catch (Exception exc) { |
| // OK : The flag is not supported. |
| } |
| |
| // Updates listener information to received notification for |
| // unregistration of this MBean |
| List<ObjectName> newRefList = new ArrayList<ObjectName>(); |
| newRefList.add(relationObjectName); |
| updateUnregistrationListener(newRefList, null); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "addRelation"); |
| return; |
| } |
| |
| /** |
| * If the relation is represented by an MBean (created by the user and |
| * added as a relation in the Relation Service), returns the ObjectName of |
| * the MBean. |
| * |
| * @param relationId relation id identifying the relation |
| * |
| * @return ObjectName of the corresponding relation MBean, or null if |
| * the relation is not an MBean. |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException there is no relation associated |
| * to that id |
| */ |
| public ObjectName isRelationMBean(String relationId) |
| throws IllegalArgumentException, |
| RelationNotFoundException{ |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "isRelationMBean", relationId); |
| |
| // Can throw RelationNotFoundException |
| Object result = getRelation(relationId); |
| if (result instanceof ObjectName) { |
| return ((ObjectName)result); |
| } else { |
| return null; |
| } |
| } |
| |
| /** |
| * Returns the relation id associated to the given ObjectName if the |
| * MBean has been added as a relation in the Relation Service. |
| * |
| * @param objectName ObjectName of supposed relation |
| * |
| * @return relation id (String) or null (if the ObjectName is not a |
| * relation handled by the Relation Service) |
| * |
| * @exception IllegalArgumentException if null parameter |
| */ |
| public String isRelation(ObjectName objectName) |
| throws IllegalArgumentException { |
| |
| if (objectName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "isRelation", objectName); |
| |
| String result = null; |
| synchronized(myRelMBeanObjName2RelIdMap) { |
| String relId = myRelMBeanObjName2RelIdMap.get(objectName); |
| if (relId != null) { |
| result = relId; |
| } |
| } |
| return result; |
| } |
| |
| /** |
| * Checks if there is a relation identified in Relation Service with given |
| * relation id. |
| * |
| * @param relationId relation id identifying the relation |
| * |
| * @return boolean: true if there is a relation, false else |
| * |
| * @exception IllegalArgumentException if null parameter |
| */ |
| public Boolean hasRelation(String relationId) |
| throws IllegalArgumentException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "hasRelation", relationId); |
| |
| try { |
| // Can throw RelationNotFoundException |
| Object result = getRelation(relationId); |
| return true; |
| } catch (RelationNotFoundException exc) { |
| return false; |
| } |
| } |
| |
| /** |
| * Returns all the relation ids for all the relations handled by the |
| * Relation Service. |
| * |
| * @return ArrayList of String |
| */ |
| public List<String> getAllRelationIds() { |
| List<String> result; |
| synchronized(myRelId2ObjMap) { |
| result = new ArrayList<String>(myRelId2ObjMap.keySet()); |
| } |
| return result; |
| } |
| |
| /** |
| * Checks if given Role can be read in a relation of the given type. |
| * |
| * @param roleName name of role to be checked |
| * @param relationTypeName name of the relation type |
| * |
| * @return an Integer wrapping an integer corresponding to possible |
| * problems represented as constants in RoleUnresolved: |
| * <P>- 0 if role can be read |
| * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME |
| * <P>- integer corresponding to RoleStatus.ROLE_NOT_READABLE |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationTypeNotFoundException if the relation type is not |
| * known in the Relation Service |
| */ |
| public Integer checkRoleReading(String roleName, |
| String relationTypeName) |
| throws IllegalArgumentException, |
| RelationTypeNotFoundException { |
| |
| if (roleName == null || relationTypeName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "checkRoleReading", new Object[] {roleName, relationTypeName}); |
| |
| Integer result; |
| |
| // Can throw a RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| try { |
| // Can throw a RoleInfoNotFoundException to be transformed into |
| // returned value RoleStatus.NO_ROLE_WITH_NAME |
| RoleInfo roleInfo = relType.getRoleInfo(roleName); |
| |
| result = checkRoleInt(1, |
| roleName, |
| null, |
| roleInfo, |
| false); |
| |
| } catch (RoleInfoNotFoundException exc) { |
| result = Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleReading"); |
| return result; |
| } |
| |
| /** |
| * Checks if given Role can be set in a relation of given type. |
| * |
| * @param role role to be checked |
| * @param relationTypeName name of relation type |
| * @param initFlag flag to specify that the checking is done for the |
| * initialization of a role, write access shall not be verified. |
| * |
| * @return an Integer wrapping an integer corresponding to possible |
| * problems represented as constants in RoleUnresolved: |
| * <P>- 0 if role can be set |
| * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME |
| * <P>- integer for RoleStatus.ROLE_NOT_WRITABLE |
| * <P>- integer for RoleStatus.LESS_THAN_MIN_ROLE_DEGREE |
| * <P>- integer for RoleStatus.MORE_THAN_MAX_ROLE_DEGREE |
| * <P>- integer for RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS |
| * <P>- integer for RoleStatus.REF_MBEAN_NOT_REGISTERED |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationTypeNotFoundException if unknown relation type |
| */ |
| public Integer checkRoleWriting(Role role, |
| String relationTypeName, |
| Boolean initFlag) |
| throws IllegalArgumentException, |
| RelationTypeNotFoundException { |
| |
| if (role == null || |
| relationTypeName == null || |
| initFlag == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "checkRoleWriting", |
| new Object[] {role, relationTypeName, initFlag}); |
| |
| // Can throw a RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| String roleName = role.getRoleName(); |
| List<ObjectName> roleValue = role.getRoleValue(); |
| boolean writeChkFlag = true; |
| if (initFlag.booleanValue()) { |
| writeChkFlag = false; |
| } |
| |
| RoleInfo roleInfo; |
| try { |
| roleInfo = relType.getRoleInfo(roleName); |
| } catch (RoleInfoNotFoundException exc) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleWriting"); |
| return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); |
| } |
| |
| Integer result = checkRoleInt(2, |
| roleName, |
| roleValue, |
| roleInfo, |
| writeChkFlag); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleWriting"); |
| return result; |
| } |
| |
| /** |
| * Sends a notification (RelationNotification) for a relation creation. |
| * The notification type is: |
| * <P>- RelationNotification.RELATION_BASIC_CREATION if the relation is an |
| * object internal to the Relation Service |
| * <P>- RelationNotification.RELATION_MBEAN_CREATION if the relation is a |
| * MBean added as a relation. |
| * <P>The source object is the Relation Service itself. |
| * <P>It is called in Relation Service createRelation() and |
| * addRelation() methods. |
| * |
| * @param relationId relation identifier of the updated relation |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if there is no relation for given |
| * relation id |
| */ |
| public void sendRelationCreationNotification(String relationId) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "sendRelationCreationNotification", relationId); |
| |
| // Message |
| StringBuilder ntfMsg = new StringBuilder("Creation of relation "); |
| ntfMsg.append(relationId); |
| |
| // Can throw RelationNotFoundException |
| sendNotificationInt(1, |
| ntfMsg.toString(), |
| relationId, |
| null, |
| null, |
| null, |
| null); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "sendRelationCreationNotification"); |
| return; |
| } |
| |
| /** |
| * Sends a notification (RelationNotification) for a role update in the |
| * given relation. The notification type is: |
| * <P>- RelationNotification.RELATION_BASIC_UPDATE if the relation is an |
| * object internal to the Relation Service |
| * <P>- RelationNotification.RELATION_MBEAN_UPDATE if the relation is a |
| * MBean added as a relation. |
| * <P>The source object is the Relation Service itself. |
| * <P>It is called in relation MBean setRole() (for given role) and |
| * setRoles() (for each role) methods (implementation provided in |
| * RelationSupport class). |
| * <P>It is also called in Relation Service setRole() (for given role) and |
| * setRoles() (for each role) methods. |
| * |
| * @param relationId relation identifier of the updated relation |
| * @param newRole new role (name and new value) |
| * @param oldValue old role value (List of ObjectName objects) |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if there is no relation for given |
| * relation id |
| */ |
| public void sendRoleUpdateNotification(String relationId, |
| Role newRole, |
| List<ObjectName> oldValue) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null || |
| newRole == null || |
| oldValue == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| if (!(oldValue instanceof ArrayList<?>)) |
| oldValue = new ArrayList<ObjectName>(oldValue); |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "sendRoleUpdateNotification", |
| new Object[] {relationId, newRole, oldValue}); |
| |
| String roleName = newRole.getRoleName(); |
| List<ObjectName> newRoleVal = newRole.getRoleValue(); |
| |
| // Message |
| String newRoleValString = Role.roleValueToString(newRoleVal); |
| String oldRoleValString = Role.roleValueToString(oldValue); |
| StringBuilder ntfMsg = new StringBuilder("Value of role "); |
| ntfMsg.append(roleName); |
| ntfMsg.append(" has changed\nOld value:\n"); |
| ntfMsg.append(oldRoleValString); |
| ntfMsg.append("\nNew value:\n"); |
| ntfMsg.append(newRoleValString); |
| |
| // Can throw a RelationNotFoundException |
| sendNotificationInt(2, |
| ntfMsg.toString(), |
| relationId, |
| null, |
| roleName, |
| newRoleVal, |
| oldValue); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "sendRoleUpdateNotification"); |
| } |
| |
| /** |
| * Sends a notification (RelationNotification) for a relation removal. |
| * The notification type is: |
| * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation is an |
| * object internal to the Relation Service |
| * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is a |
| * MBean added as a relation. |
| * <P>The source object is the Relation Service itself. |
| * <P>It is called in Relation Service removeRelation() method. |
| * |
| * @param relationId relation identifier of the updated relation |
| * @param unregMBeanList List of ObjectNames of MBeans expected |
| * to be unregistered due to relation removal (can be null) |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if there is no relation for given |
| * relation id |
| */ |
| public void sendRelationRemovalNotification(String relationId, |
| List<ObjectName> unregMBeanList) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter"; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "sendRelationRemovalNotification", |
| new Object[] {relationId, unregMBeanList}); |
| |
| // Can throw RelationNotFoundException |
| sendNotificationInt(3, |
| "Removal of relation " + relationId, |
| relationId, |
| unregMBeanList, |
| null, |
| null, |
| null); |
| |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "sendRelationRemovalNotification"); |
| return; |
| } |
| |
| /** |
| * Handles update of the Relation Service role map for the update of given |
| * role in given relation. |
| * <P>It is called in relation MBean setRole() (for given role) and |
| * setRoles() (for each role) methods (implementation provided in |
| * RelationSupport class). |
| * <P>It is also called in Relation Service setRole() (for given role) and |
| * setRoles() (for each role) methods. |
| * <P>To allow the Relation Service to maintain the consistency (in case |
| * of MBean unregistration) and to be able to perform queries, this method |
| * must be called when a role is updated. |
| * |
| * @param relationId relation identifier of the updated relation |
| * @param newRole new role (name and new value) |
| * @param oldValue old role value (List of ObjectName objects) |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception RelationNotFoundException if no relation for given id. |
| */ |
| public void updateRoleMap(String relationId, |
| Role newRole, |
| List<ObjectName> oldValue) |
| throws IllegalArgumentException, |
| RelationServiceNotRegisteredException, |
| RelationNotFoundException { |
| |
| if (relationId == null || |
| newRole == null || |
| oldValue == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "updateRoleMap", new Object[] {relationId, newRole, oldValue}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Verifies the relation has been added in the Relation Service |
| // Can throw a RelationNotFoundException |
| Object result = getRelation(relationId); |
| |
| String roleName = newRole.getRoleName(); |
| List<ObjectName> newRoleValue = newRole.getRoleValue(); |
| // Note: no need to test if oldValue not null before cloning, |
| // tested above. |
| List<ObjectName> oldRoleValue = |
| new ArrayList<ObjectName>(oldValue); |
| |
| // List of ObjectNames of new referenced MBeans |
| List<ObjectName> newRefList = new ArrayList<ObjectName>(); |
| |
| for (ObjectName currObjName : newRoleValue) { |
| |
| // Checks if this ObjectName was already present in old value |
| // Note: use copy (oldRoleValue) instead of original |
| // oldValue to speed up, as oldRoleValue is decreased |
| // by removing unchanged references :) |
| int currObjNamePos = oldRoleValue.indexOf(currObjName); |
| |
| if (currObjNamePos == -1) { |
| // New reference to an ObjectName |
| |
| // Stores this reference into map |
| // Returns true if new reference, false if MBean already |
| // referenced |
| boolean isNewFlag = addNewMBeanReference(currObjName, |
| relationId, |
| roleName); |
| |
| if (isNewFlag) { |
| // Adds it into list of new reference |
| newRefList.add(currObjName); |
| } |
| |
| } else { |
| // MBean was already referenced in old value |
| |
| // Removes it from old value (local list) to ignore it when |
| // looking for remove MBean references |
| oldRoleValue.remove(currObjNamePos); |
| } |
| } |
| |
| // List of ObjectNames of MBeans no longer referenced |
| List<ObjectName> obsRefList = new ArrayList<ObjectName>(); |
| |
| // Each ObjectName remaining in oldRoleValue is an ObjectName no longer |
| // referenced in new value |
| for (ObjectName currObjName : oldRoleValue) { |
| // Removes MBean reference from map |
| // Returns true if the MBean is no longer referenced in any |
| // relation |
| boolean noLongerRefFlag = removeMBeanReference(currObjName, |
| relationId, |
| roleName, |
| false); |
| |
| if (noLongerRefFlag) { |
| // Adds it into list of references to be removed |
| obsRefList.add(currObjName); |
| } |
| } |
| |
| // To avoid having one listener per ObjectName of referenced MBean, |
| // and to increase performances, there is only one listener recording |
| // all ObjectNames of interest |
| updateUnregistrationListener(newRefList, obsRefList); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "updateRoleMap"); |
| return; |
| } |
| |
| /** |
| * Removes given relation from the Relation Service. |
| * <P>A RelationNotification notification is sent, its type being: |
| * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation was |
| * only internal to the Relation Service |
| * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is |
| * registered as an MBean. |
| * <P>For MBeans referenced in such relation, nothing will be done, |
| * |
| * @param relationId relation id of the relation to be removed |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation corresponding to |
| * given relation id |
| */ |
| public void removeRelation(String relationId) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RelationNotFoundException { |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "removeRelation", relationId); |
| |
| // Checks there is a relation with this id |
| // Can throw RelationNotFoundException |
| Object result = getRelation(relationId); |
| |
| // Removes it from listener filter |
| if (result instanceof ObjectName) { |
| List<ObjectName> obsRefList = new ArrayList<ObjectName>(); |
| obsRefList.add((ObjectName)result); |
| // Can throw a RelationServiceNotRegisteredException |
| updateUnregistrationListener(null, obsRefList); |
| } |
| |
| // Sends a notification |
| // Note: has to be done FIRST as needs the relation to be still in the |
| // Relation Service |
| // No RelationNotFoundException as checked above |
| |
| // Revisit [cebro] Handle CIM "Delete" and "IfDeleted" qualifiers: |
| // deleting the relation can mean to delete referenced MBeans. In |
| // that case, MBeans to be unregistered are put in a list sent along |
| // with the notification below |
| |
| // Can throw a RelationNotFoundException (but detected above) |
| sendRelationRemovalNotification(relationId, null); |
| |
| // Removes the relation from various internal maps |
| |
| // - MBean reference map |
| // Retrieves the MBeans referenced in this relation |
| // Note: here we cannot use removeMBeanReference() because it would |
| // require to know the MBeans referenced in the relation. For |
| // that it would be necessary to call 'getReferencedMBeans()' |
| // on the relation itself. Ok if it is an internal one, but if |
| // it is an MBean, it is possible it is already unregistered, so |
| // not available through the MBean Server. |
| List<ObjectName> refMBeanList = new ArrayList<ObjectName>(); |
| // List of MBeans no longer referenced in any relation, to be |
| // removed fom the map |
| List<ObjectName> nonRefObjNameList = new ArrayList<ObjectName>(); |
| |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| |
| for (ObjectName currRefObjName : |
| myRefedMBeanObjName2RelIdsMap.keySet()) { |
| |
| // Retrieves relations where the MBean is referenced |
| Map<String,List<String>> relIdMap = |
| myRefedMBeanObjName2RelIdsMap.get(currRefObjName); |
| |
| if (relIdMap.containsKey(relationId)) { |
| relIdMap.remove(relationId); |
| refMBeanList.add(currRefObjName); |
| } |
| |
| if (relIdMap.isEmpty()) { |
| // MBean no longer referenced |
| // Note: do not remove it here because pointed by the |
| // iterator! |
| nonRefObjNameList.add(currRefObjName); |
| } |
| } |
| |
| // Cleans MBean reference map by removing MBeans no longer |
| // referenced |
| for (ObjectName currRefObjName : nonRefObjNameList) { |
| myRefedMBeanObjName2RelIdsMap.remove(currRefObjName); |
| } |
| } |
| |
| // - Relation id to object map |
| synchronized(myRelId2ObjMap) { |
| myRelId2ObjMap.remove(relationId); |
| } |
| |
| if (result instanceof ObjectName) { |
| // - ObjectName to relation id map |
| synchronized(myRelMBeanObjName2RelIdMap) { |
| myRelMBeanObjName2RelIdMap.remove((ObjectName)result); |
| } |
| } |
| |
| // Relation id to relation type name map |
| // First retrieves the relation type name |
| String relTypeName; |
| synchronized(myRelId2RelTypeMap) { |
| relTypeName = myRelId2RelTypeMap.get(relationId); |
| myRelId2RelTypeMap.remove(relationId); |
| } |
| // - Relation type name to relation id map |
| synchronized(myRelType2RelIdsMap) { |
| List<String> relIdList = myRelType2RelIdsMap.get(relTypeName); |
| if (relIdList != null) { |
| // Can be null if called from removeRelationType() |
| relIdList.remove(relationId); |
| if (relIdList.isEmpty()) { |
| // No other relation of that type |
| myRelType2RelIdsMap.remove(relTypeName); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "removeRelation"); |
| return; |
| } |
| |
| /** |
| * Purges the relations. |
| * |
| * <P>Depending on the purgeFlag value, this method is either called |
| * automatically when a notification is received for the unregistration of |
| * an MBean referenced in a relation (if the flag is set to true), or not |
| * (if the flag is set to false). |
| * <P>In that case it is up to the user to call it to maintain the |
| * consistency of the relations. To be kept in mind that if an MBean is |
| * unregistered and the purge not done immediately, if the ObjectName is |
| * reused and assigned to another MBean referenced in a relation, calling |
| * manually this purgeRelations() method will cause trouble, as will |
| * consider the ObjectName as corresponding to the unregistered MBean, not |
| * seeing the new one. |
| * |
| * <P>The behavior depends on the cardinality of the role where the |
| * unregistered MBean is referenced: |
| * <P>- if removing one MBean reference in the role makes its number of |
| * references less than the minimum degree, the relation has to be removed. |
| * <P>- if the remaining number of references after removing the MBean |
| * reference is still in the cardinality range, keep the relation and |
| * update it calling its handleMBeanUnregistration() callback. |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server. |
| */ |
| public void purgeRelations() |
| throws RelationServiceNotRegisteredException { |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "purgeRelations"); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Revisit [cebro] Handle the CIM "Delete" and "IfDeleted" qualifier: |
| // if the unregistered MBean has the "IfDeleted" qualifier, |
| // possible that the relation itself or other referenced MBeans |
| // have to be removed (then a notification would have to be sent |
| // to inform that they should be unregistered. |
| |
| |
| // Clones the list of notifications to be able to still receive new |
| // notifications while proceeding those ones |
| List<MBeanServerNotification> localUnregNtfList; |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| localUnregNtfList = |
| new ArrayList<MBeanServerNotification>(myUnregNtfList); |
| // Resets list |
| myUnregNtfList = new ArrayList<MBeanServerNotification>(); |
| } |
| |
| |
| // Updates the listener filter to avoid receiving notifications for |
| // those MBeans again |
| // Makes also a local "myRefedMBeanObjName2RelIdsMap" map, mapping |
| // ObjectName -> relId -> roles, to remove the MBean from the global |
| // map |
| // List of references to be removed from the listener filter |
| List<ObjectName> obsRefList = new ArrayList<ObjectName>(); |
| // Map including ObjectNames for unregistered MBeans, with |
| // referencing relation ids and roles |
| Map<ObjectName,Map<String,List<String>>> localMBean2RelIdMap = |
| new HashMap<ObjectName,Map<String,List<String>>>(); |
| |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| for (MBeanServerNotification currNtf : localUnregNtfList) { |
| |
| ObjectName unregMBeanName = currNtf.getMBeanName(); |
| |
| // Adds the unregsitered MBean in the list of references to |
| // remove from the listener filter |
| obsRefList.add(unregMBeanName); |
| |
| // Retrieves the associated map of relation ids and roles |
| Map<String,List<String>> relIdMap = |
| myRefedMBeanObjName2RelIdsMap.get(unregMBeanName); |
| localMBean2RelIdMap.put(unregMBeanName, relIdMap); |
| |
| myRefedMBeanObjName2RelIdsMap.remove(unregMBeanName); |
| } |
| } |
| |
| // Updates the listener |
| // Can throw RelationServiceNotRegisteredException |
| updateUnregistrationListener(null, obsRefList); |
| |
| for (MBeanServerNotification currNtf : localUnregNtfList) { |
| |
| ObjectName unregMBeanName = currNtf.getMBeanName(); |
| |
| // Retrieves the relations where the MBean is referenced |
| Map<String,List<String>> localRelIdMap = |
| localMBean2RelIdMap.get(unregMBeanName); |
| |
| // List of relation ids where the unregistered MBean is |
| // referenced |
| for (Map.Entry<String,List<String>> currRel : |
| localRelIdMap.entrySet()) { |
| final String currRelId = currRel.getKey(); |
| // List of roles of the relation where the MBean is |
| // referenced |
| List<String> localRoleNameList = currRel.getValue(); |
| |
| // Checks if the relation has to be removed or not, |
| // regarding expected minimum role cardinality and current |
| // number of references after removal of the current one |
| // If the relation is kept, calls |
| // handleMBeanUnregistration() callback of the relation to |
| // update it |
| // |
| // Can throw RelationServiceNotRegisteredException |
| // |
| // Shall not throw RelationNotFoundException, |
| // RoleNotFoundException, MBeanException |
| try { |
| handleReferenceUnregistration(currRelId, |
| unregMBeanName, |
| localRoleNameList); |
| } catch (RelationNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (RoleNotFoundException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "purgeRelations"); |
| return; |
| } |
| |
| /** |
| * Retrieves the relations where a given MBean is referenced. |
| * <P>This corresponds to the CIM "References" and "ReferenceNames" |
| * operations. |
| * |
| * @param mbeanName ObjectName of MBean |
| * @param relationTypeName can be null; if specified, only the relations |
| * of that type will be considered in the search. Else all relation types |
| * are considered. |
| * @param roleName can be null; if specified, only the relations |
| * where the MBean is referenced in that role will be returned. Else all |
| * roles are considered. |
| * |
| * @return an HashMap, where the keys are the relation ids of the relations |
| * where the MBean is referenced, and the value is, for each key, |
| * an ArrayList of role names (as an MBean can be referenced in several |
| * roles in the same relation). |
| * |
| * @exception IllegalArgumentException if null parameter |
| */ |
| public Map<String,List<String>> |
| findReferencingRelations(ObjectName mbeanName, |
| String relationTypeName, |
| String roleName) |
| throws IllegalArgumentException { |
| |
| if (mbeanName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "findReferencingRelations", |
| new Object[] {mbeanName, relationTypeName, roleName}); |
| |
| Map<String,List<String>> result = new HashMap<String,List<String>>(); |
| |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| |
| // Retrieves the relations referencing the MBean |
| Map<String,List<String>> relId2RoleNamesMap = |
| myRefedMBeanObjName2RelIdsMap.get(mbeanName); |
| |
| if (relId2RoleNamesMap != null) { |
| |
| // Relation Ids where the MBean is referenced |
| Set<String> allRelIdSet = relId2RoleNamesMap.keySet(); |
| |
| // List of relation ids of interest regarding the selected |
| // relation type |
| List<String> relIdList; |
| if (relationTypeName == null) { |
| // Considers all relations |
| relIdList = new ArrayList<String>(allRelIdSet); |
| |
| } else { |
| |
| relIdList = new ArrayList<String>(); |
| |
| // Considers only the relation ids for relations of given |
| // type |
| for (String currRelId : allRelIdSet) { |
| |
| // Retrieves its relation type |
| String currRelTypeName; |
| synchronized(myRelId2RelTypeMap) { |
| currRelTypeName = |
| myRelId2RelTypeMap.get(currRelId); |
| } |
| |
| if (currRelTypeName.equals(relationTypeName)) { |
| |
| relIdList.add(currRelId); |
| |
| } |
| } |
| } |
| |
| // Now looks at the roles where the MBean is expected to be |
| // referenced |
| |
| for (String currRelId : relIdList) { |
| // Retrieves list of role names where the MBean is |
| // referenced |
| List<String> currRoleNameList = |
| relId2RoleNamesMap.get(currRelId); |
| |
| if (roleName == null) { |
| // All roles to be considered |
| // Note: no need to test if list not null before |
| // cloning, MUST be not null else bug :( |
| result.put(currRelId, |
| new ArrayList<String>(currRoleNameList)); |
| |
| } else if (currRoleNameList.contains(roleName)) { |
| // Filters only the relations where the MBean is |
| // referenced in // given role |
| List<String> dummyList = new ArrayList<String>(); |
| dummyList.add(roleName); |
| result.put(currRelId, dummyList); |
| } |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "findReferencingRelations"); |
| return result; |
| } |
| |
| /** |
| * Retrieves the MBeans associated to given one in a relation. |
| * <P>This corresponds to CIM Associators and AssociatorNames operations. |
| * |
| * @param mbeanName ObjectName of MBean |
| * @param relationTypeName can be null; if specified, only the relations |
| * of that type will be considered in the search. Else all |
| * relation types are considered. |
| * @param roleName can be null; if specified, only the relations |
| * where the MBean is referenced in that role will be considered. Else all |
| * roles are considered. |
| * |
| * @return an HashMap, where the keys are the ObjectNames of the MBeans |
| * associated to given MBean, and the value is, for each key, an ArrayList |
| * of the relation ids of the relations where the key MBean is |
| * associated to given one (as they can be associated in several different |
| * relations). |
| * |
| * @exception IllegalArgumentException if null parameter |
| */ |
| public Map<ObjectName,List<String>> |
| findAssociatedMBeans(ObjectName mbeanName, |
| String relationTypeName, |
| String roleName) |
| throws IllegalArgumentException { |
| |
| if (mbeanName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "findAssociatedMBeans", |
| new Object[] {mbeanName, relationTypeName, roleName}); |
| |
| // Retrieves the map <relation id> -> <role names> for those |
| // criterias |
| Map<String,List<String>> relId2RoleNamesMap = |
| findReferencingRelations(mbeanName, |
| relationTypeName, |
| roleName); |
| |
| Map<ObjectName,List<String>> result = |
| new HashMap<ObjectName,List<String>>(); |
| |
| for (String currRelId : relId2RoleNamesMap.keySet()) { |
| |
| // Retrieves ObjectNames of MBeans referenced in this relation |
| // |
| // Shall not throw a RelationNotFoundException if incorrect status |
| // of maps :( |
| Map<ObjectName,List<String>> objName2RoleNamesMap; |
| try { |
| objName2RoleNamesMap = getReferencedMBeans(currRelId); |
| } catch (RelationNotFoundException exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| |
| // For each MBean associated to given one in a relation, adds the |
| // association <ObjectName> -> <relation id> into result map |
| for (ObjectName currObjName : objName2RoleNamesMap.keySet()) { |
| |
| if (!(currObjName.equals(mbeanName))) { |
| |
| // Sees if this MBean is already associated to the given |
| // one in another relation |
| List<String> currRelIdList = result.get(currObjName); |
| if (currRelIdList == null) { |
| |
| currRelIdList = new ArrayList<String>(); |
| currRelIdList.add(currRelId); |
| result.put(currObjName, currRelIdList); |
| |
| } else { |
| currRelIdList.add(currRelId); |
| } |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "findAssociatedMBeans"); |
| return result; |
| } |
| |
| /** |
| * Returns the relation ids for relations of the given type. |
| * |
| * @param relationTypeName relation type name |
| * |
| * @return an ArrayList of relation ids. |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationTypeNotFoundException if there is no relation type |
| * with that name. |
| */ |
| public List<String> findRelationsOfType(String relationTypeName) |
| throws IllegalArgumentException, |
| RelationTypeNotFoundException { |
| |
| if (relationTypeName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "findRelationsOfType"); |
| |
| // Can throw RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| List<String> result; |
| synchronized(myRelType2RelIdsMap) { |
| List<String> result1 = myRelType2RelIdsMap.get(relationTypeName); |
| if (result1 == null) |
| result = new ArrayList<String>(); |
| else |
| result = new ArrayList<String>(result1); |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "findRelationsOfType"); |
| return result; |
| } |
| |
| /** |
| * Retrieves role value for given role name in given relation. |
| * |
| * @param relationId relation id |
| * @param roleName name of role |
| * |
| * @return the ArrayList of ObjectName objects being the role value |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation with given id |
| * @exception RoleNotFoundException if: |
| * <P>- there is no role with given name |
| * <P>or |
| * <P>- the role is not readable. |
| * |
| * @see #setRole |
| */ |
| public List<ObjectName> getRole(String relationId, |
| String roleName) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RelationNotFoundException, |
| RoleNotFoundException { |
| |
| if (relationId == null || roleName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRole", new Object[] {relationId, roleName}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| List<ObjectName> result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| // Can throw RoleNotFoundException |
| result = cast( |
| ((RelationSupport)relObj).getRoleInt(roleName, |
| true, |
| this, |
| false)); |
| |
| } else { |
| // Relation MBean |
| Object[] params = new Object[1]; |
| params[0] = roleName; |
| String[] signature = new String[1]; |
| signature[0] = "java.lang.String"; |
| // Can throw MBeanException wrapping a RoleNotFoundException: |
| // throw wrapped exception |
| // |
| // Shall not throw InstanceNotFoundException or ReflectionException |
| try { |
| List<ObjectName> invokeResult = cast( |
| myMBeanServer.invoke(((ObjectName)relObj), |
| "getRole", |
| params, |
| signature)); |
| if (invokeResult == null || invokeResult instanceof ArrayList<?>) |
| result = invokeResult; |
| else |
| result = new ArrayList<ObjectName>(invokeResult); |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (MBeanException exc3) { |
| Exception wrappedExc = exc3.getTargetException(); |
| if (wrappedExc instanceof RoleNotFoundException) { |
| throw ((RoleNotFoundException)wrappedExc); |
| } else { |
| throw new RuntimeException(wrappedExc.getMessage()); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), "getRole"); |
| return result; |
| } |
| |
| /** |
| * Retrieves values of roles with given names in given relation. |
| * |
| * @param relationId relation id |
| * @param roleNameArray array of names of roles to be retrieved |
| * |
| * @return a RoleResult object, including a RoleList (for roles |
| * successfully retrieved) and a RoleUnresolvedList (for roles not |
| * retrieved). |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation with given id |
| * |
| * @see #setRoles |
| */ |
| public RoleResult getRoles(String relationId, |
| String[] roleNameArray) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null || roleNameArray == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRoles", relationId); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| RoleResult result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| result = ((RelationSupport)relObj).getRolesInt(roleNameArray, |
| true, |
| this); |
| } else { |
| // Relation MBean |
| Object[] params = new Object[1]; |
| params[0] = roleNameArray; |
| String[] signature = new String[1]; |
| try { |
| signature[0] = (roleNameArray.getClass()).getName(); |
| } catch (Exception exc) { |
| // OK : This is an array of java.lang.String |
| // so this should never happen... |
| } |
| // Shall not throw InstanceNotFoundException, ReflectionException |
| // or MBeanException |
| try { |
| result = (RoleResult) |
| (myMBeanServer.invoke(((ObjectName)relObj), |
| "getRoles", |
| params, |
| signature)); |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (MBeanException exc3) { |
| throw new |
| RuntimeException((exc3.getTargetException()).getMessage()); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles"); |
| return result; |
| } |
| |
| /** |
| * Returns all roles present in the relation. |
| * |
| * @param relationId relation id |
| * |
| * @return a RoleResult object, including a RoleList (for roles |
| * successfully retrieved) and a RoleUnresolvedList (for roles not |
| * readable). |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation for given id |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| */ |
| public RoleResult getAllRoles(String relationId) |
| throws IllegalArgumentException, |
| RelationNotFoundException, |
| RelationServiceNotRegisteredException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRoles", relationId); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| RoleResult result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| result = ((RelationSupport)relObj).getAllRolesInt(true, this); |
| |
| } else { |
| // Relation MBean |
| // Shall not throw any Exception |
| try { |
| result = (RoleResult) |
| (myMBeanServer.getAttribute(((ObjectName)relObj), |
| "AllRoles")); |
| } catch (Exception exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles"); |
| return result; |
| } |
| |
| /** |
| * Retrieves the number of MBeans currently referenced in the given role. |
| * |
| * @param relationId relation id |
| * @param roleName name of role |
| * |
| * @return the number of currently referenced MBeans in that role |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation with given id |
| * @exception RoleNotFoundException if there is no role with given name |
| */ |
| public Integer getRoleCardinality(String relationId, |
| String roleName) |
| throws IllegalArgumentException, |
| RelationNotFoundException, |
| RoleNotFoundException { |
| |
| if (relationId == null || roleName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRoleCardinality", new Object[] {relationId, roleName}); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| Integer result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| // Can throw RoleNotFoundException |
| result = ((RelationSupport)relObj).getRoleCardinality(roleName); |
| |
| } else { |
| // Relation MBean |
| Object[] params = new Object[1]; |
| params[0] = roleName; |
| String[] signature = new String[1]; |
| signature[0] = "java.lang.String"; |
| // Can throw MBeanException wrapping RoleNotFoundException: |
| // throw wrapped exception |
| // |
| // Shall not throw InstanceNotFoundException or ReflectionException |
| try { |
| result = (Integer) |
| (myMBeanServer.invoke(((ObjectName)relObj), |
| "getRoleCardinality", |
| params, |
| signature)); |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (MBeanException exc3) { |
| Exception wrappedExc = exc3.getTargetException(); |
| if (wrappedExc instanceof RoleNotFoundException) { |
| throw ((RoleNotFoundException)wrappedExc); |
| } else { |
| throw new RuntimeException(wrappedExc.getMessage()); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getRoleCardinality"); |
| return result; |
| } |
| |
| /** |
| * Sets the given role in given relation. |
| * <P>Will check the role according to its corresponding role definition |
| * provided in relation's relation type |
| * <P>The Relation Service will keep track of the change to keep the |
| * consistency of relations by handling referenced MBean unregistrations. |
| * |
| * @param relationId relation id |
| * @param role role to be set (name and new value) |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation with given id |
| * @exception RoleNotFoundException if the role does not exist or is not |
| * writable |
| * @exception InvalidRoleValueException if value provided for role is not |
| * valid: |
| * <P>- the number of referenced MBeans in given value is less than |
| * expected minimum degree |
| * <P>or |
| * <P>- the number of referenced MBeans in provided value exceeds expected |
| * maximum degree |
| * <P>or |
| * <P>- one referenced MBean in the value is not an Object of the MBean |
| * class expected for that role |
| * <P>or |
| * <P>- an MBean provided for that role does not exist |
| * |
| * @see #getRole |
| */ |
| public void setRole(String relationId, |
| Role role) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RelationNotFoundException, |
| RoleNotFoundException, |
| InvalidRoleValueException { |
| |
| if (relationId == null || role == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "setRole", new Object[] {relationId, role}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| // Can throw RoleNotFoundException, |
| // InvalidRoleValueException and |
| // RelationServiceNotRegisteredException |
| // |
| // Shall not throw RelationTypeNotFoundException |
| // (as relation exists in the RS, its relation type is known) |
| try { |
| ((RelationSupport)relObj).setRoleInt(role, |
| true, |
| this, |
| false); |
| |
| } catch (RelationTypeNotFoundException exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| |
| } else { |
| // Relation MBean |
| Object[] params = new Object[1]; |
| params[0] = role; |
| String[] signature = new String[1]; |
| signature[0] = "javax.management.relation.Role"; |
| // Can throw MBeanException wrapping RoleNotFoundException, |
| // InvalidRoleValueException |
| // |
| // Shall not MBeanException wrapping an MBeanException wrapping |
| // RelationTypeNotFoundException, or ReflectionException, or |
| // InstanceNotFoundException |
| try { |
| myMBeanServer.setAttribute(((ObjectName)relObj), |
| new Attribute("Role", role)); |
| |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } catch (MBeanException exc2) { |
| Exception wrappedExc = exc2.getTargetException(); |
| if (wrappedExc instanceof RoleNotFoundException) { |
| throw ((RoleNotFoundException)wrappedExc); |
| } else if (wrappedExc instanceof InvalidRoleValueException) { |
| throw ((InvalidRoleValueException)wrappedExc); |
| } else { |
| throw new RuntimeException(wrappedExc.getMessage()); |
| |
| } |
| } catch (AttributeNotFoundException exc4) { |
| throw new RuntimeException(exc4.getMessage()); |
| } catch (InvalidAttributeValueException exc5) { |
| throw new RuntimeException(exc5.getMessage()); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), "setRole"); |
| return; |
| } |
| |
| /** |
| * Sets the given roles in given relation. |
| * <P>Will check the role according to its corresponding role definition |
| * provided in relation's relation type |
| * <P>The Relation Service keeps track of the changes to keep the |
| * consistency of relations by handling referenced MBean unregistrations. |
| * |
| * @param relationId relation id |
| * @param roleList list of roles to be set |
| * |
| * @return a RoleResult object, including a RoleList (for roles |
| * successfully set) and a RoleUnresolvedList (for roles not |
| * set). |
| * |
| * @exception RelationServiceNotRegisteredException if the Relation |
| * Service is not registered in the MBean Server |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation with given id |
| * |
| * @see #getRoles |
| */ |
| public RoleResult setRoles(String relationId, |
| RoleList roleList) |
| throws RelationServiceNotRegisteredException, |
| IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null || roleList == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "setRoles", new Object[] {relationId, roleList}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| RoleResult result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| // Can throw RelationServiceNotRegisteredException |
| // |
| // Shall not throw RelationTypeNotFoundException (as relation is |
| // known, its relation type exists) |
| try { |
| result = ((RelationSupport)relObj).setRolesInt(roleList, |
| true, |
| this); |
| } catch (RelationTypeNotFoundException exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| |
| } else { |
| // Relation MBean |
| Object[] params = new Object[1]; |
| params[0] = roleList; |
| String[] signature = new String[1]; |
| signature[0] = "javax.management.relation.RoleList"; |
| // Shall not throw InstanceNotFoundException or an MBeanException |
| // or ReflectionException |
| try { |
| result = (RoleResult) |
| (myMBeanServer.invoke(((ObjectName)relObj), |
| "setRoles", |
| params, |
| signature)); |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } catch (MBeanException exc2) { |
| throw new |
| RuntimeException((exc2.getTargetException()).getMessage()); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), "setRoles"); |
| return result; |
| } |
| |
| /** |
| * Retrieves MBeans referenced in the various roles of the relation. |
| * |
| * @param relationId relation id |
| * |
| * @return a HashMap mapping: |
| * <P> ObjectName -> ArrayList of String (role |
| * names) |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation for given |
| * relation id |
| */ |
| public Map<ObjectName,List<String>> |
| getReferencedMBeans(String relationId) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getReferencedMBeans", relationId); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| Map<ObjectName,List<String>> result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| result = ((RelationSupport)relObj).getReferencedMBeans(); |
| |
| } else { |
| // Relation MBean |
| // No Exception |
| try { |
| result = cast( |
| myMBeanServer.getAttribute(((ObjectName)relObj), |
| "ReferencedMBeans")); |
| } catch (Exception exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getReferencedMBeans"); |
| return result; |
| } |
| |
| /** |
| * Returns name of associated relation type for given relation. |
| * |
| * @param relationId relation id |
| * |
| * @return the name of the associated relation type. |
| * |
| * @exception IllegalArgumentException if null parameter |
| * @exception RelationNotFoundException if no relation for given |
| * relation id |
| */ |
| public String getRelationTypeName(String relationId) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRelationTypeName", relationId); |
| |
| // Can throw a RelationNotFoundException |
| Object relObj = getRelation(relationId); |
| |
| String result; |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| result = ((RelationSupport)relObj).getRelationTypeName(); |
| |
| } else { |
| // Relation MBean |
| // No Exception |
| try { |
| result = (String) |
| (myMBeanServer.getAttribute(((ObjectName)relObj), |
| "RelationTypeName")); |
| } catch (Exception exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getRelationTypeName"); |
| return result; |
| } |
| |
| // |
| // NotificationListener Interface |
| // |
| |
| /** |
| * Invoked when a JMX notification occurs. |
| * Currently handles notifications for unregistration of MBeans, either |
| * referenced in a relation role or being a relation itself. |
| * |
| * @param notif The notification. |
| * @param handback An opaque object which helps the listener to |
| * associate information regarding the MBean emitter (can be null). |
| */ |
| public void handleNotification(Notification notif, |
| Object handback) { |
| |
| if (notif == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "handleNotification", notif); |
| |
| if (notif instanceof MBeanServerNotification) { |
| |
| MBeanServerNotification mbsNtf = (MBeanServerNotification) notif; |
| String ntfType = notif.getType(); |
| |
| if (ntfType.equals( |
| MBeanServerNotification.UNREGISTRATION_NOTIFICATION )) { |
| ObjectName mbeanName = |
| ((MBeanServerNotification)notif).getMBeanName(); |
| |
| // Note: use a flag to block access to |
| // myRefedMBeanObjName2RelIdsMap only for a quick access |
| boolean isRefedMBeanFlag = false; |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| |
| if (myRefedMBeanObjName2RelIdsMap.containsKey(mbeanName)) { |
| // Unregistration of a referenced MBean |
| synchronized(myUnregNtfList) { |
| myUnregNtfList.add(mbsNtf); |
| } |
| isRefedMBeanFlag = true; |
| } |
| if (isRefedMBeanFlag && myPurgeFlag) { |
| // Immediate purge |
| // Can throw RelationServiceNotRegisteredException |
| // but assume that will be fine :) |
| try { |
| purgeRelations(); |
| } catch (Exception exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| } |
| } |
| |
| // Note: do both tests as a relation can be an MBean and be |
| // itself referenced in another relation :) |
| String relId; |
| synchronized(myRelMBeanObjName2RelIdMap){ |
| relId = myRelMBeanObjName2RelIdMap.get(mbeanName); |
| } |
| if (relId != null) { |
| // Unregistration of a relation MBean |
| // Can throw RelationTypeNotFoundException, |
| // RelationServiceNotRegisteredException |
| // |
| // Shall not throw RelationTypeNotFoundException or |
| // InstanceNotFoundException |
| try { |
| removeRelation(relId); |
| } catch (Exception exc) { |
| throw new RuntimeException(exc.getMessage()); |
| } |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "handleNotification"); |
| return; |
| } |
| |
| // |
| // NotificationBroadcaster interface |
| // |
| |
| /** |
| * Returns a NotificationInfo object containing the name of the Java class |
| * of the notification and the notification types sent. |
| */ |
| public MBeanNotificationInfo[] getNotificationInfo() { |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getNotificationInfo"); |
| |
| String ntfClass = "javax.management.relation.RelationNotification"; |
| |
| String[] ntfTypes = new String[] { |
| RelationNotification.RELATION_BASIC_CREATION, |
| RelationNotification.RELATION_MBEAN_CREATION, |
| RelationNotification.RELATION_BASIC_UPDATE, |
| RelationNotification.RELATION_MBEAN_UPDATE, |
| RelationNotification.RELATION_BASIC_REMOVAL, |
| RelationNotification.RELATION_MBEAN_REMOVAL, |
| }; |
| |
| String ntfDesc = "Sent when a relation is created, updated or deleted."; |
| |
| MBeanNotificationInfo ntfInfo = |
| new MBeanNotificationInfo(ntfTypes, ntfClass, ntfDesc); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getNotificationInfo"); |
| return new MBeanNotificationInfo[] {ntfInfo}; |
| } |
| |
| // |
| // Misc |
| // |
| |
| // Adds given object as a relation type. |
| // |
| // -param relationTypeObj relation type object |
| // |
| // -exception IllegalArgumentException if null parameter |
| // -exception InvalidRelationTypeException if there is already a relation |
| // type with that name |
| private void addRelationTypeInt(RelationType relationTypeObj) |
| throws IllegalArgumentException, |
| InvalidRelationTypeException { |
| |
| if (relationTypeObj == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "addRelationTypeInt"); |
| |
| String relTypeName = relationTypeObj.getRelationTypeName(); |
| |
| // Checks that there is not already a relation type with that name |
| // existing in the Relation Service |
| try { |
| // Can throw a RelationTypeNotFoundException (in fact should ;) |
| RelationType relType = getRelationType(relTypeName); |
| |
| if (relType != null) { |
| String excMsg = "There is already a relation type in the Relation Service with name "; |
| StringBuilder excMsgStrB = new StringBuilder(excMsg); |
| excMsgStrB.append(relTypeName); |
| throw new InvalidRelationTypeException(excMsgStrB.toString()); |
| } |
| |
| } catch (RelationTypeNotFoundException exc) { |
| // OK : The RelationType could not be found. |
| } |
| |
| // Adds the relation type |
| synchronized(myRelType2ObjMap) { |
| myRelType2ObjMap.put(relTypeName, relationTypeObj); |
| } |
| |
| if (relationTypeObj instanceof RelationTypeSupport) { |
| ((RelationTypeSupport)relationTypeObj).setRelationServiceFlag(true); |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "addRelationTypeInt"); |
| return; |
| } |
| |
| // Retrieves relation type with given name |
| // |
| // -param relationTypeName expected name of a relation type created in the |
| // Relation Service |
| // |
| // -return RelationType object corresponding to given name |
| // |
| // -exception IllegalArgumentException if null parameter |
| // -exception RelationTypeNotFoundException if no relation type for that |
| // name created in Relation Service |
| // |
| RelationType getRelationType(String relationTypeName) |
| throws IllegalArgumentException, |
| RelationTypeNotFoundException { |
| |
| if (relationTypeName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRelationType", relationTypeName); |
| |
| // No null relation type accepted, so can use get() |
| RelationType relType; |
| synchronized(myRelType2ObjMap) { |
| relType = (myRelType2ObjMap.get(relationTypeName)); |
| } |
| |
| if (relType == null) { |
| String excMsg = "No relation type created in the Relation Service with the name "; |
| StringBuilder excMsgStrB = new StringBuilder(excMsg); |
| excMsgStrB.append(relationTypeName); |
| throw new RelationTypeNotFoundException(excMsgStrB.toString()); |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getRelationType"); |
| return relType; |
| } |
| |
| // Retrieves relation corresponding to given relation id. |
| // Returns either: |
| // - a RelationSupport object if the relation is internal |
| // or |
| // - the ObjectName of the corresponding MBean |
| // |
| // -param relationId expected relation id |
| // |
| // -return RelationSupport object or ObjectName of relation with given id |
| // |
| // -exception IllegalArgumentException if null parameter |
| // -exception RelationNotFoundException if no relation for that |
| // relation id created in Relation Service |
| // |
| Object getRelation(String relationId) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (relationId == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "getRelation", relationId); |
| |
| // No null relation accepted, so can use get() |
| Object rel; |
| synchronized(myRelId2ObjMap) { |
| rel = myRelId2ObjMap.get(relationId); |
| } |
| |
| if (rel == null) { |
| String excMsg = "No relation associated to relation id " + relationId; |
| throw new RelationNotFoundException(excMsg); |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "getRelation"); |
| return rel; |
| } |
| |
| // Adds a new MBean reference (reference to an ObjectName) in the |
| // referenced MBean map (myRefedMBeanObjName2RelIdsMap). |
| // |
| // -param objectName ObjectName of new referenced MBean |
| // -param relationId relation id of the relation where the MBean is |
| // referenced |
| // -param roleName name of the role where the MBean is referenced |
| // |
| // -return boolean: |
| // - true if the MBean was not referenced before, so really a new |
| // reference |
| // - false else |
| // |
| // -exception IllegalArgumentException if null parameter |
| private boolean addNewMBeanReference(ObjectName objectName, |
| String relationId, |
| String roleName) |
| throws IllegalArgumentException { |
| |
| if (objectName == null || |
| relationId == null || |
| roleName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "addNewMBeanReference", |
| new Object[] {objectName, relationId, roleName}); |
| |
| boolean isNewFlag = false; |
| |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| |
| // Checks if the MBean was already referenced |
| // No null value allowed, use get() directly |
| Map<String,List<String>> mbeanRefMap = |
| myRefedMBeanObjName2RelIdsMap.get(objectName); |
| |
| if (mbeanRefMap == null) { |
| // MBean not referenced in any relation yet |
| |
| isNewFlag = true; |
| |
| // List of roles where the MBean is referenced in given |
| // relation |
| List<String> roleNames = new ArrayList<String>(); |
| roleNames.add(roleName); |
| |
| // Map of relations where the MBean is referenced |
| mbeanRefMap = new HashMap<String,List<String>>(); |
| mbeanRefMap.put(relationId, roleNames); |
| |
| myRefedMBeanObjName2RelIdsMap.put(objectName, mbeanRefMap); |
| |
| } else { |
| // MBean already referenced in at least another relation |
| // Checks if already referenced in another role in current |
| // relation |
| List<String> roleNames = mbeanRefMap.get(relationId); |
| |
| if (roleNames == null) { |
| // MBean not referenced in current relation |
| |
| // List of roles where the MBean is referenced in given |
| // relation |
| roleNames = new ArrayList<String>(); |
| roleNames.add(roleName); |
| |
| // Adds new reference done in current relation |
| mbeanRefMap.put(relationId, roleNames); |
| |
| } else { |
| // MBean already referenced in current relation in another |
| // role |
| // Adds new reference done |
| roleNames.add(roleName); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "addNewMBeanReference"); |
| return isNewFlag; |
| } |
| |
| // Removes an obsolete MBean reference (reference to an ObjectName) in |
| // the referenced MBean map (myRefedMBeanObjName2RelIdsMap). |
| // |
| // -param objectName ObjectName of MBean no longer referenced |
| // -param relationId relation id of the relation where the MBean was |
| // referenced |
| // -param roleName name of the role where the MBean was referenced |
| // -param allRolesFlag flag, if true removes reference to MBean for all |
| // roles in the relation, not only for the one above |
| // |
| // -return boolean: |
| // - true if the MBean is no longer reference in any relation |
| // - false else |
| // |
| // -exception IllegalArgumentException if null parameter |
| private boolean removeMBeanReference(ObjectName objectName, |
| String relationId, |
| String roleName, |
| boolean allRolesFlag) |
| throws IllegalArgumentException { |
| |
| if (objectName == null || |
| relationId == null || |
| roleName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "removeMBeanReference", |
| new Object[] {objectName, relationId, roleName, allRolesFlag}); |
| |
| boolean noLongerRefFlag = false; |
| |
| synchronized(myRefedMBeanObjName2RelIdsMap) { |
| |
| // Retrieves the set of relations (designed via their relation ids) |
| // where the MBean is referenced |
| // Note that it is possible that the MBean has already been removed |
| // from the internal map: this is the case when the MBean is |
| // unregistered, the role is updated, then we arrive here. |
| Map<String,List<String>> mbeanRefMap = |
| (myRefedMBeanObjName2RelIdsMap.get(objectName)); |
| |
| if (mbeanRefMap == null) { |
| // The MBean is no longer referenced |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "removeMBeanReference"); |
| return true; |
| } |
| |
| List<String> roleNames = null; |
| if (!allRolesFlag) { |
| // Now retrieves the roles of current relation where the MBean |
| // was referenced |
| roleNames = mbeanRefMap.get(relationId); |
| |
| // Removes obsolete reference to role |
| int obsRefIdx = roleNames.indexOf(roleName); |
| if (obsRefIdx != -1) { |
| roleNames.remove(obsRefIdx); |
| } |
| } |
| |
| // Checks if there is still at least one role in current relation |
| // where the MBean is referenced |
| if (roleNames.isEmpty() || allRolesFlag) { |
| // MBean no longer referenced in current relation: removes |
| // entry |
| mbeanRefMap.remove(relationId); |
| } |
| |
| // Checks if the MBean is still referenced in at least on relation |
| if (mbeanRefMap.isEmpty()) { |
| // MBean no longer referenced in any relation: removes entry |
| myRefedMBeanObjName2RelIdsMap.remove(objectName); |
| noLongerRefFlag = true; |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "removeMBeanReference"); |
| return noLongerRefFlag; |
| } |
| |
| // Updates the listener registered to the MBean Server to be informed of |
| // referenced MBean unregistrations |
| // |
| // -param newRefList ArrayList of ObjectNames for new references done |
| // to MBeans (can be null) |
| // -param obsoleteRefList ArrayList of ObjectNames for obsolete references |
| // to MBeans (can be null) |
| // |
| // -exception RelationServiceNotRegisteredException if the Relation |
| // Service is not registered in the MBean Server. |
| private void updateUnregistrationListener(List<ObjectName> newRefList, |
| List<ObjectName> obsoleteRefList) |
| throws RelationServiceNotRegisteredException { |
| |
| if (newRefList != null && obsoleteRefList != null) { |
| if (newRefList.isEmpty() && obsoleteRefList.isEmpty()) { |
| // Nothing to do :) |
| return; |
| } |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "updateUnregistrationListener", |
| new Object[] {newRefList, obsoleteRefList}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| if (newRefList != null || obsoleteRefList != null) { |
| |
| boolean newListenerFlag = false; |
| if (myUnregNtfFilter == null) { |
| // Initialize it to be able to synchronise it :) |
| myUnregNtfFilter = new MBeanServerNotificationFilter(); |
| newListenerFlag = true; |
| } |
| |
| synchronized(myUnregNtfFilter) { |
| |
| // Enables ObjectNames in newRefList |
| if (newRefList != null) { |
| for (ObjectName newObjName : newRefList) |
| myUnregNtfFilter.enableObjectName(newObjName); |
| } |
| |
| if (obsoleteRefList != null) { |
| // Disables ObjectNames in obsoleteRefList |
| for (ObjectName obsObjName : obsoleteRefList) |
| myUnregNtfFilter.disableObjectName(obsObjName); |
| } |
| |
| // Under test |
| if (newListenerFlag) { |
| try { |
| myMBeanServer.addNotificationListener( |
| MBeanServerDelegate.DELEGATE_NAME, |
| this, |
| myUnregNtfFilter, |
| null); |
| } catch (InstanceNotFoundException exc) { |
| throw new |
| RelationServiceNotRegisteredException(exc.getMessage()); |
| } |
| } |
| // End test |
| |
| |
| // if (!newListenerFlag) { |
| // The Relation Service was already registered as a |
| // listener: |
| // removes it |
| // Shall not throw InstanceNotFoundException (as the |
| // MBean Server Delegate is expected to exist) or |
| // ListenerNotFoundException (as it has been checked above |
| // that the Relation Service is registered) |
| // try { |
| // myMBeanServer.removeNotificationListener( |
| // MBeanServerDelegate.DELEGATE_NAME, |
| // this); |
| // } catch (InstanceNotFoundException exc1) { |
| // throw new RuntimeException(exc1.getMessage()); |
| // } catch (ListenerNotFoundException exc2) { |
| // throw new |
| // RelationServiceNotRegisteredException(exc2.getMessage()); |
| // } |
| // } |
| |
| // Adds Relation Service with current filter |
| // Can throw InstanceNotFoundException if the Relation |
| // Service is not registered, to be transformed into |
| // RelationServiceNotRegisteredException |
| // |
| // Assume that there will not be any InstanceNotFoundException |
| // for the MBean Server Delegate :) |
| // try { |
| // myMBeanServer.addNotificationListener( |
| // MBeanServerDelegate.DELEGATE_NAME, |
| // this, |
| // myUnregNtfFilter, |
| // null); |
| // } catch (InstanceNotFoundException exc) { |
| // throw new |
| // RelationServiceNotRegisteredException(exc.getMessage()); |
| // } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "updateUnregistrationListener"); |
| return; |
| } |
| |
| // Adds a relation (being either a RelationSupport object or an MBean |
| // referenced using its ObjectName) in the Relation Service. |
| // Will send a notification RelationNotification with type: |
| // - RelationNotification.RELATION_BASIC_CREATION for internal relation |
| // creation |
| // - RelationNotification.RELATION_MBEAN_CREATION for an MBean being added |
| // as a relation. |
| // |
| // -param relationBaseFlag flag true if the relation is a RelationSupport |
| // object, false if it is an MBean |
| // -param relationObj RelationSupport object (if relation is internal) |
| // -param relationObjName ObjectName of the MBean to be added as a relation |
| // (only for the relation MBean) |
| // -param relationId relation identifier, to uniquely identify the relation |
| // inside the Relation Service |
| // -param relationTypeName name of the relation type (has to be created |
| // in the Relation Service) |
| // -param roleList role list to initialize roles of the relation |
| // (can be null) |
| // |
| // -exception IllegalArgumentException if null paramater |
| // -exception RelationServiceNotRegisteredException if the Relation |
| // Service is not registered in the MBean Server |
| // -exception RoleNotFoundException if a value is provided for a role |
| // that does not exist in the relation type |
| // -exception InvalidRelationIdException if relation id already used |
| // -exception RelationTypeNotFoundException if relation type not known in |
| // Relation Service |
| // -exception InvalidRoleValueException if: |
| // - the same role name is used for two different roles |
| // - the number of referenced MBeans in given value is less than |
| // expected minimum degree |
| // - the number of referenced MBeans in provided value exceeds expected |
| // maximum degree |
| // - one referenced MBean in the value is not an Object of the MBean |
| // class expected for that role |
| // - an MBean provided for that role does not exist |
| private void addRelationInt(boolean relationBaseFlag, |
| RelationSupport relationObj, |
| ObjectName relationObjName, |
| String relationId, |
| String relationTypeName, |
| RoleList roleList) |
| throws IllegalArgumentException, |
| RelationServiceNotRegisteredException, |
| RoleNotFoundException, |
| InvalidRelationIdException, |
| RelationTypeNotFoundException, |
| InvalidRoleValueException { |
| |
| if (relationId == null || |
| relationTypeName == null || |
| (relationBaseFlag && |
| (relationObj == null || |
| relationObjName != null)) || |
| (!relationBaseFlag && |
| (relationObjName == null || |
| relationObj != null))) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "addRelationInt", new Object[] {relationBaseFlag, relationObj, |
| relationObjName, relationId, relationTypeName, roleList}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Checks if there is already a relation with given id |
| try { |
| // Can throw a RelationNotFoundException (in fact should :) |
| Object rel = getRelation(relationId); |
| |
| if (rel != null) { |
| // There is already a relation with that id |
| String excMsg = "There is already a relation with id "; |
| StringBuilder excMsgStrB = new StringBuilder(excMsg); |
| excMsgStrB.append(relationId); |
| throw new InvalidRelationIdException(excMsgStrB.toString()); |
| } |
| } catch (RelationNotFoundException exc) { |
| // OK : The Relation could not be found. |
| } |
| |
| // Retrieves the relation type |
| // Can throw RelationTypeNotFoundException |
| RelationType relType = getRelationType(relationTypeName); |
| |
| // Checks that each provided role conforms to its role info provided in |
| // the relation type |
| // First retrieves a local list of the role infos of the relation type |
| // to see which roles have not been initialized |
| // Note: no need to test if list not null before cloning, not allowed |
| // to have an empty relation type. |
| List<RoleInfo> roleInfoList = new ArrayList<RoleInfo>(relType.getRoleInfos()); |
| |
| if (roleList != null) { |
| |
| for (Role currRole : roleList.asList()) { |
| String currRoleName = currRole.getRoleName(); |
| List<ObjectName> currRoleValue = currRole.getRoleValue(); |
| // Retrieves corresponding role info |
| // Can throw a RoleInfoNotFoundException to be converted into a |
| // RoleNotFoundException |
| RoleInfo roleInfo; |
| try { |
| roleInfo = relType.getRoleInfo(currRoleName); |
| } catch (RoleInfoNotFoundException exc) { |
| throw new RoleNotFoundException(exc.getMessage()); |
| } |
| |
| // Checks that role conforms to role info, |
| Integer status = checkRoleInt(2, |
| currRoleName, |
| currRoleValue, |
| roleInfo, |
| false); |
| int pbType = status.intValue(); |
| if (pbType != 0) { |
| // A problem has occurred: throws appropriate exception |
| // here InvalidRoleValueException |
| throwRoleProblemException(pbType, currRoleName); |
| } |
| |
| // Removes role info for that list from list of role infos for |
| // roles to be defaulted |
| int roleInfoIdx = roleInfoList.indexOf(roleInfo); |
| // Note: no need to check if != -1, MUST be there :) |
| roleInfoList.remove(roleInfoIdx); |
| } |
| } |
| |
| // Initializes roles not initialized by roleList |
| // Can throw InvalidRoleValueException |
| initializeMissingRoles(relationBaseFlag, |
| relationObj, |
| relationObjName, |
| relationId, |
| relationTypeName, |
| roleInfoList); |
| |
| // Creation of relation successfull!!!! |
| |
| // Updates internal maps |
| // Relation id to object map |
| synchronized(myRelId2ObjMap) { |
| if (relationBaseFlag) { |
| // Note: do not clone relation object, created by us :) |
| myRelId2ObjMap.put(relationId, relationObj); |
| } else { |
| myRelId2ObjMap.put(relationId, relationObjName); |
| } |
| } |
| |
| // Relation id to relation type name map |
| synchronized(myRelId2RelTypeMap) { |
| myRelId2RelTypeMap.put(relationId, |
| relationTypeName); |
| } |
| |
| // Relation type to relation id map |
| synchronized(myRelType2RelIdsMap) { |
| List<String> relIdList = |
| myRelType2RelIdsMap.get(relationTypeName); |
| boolean firstRelFlag = false; |
| if (relIdList == null) { |
| firstRelFlag = true; |
| relIdList = new ArrayList<String>(); |
| } |
| relIdList.add(relationId); |
| if (firstRelFlag) { |
| myRelType2RelIdsMap.put(relationTypeName, relIdList); |
| } |
| } |
| |
| // Referenced MBean to relation id map |
| // Only role list parameter used, as default initialization of roles |
| // done automatically in initializeMissingRoles() sets each |
| // uninitialized role to an empty value. |
| for (Role currRole : roleList.asList()) { |
| // Creates a dummy empty ArrayList of ObjectNames to be the old |
| // role value :) |
| List<ObjectName> dummyList = new ArrayList<ObjectName>(); |
| // Will not throw a RelationNotFoundException (as the RelId2Obj map |
| // has been updated above) so catch it :) |
| try { |
| updateRoleMap(relationId, currRole, dummyList); |
| |
| } catch (RelationNotFoundException exc) { |
| // OK : The Relation could not be found. |
| } |
| } |
| |
| // Sends a notification for relation creation |
| // Will not throw RelationNotFoundException so catch it :) |
| try { |
| sendRelationCreationNotification(relationId); |
| |
| } catch (RelationNotFoundException exc) { |
| // OK : The Relation could not be found. |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "addRelationInt"); |
| return; |
| } |
| |
| // Checks that given role conforms to given role info. |
| // |
| // -param chkType type of check: |
| // - 1: read, just check read access |
| // - 2: write, check value and write access if writeChkFlag |
| // -param roleName role name |
| // -param roleValue role value |
| // -param roleInfo corresponding role info |
| // -param writeChkFlag boolean to specify a current write access and |
| // to check it |
| // |
| // -return Integer with value: |
| // - 0: ok |
| // - RoleStatus.NO_ROLE_WITH_NAME |
| // - RoleStatus.ROLE_NOT_READABLE |
| // - RoleStatus.ROLE_NOT_WRITABLE |
| // - RoleStatus.LESS_THAN_MIN_ROLE_DEGREE |
| // - RoleStatus.MORE_THAN_MAX_ROLE_DEGREE |
| // - RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS |
| // - RoleStatus.REF_MBEAN_NOT_REGISTERED |
| // |
| // -exception IllegalArgumentException if null parameter |
| private Integer checkRoleInt(int chkType, |
| String roleName, |
| List<ObjectName> roleValue, |
| RoleInfo roleInfo, |
| boolean writeChkFlag) |
| throws IllegalArgumentException { |
| |
| if (roleName == null || |
| roleInfo == null || |
| (chkType == 2 && roleValue == null)) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "checkRoleInt", new Object[] {chkType, roleName, |
| roleValue, roleInfo, writeChkFlag}); |
| |
| // Compares names |
| String expName = roleInfo.getName(); |
| if (!(roleName.equals(expName))) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); |
| } |
| |
| // Checks read access if required |
| if (chkType == 1) { |
| boolean isReadable = roleInfo.isReadable(); |
| if (!isReadable) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return Integer.valueOf(RoleStatus.ROLE_NOT_READABLE); |
| } else { |
| // End of check :) |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(0); |
| } |
| } |
| |
| // Checks write access if required |
| if (writeChkFlag) { |
| boolean isWritable = roleInfo.isWritable(); |
| if (!isWritable) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(RoleStatus.ROLE_NOT_WRITABLE); |
| } |
| } |
| |
| int refNbr = roleValue.size(); |
| |
| // Checks minimum cardinality |
| boolean chkMinFlag = roleInfo.checkMinDegree(refNbr); |
| if (!chkMinFlag) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(RoleStatus.LESS_THAN_MIN_ROLE_DEGREE); |
| } |
| |
| // Checks maximum cardinality |
| boolean chkMaxFlag = roleInfo.checkMaxDegree(refNbr); |
| if (!chkMaxFlag) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(RoleStatus.MORE_THAN_MAX_ROLE_DEGREE); |
| } |
| |
| // Verifies that each referenced MBean is registered in the MBean |
| // Server and that it is an instance of the class specified in the |
| // role info, or of a subclass of it |
| // Note that here again this is under the assumption that |
| // referenced MBeans, relation MBeans and the Relation Service are |
| // registered in the same MBean Server. |
| String expClassName = roleInfo.getRefMBeanClassName(); |
| |
| for (ObjectName currObjName : roleValue) { |
| |
| // Checks it is registered |
| if (currObjName == null) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED); |
| } |
| |
| // Checks if it is of the correct class |
| // Can throw an InstanceNotFoundException, if MBean not registered |
| try { |
| boolean classSts = myMBeanServer.isInstanceOf(currObjName, |
| expClassName); |
| if (!classSts) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS); |
| } |
| |
| } catch (InstanceNotFoundException exc) { |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED); |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "checkRoleInt"); |
| return new Integer(0); |
| } |
| |
| |
| // Initializes roles associated to given role infos to default value (empty |
| // ArrayList of ObjectNames) in given relation. |
| // It will succeed for every role except if the role info has a minimum |
| // cardinality greater than 0. In that case, an InvalidRoleValueException |
| // will be raised. |
| // |
| // -param relationBaseFlag flag true if the relation is a RelationSupport |
| // object, false if it is an MBean |
| // -param relationObj RelationSupport object (if relation is internal) |
| // -param relationObjName ObjectName of the MBean to be added as a relation |
| // (only for the relation MBean) |
| // -param relationId relation id |
| // -param relationTypeName name of the relation type (has to be created |
| // in the Relation Service) |
| // -param roleInfoList list of role infos for roles to be defaulted |
| // |
| // -exception IllegalArgumentException if null paramater |
| // -exception RelationServiceNotRegisteredException if the Relation |
| // Service is not registered in the MBean Server |
| // -exception InvalidRoleValueException if role must have a non-empty |
| // value |
| |
| // Revisit [cebro] Handle CIM qualifiers as REQUIRED to detect roles which |
| // should have been initialized by the user |
| private void initializeMissingRoles(boolean relationBaseFlag, |
| RelationSupport relationObj, |
| ObjectName relationObjName, |
| String relationId, |
| String relationTypeName, |
| List<RoleInfo> roleInfoList) |
| throws IllegalArgumentException, |
| RelationServiceNotRegisteredException, |
| InvalidRoleValueException { |
| |
| if ((relationBaseFlag && |
| (relationObj == null || |
| relationObjName != null)) || |
| (!relationBaseFlag && |
| (relationObjName == null || |
| relationObj != null)) || |
| relationId == null || |
| relationTypeName == null || |
| roleInfoList == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "initializeMissingRoles", new Object[] {relationBaseFlag, |
| relationObj, relationObjName, relationId, relationTypeName, |
| roleInfoList}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // For each role info (corresponding to a role not initialized by the |
| // role list provided by the user), try to set in the relation a role |
| // with an empty list of ObjectNames. |
| // A check is performed to verify that the role can be set to an |
| // empty value, according to its minimum cardinality |
| for (RoleInfo currRoleInfo : roleInfoList) { |
| |
| String roleName = currRoleInfo.getName(); |
| |
| // Creates an empty value |
| List<ObjectName> emptyValue = new ArrayList<ObjectName>(); |
| // Creates a role |
| Role role = new Role(roleName, emptyValue); |
| |
| if (relationBaseFlag) { |
| |
| // Internal relation |
| // Can throw InvalidRoleValueException |
| // |
| // Will not throw RoleNotFoundException (role to be |
| // initialized), or RelationNotFoundException, or |
| // RelationTypeNotFoundException |
| try { |
| relationObj.setRoleInt(role, true, this, false); |
| |
| } catch (RoleNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (RelationNotFoundException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } catch (RelationTypeNotFoundException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } |
| |
| } else { |
| |
| // Relation is an MBean |
| // Use standard setRole() |
| Object[] params = new Object[1]; |
| params[0] = role; |
| String[] signature = new String[1]; |
| signature[0] = "javax.management.relation.Role"; |
| // Can throw MBeanException wrapping |
| // InvalidRoleValueException. Returns the target exception to |
| // be homogeneous. |
| // |
| // Will not throw MBeanException (wrapping |
| // RoleNotFoundException or MBeanException) or |
| // InstanceNotFoundException, or ReflectionException |
| // |
| // Again here the assumption is that the Relation Service and |
| // the relation MBeans are registered in the same MBean Server. |
| try { |
| myMBeanServer.setAttribute(relationObjName, |
| new Attribute("Role", role)); |
| |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } catch (MBeanException exc2) { |
| Exception wrappedExc = exc2.getTargetException(); |
| if (wrappedExc instanceof InvalidRoleValueException) { |
| throw ((InvalidRoleValueException)wrappedExc); |
| } else { |
| throw new RuntimeException(wrappedExc.getMessage()); |
| } |
| } catch (AttributeNotFoundException exc4) { |
| throw new RuntimeException(exc4.getMessage()); |
| } catch (InvalidAttributeValueException exc5) { |
| throw new RuntimeException(exc5.getMessage()); |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "initializeMissingRoles"); |
| return; |
| } |
| |
| // Throws an exception corresponding to a given problem type |
| // |
| // -param pbType possible problem, defined in RoleUnresolved |
| // -param roleName role name |
| // |
| // -exception IllegalArgumentException if null parameter |
| // -exception RoleNotFoundException for problems: |
| // - NO_ROLE_WITH_NAME |
| // - ROLE_NOT_READABLE |
| // - ROLE_NOT_WRITABLE |
| // -exception InvalidRoleValueException for problems: |
| // - LESS_THAN_MIN_ROLE_DEGREE |
| // - MORE_THAN_MAX_ROLE_DEGREE |
| // - REF_MBEAN_OF_INCORRECT_CLASS |
| // - REF_MBEAN_NOT_REGISTERED |
| static void throwRoleProblemException(int pbType, |
| String roleName) |
| throws IllegalArgumentException, |
| RoleNotFoundException, |
| InvalidRoleValueException { |
| |
| if (roleName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| // Exception type: 1 = RoleNotFoundException |
| // 2 = InvalidRoleValueException |
| int excType = 0; |
| |
| String excMsgPart = null; |
| |
| switch (pbType) { |
| case RoleStatus.NO_ROLE_WITH_NAME: |
| excMsgPart = " does not exist in relation."; |
| excType = 1; |
| break; |
| case RoleStatus.ROLE_NOT_READABLE: |
| excMsgPart = " is not readable."; |
| excType = 1; |
| break; |
| case RoleStatus.ROLE_NOT_WRITABLE: |
| excMsgPart = " is not writable."; |
| excType = 1; |
| break; |
| case RoleStatus.LESS_THAN_MIN_ROLE_DEGREE: |
| excMsgPart = " has a number of MBean references less than the expected minimum degree."; |
| excType = 2; |
| break; |
| case RoleStatus.MORE_THAN_MAX_ROLE_DEGREE: |
| excMsgPart = " has a number of MBean references greater than the expected maximum degree."; |
| excType = 2; |
| break; |
| case RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS: |
| excMsgPart = " has an MBean reference to an MBean not of the expected class of references for that role."; |
| excType = 2; |
| break; |
| case RoleStatus.REF_MBEAN_NOT_REGISTERED: |
| excMsgPart = " has a reference to null or to an MBean not registered."; |
| excType = 2; |
| break; |
| } |
| // No default as we must have been in one of those cases |
| |
| StringBuilder excMsgStrB = new StringBuilder(roleName); |
| excMsgStrB.append(excMsgPart); |
| String excMsg = excMsgStrB.toString(); |
| if (excType == 1) { |
| throw new RoleNotFoundException(excMsg); |
| |
| } else if (excType == 2) { |
| throw new InvalidRoleValueException(excMsg); |
| } |
| } |
| |
| // Sends a notification of given type, with given parameters |
| // |
| // -param intNtfType integer to represent notification type: |
| // - 1 : create |
| // - 2 : update |
| // - 3 : delete |
| // -param message human-readable message |
| // -param relationId relation id of the created/updated/deleted relation |
| // -param unregMBeanList list of ObjectNames of referenced MBeans |
| // expected to be unregistered due to relation removal (only for removal, |
| // due to CIM qualifiers, can be null) |
| // -param roleName role name |
| // -param roleNewValue role new value (ArrayList of ObjectNames) |
| // -param oldValue old role value (ArrayList of ObjectNames) |
| // |
| // -exception IllegalArgument if null parameter |
| // -exception RelationNotFoundException if no relation for given id |
| private void sendNotificationInt(int intNtfType, |
| String message, |
| String relationId, |
| List<ObjectName> unregMBeanList, |
| String roleName, |
| List<ObjectName> roleNewValue, |
| List<ObjectName> oldValue) |
| throws IllegalArgumentException, |
| RelationNotFoundException { |
| |
| if (message == null || |
| relationId == null || |
| (intNtfType != 3 && unregMBeanList != null) || |
| (intNtfType == 2 && |
| (roleName == null || |
| roleNewValue == null || |
| oldValue == null))) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "sendNotificationInt", new Object[] {intNtfType, message, |
| relationId, unregMBeanList, roleName, roleNewValue, oldValue}); |
| |
| // Relation type name |
| // Note: do not use getRelationTypeName() as if it is a relation MBean |
| // it is already unregistered. |
| String relTypeName; |
| synchronized(myRelId2RelTypeMap) { |
| relTypeName = (myRelId2RelTypeMap.get(relationId)); |
| } |
| |
| // ObjectName (for a relation MBean) |
| // Can also throw a RelationNotFoundException, but detected above |
| ObjectName relObjName = isRelationMBean(relationId); |
| |
| String ntfType = null; |
| if (relObjName != null) { |
| switch (intNtfType) { |
| case 1: |
| ntfType = RelationNotification.RELATION_MBEAN_CREATION; |
| break; |
| case 2: |
| ntfType = RelationNotification.RELATION_MBEAN_UPDATE; |
| break; |
| case 3: |
| ntfType = RelationNotification.RELATION_MBEAN_REMOVAL; |
| break; |
| } |
| } else { |
| switch (intNtfType) { |
| case 1: |
| ntfType = RelationNotification.RELATION_BASIC_CREATION; |
| break; |
| case 2: |
| ntfType = RelationNotification.RELATION_BASIC_UPDATE; |
| break; |
| case 3: |
| ntfType = RelationNotification.RELATION_BASIC_REMOVAL; |
| break; |
| } |
| } |
| |
| // Sequence number |
| Long seqNo = atomicSeqNo.incrementAndGet(); |
| |
| // Timestamp |
| Date currDate = new Date(); |
| long timeStamp = currDate.getTime(); |
| |
| RelationNotification ntf = null; |
| |
| if (ntfType.equals(RelationNotification.RELATION_BASIC_CREATION) || |
| ntfType.equals(RelationNotification.RELATION_MBEAN_CREATION) || |
| ntfType.equals(RelationNotification.RELATION_BASIC_REMOVAL) || |
| ntfType.equals(RelationNotification.RELATION_MBEAN_REMOVAL)) |
| |
| // Creation or removal |
| ntf = new RelationNotification(ntfType, |
| this, |
| seqNo.longValue(), |
| timeStamp, |
| message, |
| relationId, |
| relTypeName, |
| relObjName, |
| unregMBeanList); |
| |
| else if (ntfType.equals(RelationNotification.RELATION_BASIC_UPDATE) |
| || |
| ntfType.equals(RelationNotification.RELATION_MBEAN_UPDATE)) |
| { |
| // Update |
| ntf = new RelationNotification(ntfType, |
| this, |
| seqNo.longValue(), |
| timeStamp, |
| message, |
| relationId, |
| relTypeName, |
| relObjName, |
| roleName, |
| roleNewValue, |
| oldValue); |
| } |
| |
| sendNotification(ntf); |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "sendNotificationInt"); |
| return; |
| } |
| |
| // Checks, for the unregistration of an MBean referenced in the roles given |
| // in parameter, if the relation has to be removed or not, regarding |
| // expected minimum role cardinality and current number of |
| // references in each role after removal of the current one. |
| // If the relation is kept, calls handleMBeanUnregistration() callback of |
| // the relation to update it. |
| // |
| // -param relationId relation id |
| // -param objectName ObjectName of the unregistered MBean |
| // -param roleNameList list of names of roles where the unregistered |
| // MBean is referenced. |
| // |
| // -exception IllegalArgumentException if null parameter |
| // -exception RelationServiceNotRegisteredException if the Relation |
| // Service is not registered in the MBean Server |
| // -exception RelationNotFoundException if unknown relation id |
| // -exception RoleNotFoundException if one role given as parameter does |
| // not exist in the relation |
| private void handleReferenceUnregistration(String relationId, |
| ObjectName objectName, |
| List<String> roleNameList) |
| throws IllegalArgumentException, |
| RelationServiceNotRegisteredException, |
| RelationNotFoundException, |
| RoleNotFoundException { |
| |
| if (relationId == null || |
| roleNameList == null || |
| objectName == null) { |
| String excMsg = "Invalid parameter."; |
| throw new IllegalArgumentException(excMsg); |
| } |
| |
| RELATION_LOGGER.entering(RelationService.class.getName(), |
| "handleReferenceUnregistration", |
| new Object[] {relationId, objectName, roleNameList}); |
| |
| // Can throw RelationServiceNotRegisteredException |
| isActive(); |
| |
| // Retrieves the relation type name of the relation |
| // Can throw RelationNotFoundException |
| String currRelTypeName = getRelationTypeName(relationId); |
| |
| // Retrieves the relation |
| // Can throw RelationNotFoundException, but already detected above |
| Object relObj = getRelation(relationId); |
| |
| // Flag to specify if the relation has to be deleted |
| boolean deleteRelFlag = false; |
| |
| for (String currRoleName : roleNameList) { |
| |
| if (deleteRelFlag) { |
| break; |
| } |
| |
| // Retrieves number of MBeans currently referenced in role |
| // BEWARE! Do not use getRole() as role may be not readable |
| // |
| // Can throw RelationNotFoundException (but already checked), |
| // RoleNotFoundException |
| int currRoleRefNbr = |
| (getRoleCardinality(relationId, currRoleName)).intValue(); |
| |
| // Retrieves new number of element in role |
| int currRoleNewRefNbr = currRoleRefNbr - 1; |
| |
| // Retrieves role info for that role |
| // |
| // Shall not throw RelationTypeNotFoundException or |
| // RoleInfoNotFoundException |
| RoleInfo currRoleInfo; |
| try { |
| currRoleInfo = getRoleInfo(currRelTypeName, |
| currRoleName); |
| } catch (RelationTypeNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (RoleInfoNotFoundException exc2) { |
| throw new RuntimeException(exc2.getMessage()); |
| } |
| |
| // Checks with expected minimum number of elements |
| boolean chkMinFlag = currRoleInfo.checkMinDegree(currRoleNewRefNbr); |
| |
| if (!chkMinFlag) { |
| // The relation has to be deleted |
| deleteRelFlag = true; |
| } |
| } |
| |
| if (deleteRelFlag) { |
| // Removes the relation |
| removeRelation(relationId); |
| |
| } else { |
| |
| // Updates each role in the relation using |
| // handleMBeanUnregistration() callback |
| // |
| // BEWARE: this roleNameList list MUST BE A COPY of a role name |
| // list for a referenced MBean in a relation, NOT a |
| // reference to an original one part of the |
| // myRefedMBeanObjName2RelIdsMap!!!! Because each role |
| // which name is in that list will be updated (potentially |
| // using setRole(). So the Relation Service will update the |
| // myRefedMBeanObjName2RelIdsMap to refelect the new role |
| // value! |
| for (String currRoleName : roleNameList) { |
| |
| if (relObj instanceof RelationSupport) { |
| // Internal relation |
| // Can throw RoleNotFoundException (but already checked) |
| // |
| // Shall not throw |
| // RelationTypeNotFoundException, |
| // InvalidRoleValueException (value was correct, removing |
| // one reference shall not invalidate it, else detected |
| // above) |
| try { |
| ((RelationSupport)relObj).handleMBeanUnregistrationInt( |
| objectName, |
| currRoleName, |
| true, |
| this); |
| } catch (RelationTypeNotFoundException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } catch (InvalidRoleValueException exc4) { |
| throw new RuntimeException(exc4.getMessage()); |
| } |
| |
| } else { |
| // Relation MBean |
| Object[] params = new Object[2]; |
| params[0] = objectName; |
| params[1] = currRoleName; |
| String[] signature = new String[2]; |
| signature[0] = "javax.management.ObjectName"; |
| signature[1] = "java.lang.String"; |
| // Shall not throw InstanceNotFoundException, or |
| // MBeanException (wrapping RoleNotFoundException or |
| // MBeanException or InvalidRoleValueException) or |
| // ReflectionException |
| try { |
| myMBeanServer.invoke(((ObjectName)relObj), |
| "handleMBeanUnregistration", |
| params, |
| signature); |
| } catch (InstanceNotFoundException exc1) { |
| throw new RuntimeException(exc1.getMessage()); |
| } catch (ReflectionException exc3) { |
| throw new RuntimeException(exc3.getMessage()); |
| } catch (MBeanException exc2) { |
| Exception wrappedExc = exc2.getTargetException(); |
| throw new RuntimeException(wrappedExc.getMessage()); |
| } |
| |
| } |
| } |
| } |
| |
| RELATION_LOGGER.exiting(RelationService.class.getName(), |
| "handleReferenceUnregistration"); |
| return; |
| } |
| } |