You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
3790 lines
147 KiB
3790 lines
147 KiB
/*
|
|
* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.
|
|
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*
|
|
*/
|
|
|
|
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 deregistrations
|
|
private MBeanServerNotificationFilter myUnregNtfFilter = null;
|
|
|
|
// List of unregistration notifications received (storage used if purge
|
|
// of relations when unregistering a referenced MBean is not immediate but
|
|
// on user request)
|
|
private List<MBeanServerNotification> myUnregNtfList =
|
|
new ArrayList<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 deregistrations.
|
|
*
|
|
* @param relationId relation id
|
|
* @param role role to be set (name and new value)
|
|
*
|
|
* @exception RelationServiceNotRegisteredException if the Relation
|
|
* Service is not registered in the MBean Server
|
|
* @exception IllegalArgumentException if null parameter
|
|
* @exception RelationNotFoundException if no relation with given id
|
|
* @exception RoleNotFoundException if the role does not exist or is not
|
|
* writable
|
|
* @exception InvalidRoleValueException if value provided for role is not
|
|
* valid:
|
|
* <P>- the number of referenced MBeans in given value is less than
|
|
* expected minimum degree
|
|
* <P>or
|
|
* <P>- the number of referenced MBeans in provided value exceeds expected
|
|
* maximum degree
|
|
* <P>or
|
|
* <P>- one referenced MBean in the value is not an Object of the MBean
|
|
* class expected for that role
|
|
* <P>or
|
|
* <P>- an MBean provided for that role does not exist
|
|
*
|
|
* @see #getRole
|
|
*/
|
|
public void setRole(String relationId,
|
|
Role role)
|
|
throws RelationServiceNotRegisteredException,
|
|
IllegalArgumentException,
|
|
RelationNotFoundException,
|
|
RoleNotFoundException,
|
|
InvalidRoleValueException {
|
|
|
|
if (relationId == null || role == null) {
|
|
String excMsg = "Invalid parameter.";
|
|
throw new IllegalArgumentException(excMsg);
|
|
}
|
|
|
|
RELATION_LOGGER.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 deregistrations.
|
|
*
|
|
* @param relationId relation id
|
|
* @param roleList list of roles to be set
|
|
*
|
|
* @return a RoleResult object, including a RoleList (for roles
|
|
* successfully set) and a RoleUnresolvedList (for roles not
|
|
* set).
|
|
*
|
|
* @exception RelationServiceNotRegisteredException if the Relation
|
|
* Service is not registered in the MBean Server
|
|
* @exception IllegalArgumentException if null parameter
|
|
* @exception RelationNotFoundException if no relation with given id
|
|
*
|
|
* @see #getRoles
|
|
*/
|
|
public RoleResult setRoles(String relationId,
|
|
RoleList roleList)
|
|
throws RelationServiceNotRegisteredException,
|
|
IllegalArgumentException,
|
|
RelationNotFoundException {
|
|
|
|
if (relationId == null || roleList == null) {
|
|
String excMsg = "Invalid parameter.";
|
|
throw new IllegalArgumentException(excMsg);
|
|
}
|
|
|
|
RELATION_LOGGER.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 {@literal ->} ArrayList of String (role names)
|
|
*
|
|
* @exception IllegalArgumentException if null parameter
|
|
* @exception RelationNotFoundException if no relation for given
|
|
* relation id
|
|
*/
|
|
public Map<ObjectName,List<String>>
|
|
getReferencedMBeans(String relationId)
|
|
throws IllegalArgumentException,
|
|
RelationNotFoundException {
|
|
|
|
if (relationId == null) {
|
|
String excMsg = "Invalid parameter.";
|
|
throw new IllegalArgumentException(excMsg);
|
|
}
|
|
|
|
RELATION_LOGGER.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 deregistrations
|
|
//
|
|
// -param newRefList ArrayList of ObjectNames for new references done
|
|
// to MBeans (can be null)
|
|
// -param obsoleteRefList ArrayList of ObjectNames for obsolete references
|
|
// to MBeans (can be null)
|
|
//
|
|
// -exception RelationServiceNotRegisteredException if the Relation
|
|
// Service is not registered in the MBean Server.
|
|
private void updateUnregistrationListener(List<ObjectName> newRefList,
|
|
List<ObjectName> obsoleteRefList)
|
|
throws RelationServiceNotRegisteredException {
|
|
|
|
if (newRefList != null && obsoleteRefList != null) {
|
|
if (newRefList.isEmpty() && obsoleteRefList.isEmpty()) {
|
|
// Nothing to do :)
|
|
return;
|
|
}
|
|
}
|
|
|
|
RELATION_LOGGER.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;
|
|
}
|
|
}
|