0001: /* JFox, the OpenSource J2EE Application Server
0002: *
0003: * Copyright (C) 2002 huihoo.org
0004: * Distributable under GNU LGPL license
0005: * See the GNU Lesser General Public License for more details.
0006: */
0007:
0008: package javax.management.relation;
0009:
0010: import java.util.ArrayList;
0011: import java.util.List;
0012: import java.util.Map;
0013: import java.util.HashMap;
0014: import java.util.HashSet;
0015: import java.util.Set;
0016: import java.util.Iterator;
0017: import javax.management.NotificationBroadcasterSupport;
0018: import javax.management.MBeanRegistration;
0019: import javax.management.NotificationListener;
0020: import javax.management.ObjectName;
0021: import javax.management.MBeanServer;
0022: import javax.management.JMRuntimeException;
0023: import javax.management.Notification;
0024: import javax.management.MBeanServerNotification;
0025: import javax.management.InstanceNotFoundException;
0026: import javax.management.ReflectionException;
0027: import javax.management.MBeanException;
0028: import javax.management.MBeanNotificationInfo; //import javax.management.MBeanServerInvocationHandler;
0029: import javax.management.AttributeNotFoundException;
0030: import javax.management.Attribute;
0031:
0032: import org.huihoo.jfox.jmx.ExtendedMBeanServerDelegate;
0033:
0034: /**
0035: *
0036: * @author <a href="mailto:young_yy@hotmail.org">Young Yang</a>
0037: */
0038:
0039: public class RelationService extends NotificationBroadcasterSupport
0040: implements RelationServiceMBean, MBeanRegistration,
0041: NotificationListener {
0042:
0043: // contains the RelationTypeRepository Map (relationtypename = > RelationTypeRepository object)
0044: private Map relationTypeMap = new HashMap();
0045: // relationId = > [RelationSupport(internal)/ObjectName(external)]
0046: private Map relationMap = new HashMap();
0047:
0048: // Flag to indicate if, when a notification is received for the
0049: // unregistration of a MBean referenced in a relation, if an immediate
0050: // "purge" of the relations (look for the relations no
0051: // longer valid) has to be performed , or if that will be performed only
0052: // when the purgeRelations method will be explicitly called.
0053: // true is immediate purge.
0054: private boolean purgeFlag = true;
0055:
0056: // Internal counter to provide sequence numbers for notifications sent by:
0057: // - the Relation Service
0058: // - a relation handled by the Relation Service
0059: private volatile long notifSequence = 0L;
0060:
0061: // ObjectName used to register the Relation Service in the MBean Server
0062: private ObjectName relServObjectName = null;
0063:
0064: // MBean Server where the Relation Service is registered
0065: private MBeanServer mbeanServer = null;
0066:
0067: // Filter registered in the MBean Server with the Relation Service to be
0068: // informed of referenced MBean unregistrations
0069: private MBeanServerNotificationFilter unregNotifationFilter = new MBeanServerNotificationFilter();
0070:
0071: // List of unregistration notifications received (storage used if purge
0072: // of relations when unregistering a referenced MBean is not immediate but
0073: // on user request)
0074: private List unregNotifications = new ArrayList();
0075:
0076: public RelationService(boolean purgeFlag) {
0077: setPurgeFlag(purgeFlag);
0078: }
0079:
0080: /**
0081: * Sets the flag to indicate if when a notification is received for the
0082: * unregistration of a MBean referenced in a relation, if an immediate
0083: * "purge" of the relations (look for the relations no longer valid)
0084: * has to be performed , or if that will be performed only when the
0085: * purgeRelations method will be explicitly called.
0086: * <P>true is immediate purge.
0087: *
0088: * @param flag flag
0089: */
0090: public void setPurgeFlag(boolean flag) {
0091: purgeFlag = flag;
0092: }
0093:
0094: public boolean getPurgeFlag() {
0095: return purgeFlag;
0096: }
0097:
0098: public void isActive() throws RelationServiceNotRegisteredException {
0099: if (mbeanServer == null) {
0100: throw new RelationServiceNotRegisteredException(
0101: "Relation Service not registered in the MBean Server.");
0102: }
0103: }
0104:
0105: /**
0106: * Creates a relation type (a RelationTypeSupport object) with given
0107: * role infos (provided by the RoleInfo objects), and adds it in the
0108: * Relation Service.
0109: *
0110: */
0111: public void createRelationType(String relTypeName,
0112: RoleInfo[] roleInfoArray) throws IllegalArgumentException,
0113: InvalidRelationTypeException {
0114:
0115: if (relTypeName == null || roleInfoArray == null) {
0116: throw new IllegalArgumentException(
0117: "Invalid parameter: relTypeName and roleInfoArray can not be null.");
0118: }
0119:
0120: // Can throw an InvalidRelationTypeException
0121: RelationType relType = new RelationTypeSupport(relTypeName,
0122: roleInfoArray);
0123: this .addRelationType(relType);
0124: }
0125:
0126: /**
0127: * Adds given object as a relation type. The object is expected to
0128: * implement the relationType interface.
0129: *
0130: * @param relationType relation type object (implementing the
0131: * relationType interface)
0132: *
0133: */
0134: public void addRelationType(RelationType relationType)
0135: throws IllegalArgumentException,
0136: InvalidRelationTypeException {
0137: String relTypeName = relationType.getRelationTypeName();
0138: if (relationTypeMap.containsKey(relTypeName)) {
0139: throw new InvalidRelationTypeException(
0140: "There is already a relation type in the Relation Service with name "
0141: + relTypeName);
0142: }
0143:
0144: RelationTypeRepository rtrepo = new RelationTypeRepository(
0145: relationType);
0146:
0147: synchronized (relationTypeMap) {
0148: relationTypeMap.put(relTypeName, rtrepo);
0149: }
0150:
0151: // if a RelationType have added in a RelationService, it can not be changed
0152: if (relationType instanceof RelationTypeSupport) {
0153: ((RelationTypeSupport) relationType)
0154: .setRelationServiceFlag(true);
0155: }
0156: }
0157:
0158: /**
0159: * doCreate a internal Relation
0160: */
0161:
0162: public void createRelation(String relationId, String relTypeName,
0163: RoleList roleList)
0164: throws RelationServiceNotRegisteredException,
0165: IllegalArgumentException, RoleNotFoundException,
0166: InvalidRelationIdException, RelationTypeNotFoundException,
0167: InvalidRoleValueException {
0168:
0169: // Can throw RelationServiceNotRegisteredException
0170: isActive();
0171:
0172: if (relationId == null || relTypeName == null) {
0173: throw new IllegalArgumentException(
0174: "Invalid parameter: relationId and relationTypeName can not be null.");
0175: }
0176:
0177: // Creates RelationSupport object
0178: // Can throw InvalidRoleValueException
0179: RelationSupport relationObj = new InternalRelationSupport(
0180: relationId, relTypeName, roleList);
0181: this ._addRelation(relationId, relationObj, relTypeName,
0182: roleList);
0183: }
0184:
0185: /**
0186: * add a external Relation with it's DEFAULT_OBJECTNAME
0187: */
0188: public void addRelation(ObjectName objectName)
0189: throws IllegalArgumentException,
0190: RelationServiceNotRegisteredException,
0191: NoSuchMethodException, InvalidRelationIdException,
0192: InstanceNotFoundException, InvalidRelationServiceException,
0193: RelationTypeNotFoundException, RoleNotFoundException,
0194: InvalidRoleValueException {
0195:
0196: if (objectName == null) {
0197: throw new IllegalArgumentException(
0198: "Invalid parameter: DEFAULT_OBJECTNAME can not be null.");
0199: }
0200:
0201: // Can throw RelationServiceNotRegisteredException
0202: isActive();
0203:
0204: // not a RelationSupportMBean
0205: if (!(mbeanServer.isInstanceOf(objectName,
0206: "javax.management.relation.Relation"))) {
0207: throw new NoSuchMethodException(
0208: "This MBean does not implement the Relation interface: "
0209: + objectName);
0210: }
0211:
0212: String relationId = null;
0213: ObjectName relServObjName = null;
0214: String relTypeName = null;
0215: RoleList roleList = null;
0216:
0217: try {
0218: relationId = (String) (mbeanServer.getAttribute(objectName,
0219: "RelationId"));
0220:
0221: if (relationId == null) {
0222: throw new InvalidRelationIdException(
0223: "This MBean does not provide a relation id.");
0224: }
0225:
0226: // check RelationService ObjectName
0227: relServObjName = (ObjectName) (mbeanServer.getAttribute(
0228: objectName, "RelationServiceName"));
0229: if (relServObjName == null
0230: || !(relServObjName.equals(this .relServObjectName))) {
0231: throw new InvalidRelationServiceException(
0232: "The Relation Service referenced in the MBean is not the current one: "
0233: + relServObjName);
0234: }
0235:
0236: // check RelationTypeName
0237: relTypeName = (String) (mbeanServer.getAttribute(
0238: objectName, "RelationTypeName"));
0239: if (relTypeName == null) {
0240: throw new RelationTypeNotFoundException(
0241: "No relation type provided.");
0242: }
0243:
0244: // check RoleList
0245: roleList = (RoleList) (mbeanServer.invoke(objectName,
0246: "retrieveAllRoles", null, null));
0247: } catch (AttributeNotFoundException e) {
0248: throw new JMRuntimeException(e.getMessage());
0249: } catch (MBeanException e) {
0250: throw new JMRuntimeException((e.getTargetException())
0251: .getMessage());
0252: } catch (ReflectionException e) {
0253: throw new JMRuntimeException(e.getMessage());
0254: }
0255:
0256: this
0257: ._addRelation(relationId, objectName, relTypeName,
0258: roleList);
0259:
0260: // Updates flag to specify that the relation is managed by the Relation
0261: // Service
0262: // This flag and setter are inherited from RelationSupport and not parts
0263: // of the Relation interface, so may be not supported.
0264: try {
0265: Attribute attribute = new Attribute(
0266: "RelationServiceManagementFlag", Boolean.TRUE);
0267: mbeanServer.setAttribute(objectName, attribute);
0268: // "RelationServiceManagementFlag",
0269: // new Object[]{Boolean.TRUE},
0270: // new String[]{"java.lang.Boolean"});
0271: } catch (Exception e) {
0272: e.printStackTrace();
0273: }
0274: // update unregNotificationFilter
0275: // System.out.println("!!!!!!!! notification enable: " + objectName);
0276: unregNotifationFilter.enableObjectName(objectName);
0277: }
0278:
0279: // do adding RelationSupport or relation ObjectName to RelationService
0280: private void _addRelation(String relationId, Object relation,
0281: String relTypeName, RoleList roleList)
0282: throws RelationTypeNotFoundException,
0283: InvalidRelationIdException, InvalidRoleValueException,
0284: RoleNotFoundException {
0285: if (!relationTypeMap.containsKey(relTypeName)) {
0286: throw new RelationTypeNotFoundException(relTypeName);
0287: }
0288: if (relationMap.containsKey(relationId)) {
0289: throw new InvalidRelationIdException(
0290: "There is already a relation with id: "
0291: + relationId);
0292:
0293: }
0294:
0295: RelationTypeRepository rtrepo = (RelationTypeRepository) relationTypeMap
0296: .get(relTypeName);
0297: RelationType relationType = rtrepo.getRelationType();
0298: List roleInfos = new ArrayList(relationType.getRoleInfos());
0299:
0300: if (roleList != null) {
0301: for (int i = 0; i < roleList.size(); i++) {
0302: Role role = (Role) roleList.get(i);
0303: Integer status = checkRoleWriting(role, relTypeName,
0304: Boolean.TRUE); // is initialize becaus doCreate
0305: if (status.intValue() != 0) { // check writable failed
0306: throw new InvalidRoleValueException(
0307: "problem status: " + status.intValue());
0308: }
0309: RoleInfo roleInfo = null;
0310: try {
0311: roleInfo = relationType.getRoleInfo(role
0312: .getRoleName());
0313: } catch (RoleInfoNotFoundException e) {
0314: throw new RoleNotFoundException(role.getRoleName());
0315: }
0316: roleInfos.remove(roleInfo); // remove the exists roleInfo, the others will be added below
0317: }
0318: }
0319:
0320: // For each role info (corresponding to a role not initialised by the
0321: // role list provided by the user), try to set in the relation a role
0322: // with an empty list of ObjectNames.
0323: // A check is performed to verify that the role can be set to an
0324: // empty value, according to its minimum cardinality
0325: if (!roleInfos.isEmpty()) {
0326: for (Iterator roleInfoIter = roleInfos.iterator(); roleInfoIter
0327: .hasNext();) {
0328: RoleInfo currRoleInfo = (RoleInfo) (roleInfoIter.next());
0329: String roleName = currRoleInfo.getName();
0330:
0331: // Creates an empty value
0332: ArrayList emptyValue = new ArrayList();
0333: // Creates a role
0334: Role role = new Role(roleName, emptyValue);
0335:
0336: if (relation instanceof RelationSupport) {
0337:
0338: // Internal relation
0339: // Can throw InvalidRoleValueException
0340: //
0341: // Will not throw RoleNotFoundException (role to be
0342: // initialised), or RelationNotFoundException, or
0343: // RelationTypeNotFoundException
0344: try {
0345: ((RelationSupport) relation).setRole(role);
0346:
0347: } catch (Exception e) {
0348: throw new JMRuntimeException(e.getMessage());
0349: }
0350: } else {
0351:
0352: // Relation is a MBean
0353: // Use standard setRole()
0354: // Can throw MBeanException wrapping
0355: // InvalidRoleValueException. Returns the target exception to
0356: // be homogeneous.
0357: //
0358: // Will not throw MBeanException (wrapping
0359: // RoleNotFoundException or MBeanException) or
0360: // InstanceNotFoundException, or ReflectionException
0361: //
0362: // Again here the assumption is that the Relation Service and
0363: // the relation MBeans are registered in the same MBean Server.
0364: try {
0365: Attribute attribute = new Attribute("Role",
0366: role);
0367: mbeanServer.setAttribute((ObjectName) relation,
0368: attribute);
0369: // mbeanServer.invoke((ObjectName)relation,
0370: // "setRole",
0371: // new Object[]{role},
0372: // new String[]{"javax.management.relation.Role"});
0373:
0374: } catch (MBeanException e) {
0375: Exception target = e.getTargetException();
0376: if (target instanceof InvalidRoleValueException) {
0377: throw ((InvalidRoleValueException) target);
0378: } else {
0379: throw new JMRuntimeException(target
0380: .getMessage());
0381: }
0382: } catch (Exception e) {
0383: throw new JMRuntimeException(e.getMessage());
0384: }
0385: }
0386: }
0387: }
0388:
0389: rtrepo.addRelationId(relationId);
0390:
0391: // put the relation to the relationMap
0392: synchronized (relationMap) {
0393: relationMap.put(relationId, relation);
0394: }
0395:
0396: try {
0397: sendRelationCreationNotification(relationId);
0398: } catch (RelationNotFoundException e) {
0399: e.printStackTrace();
0400: }
0401: }
0402:
0403: /**
0404: * Retrieves names of all known relation types
0405: *
0406: * @return ArrayList of relation type names (Strings)
0407: */
0408: public List getAllRelationTypeNames() {
0409: synchronized (relationTypeMap) {
0410: return new ArrayList(relationTypeMap.keySet());
0411: }
0412: }
0413:
0414: public List getAllRelationIds() {
0415: synchronized (relationMap) {
0416: return new ArrayList(relationMap.keySet());
0417: }
0418: }
0419:
0420: /**
0421: * Retrieves list of role infos (RoleInfo objects) of a given relation
0422: * type
0423: */
0424: public List getRoleInfos(String relTypeName)
0425: throws IllegalArgumentException,
0426: RelationTypeNotFoundException {
0427:
0428: if (relTypeName == null) {
0429: throw new IllegalArgumentException(
0430: "Invalid parameter: relTypeName can not be null.");
0431: }
0432:
0433: if (!relationTypeMap.containsKey(relTypeName)) {
0434: throw new RelationTypeNotFoundException(relTypeName);
0435: }
0436:
0437: RelationType relType = ((RelationTypeRepository) relationTypeMap
0438: .get(relTypeName)).getRelationType();
0439:
0440: return relType.getRoleInfos();
0441: }
0442:
0443: public RoleInfo getRoleInfo(String relTypeName, String roleInfoName)
0444: throws IllegalArgumentException,
0445: RelationTypeNotFoundException, RoleInfoNotFoundException {
0446:
0447: if (relTypeName == null || roleInfoName == null) {
0448: throw new IllegalArgumentException(
0449: "Invalid parameter: relTypeName and roleInfoName can not be null.");
0450: }
0451:
0452: if (!relationTypeMap.containsKey(relTypeName)) {
0453: throw new RelationTypeNotFoundException(relTypeName);
0454: }
0455:
0456: RelationType relType = ((RelationTypeRepository) relationTypeMap
0457: .get(relTypeName)).getRelationType();
0458:
0459: return relType.getRoleInfo(roleInfoName);
0460: }
0461:
0462: public RoleResult getAllRoles(String relationId)
0463: throws IllegalArgumentException, RelationNotFoundException,
0464: RelationServiceNotRegisteredException {
0465:
0466: if (relationId == null) {
0467: throw new IllegalArgumentException(
0468: "Invalid parameter: relationId can not be null.");
0469: }
0470:
0471: // Can throw a RelationNotFoundException
0472: Object relation = getRelation(relationId);
0473:
0474: RoleResult result = null;
0475:
0476: if (relation instanceof RelationSupport) {
0477: // Internal relation
0478: result = ((RelationSupport) relation).getAllRoles();
0479:
0480: } else {
0481: // Relation MBean
0482: try {
0483: result = (RoleResult) (mbeanServer.getAttribute(
0484: ((ObjectName) relation), "AllRoles"));
0485: // result = (RoleResult)(mbeanServer.invoke(((ObjectName)relation),
0486: // "getAllRoles",
0487: // null,
0488: // null));
0489: } catch (Exception e) {
0490: throw new JMRuntimeException(e.getMessage());
0491: }
0492: }
0493:
0494: return result;
0495: }
0496:
0497: public List getRole(String relationId, String roleName)
0498: throws RelationServiceNotRegisteredException,
0499: IllegalArgumentException, RelationNotFoundException,
0500: RoleNotFoundException {
0501:
0502: if (relationId == null || roleName == null) {
0503: throw new IllegalArgumentException(
0504: "Invalid parameter: relationId and roleName can not be null.");
0505: }
0506:
0507: // Can throw RelationServiceNotRegisteredException
0508: isActive();
0509:
0510: // Can throw a RelationNotFoundException
0511: Object relation = getRelation(relationId);
0512:
0513: List result = null;
0514:
0515: if (relation instanceof RelationSupport) {
0516: // Internal relation
0517: // Can throw RoleNotFoundException
0518: result = ((RelationSupport) relation).getRole(roleName);
0519: } else {
0520: // Relation MBean
0521: // Can throw MBeanException wrapping a RoleNotFoundException:
0522: // throw wrapped exception
0523: //
0524: // Shall not throw InstanceNotFoundException or ReflectionException
0525: try {
0526: result = (List) (mbeanServer.invoke(
0527: ((ObjectName) relation), "getRole",
0528: new Object[] { roleName },
0529: new String[] { "java.lang.String" }));
0530: } catch (MBeanException e) {
0531: Exception target = e.getTargetException();
0532: if (target instanceof RoleNotFoundException) {
0533: throw ((RoleNotFoundException) target);
0534: } else {
0535: throw new JMRuntimeException(target.getMessage());
0536: }
0537: } catch (Exception e) {
0538: throw new JMRuntimeException(e.getMessage());
0539: }
0540:
0541: }
0542:
0543: return result;
0544: }
0545:
0546: public Integer getRoleCardinality(String relationId, String roleName)
0547: throws IllegalArgumentException, RelationNotFoundException,
0548: RoleNotFoundException {
0549:
0550: if (relationId == null || roleName == null) {
0551: throw new IllegalArgumentException(
0552: "Invalid parameter: relationId and roleName can not be null.");
0553: }
0554: // Can throw a RelationNotFoundException
0555: Object relation = getRelation(relationId);
0556:
0557: Integer result = null;
0558:
0559: if (relation instanceof RelationSupport) {
0560: // Internal relation
0561: // Can throw RoleNotFoundException
0562: result = ((RelationSupport) relation)
0563: .getRoleCardinality(roleName);
0564: } else {
0565: // Relation MBean
0566: Object[] params = new Object[1];
0567: params[0] = roleName;
0568: String[] signature = new String[1];
0569: signature[0] = "java.lang.String";
0570: // Can throw MBeanException wrapping RoleNotFoundException:
0571: // throw wrapped exception
0572: //
0573: // Shall not throw InstanceNotFoundException or ReflectionException
0574: try {
0575: result = (Integer) (mbeanServer.invoke(
0576: ((ObjectName) relation), "getRoleCardinality",
0577: new Object[] { roleName },
0578: new String[] { "java.lang.String" }));
0579: } catch (MBeanException e) {
0580: Exception target = e.getTargetException();
0581: if (target instanceof RoleNotFoundException) {
0582: throw ((RoleNotFoundException) target);
0583: } else {
0584: throw new JMRuntimeException(target.getMessage());
0585: }
0586: } catch (Exception e) {
0587: throw new JMRuntimeException(e.getMessage());
0588: }
0589: }
0590:
0591: return result;
0592: }
0593:
0594: public RoleResult getRoles(String relationId, String[] roleNames)
0595: throws RelationServiceNotRegisteredException,
0596: IllegalArgumentException, RelationNotFoundException {
0597:
0598: if (relationId == null || roleNames == null) {
0599: throw new IllegalArgumentException(
0600: "Invalid parameter: relationId and roleNames can not be null.");
0601: }
0602:
0603: // Can throw RelationServiceNotRegisteredException
0604: isActive();
0605:
0606: // Can throw a RelationNotFoundException
0607: Object relation = getRelation(relationId);
0608:
0609: RoleResult result = null;
0610:
0611: if (relation instanceof RelationSupport) {
0612: // Internal relation
0613: result = ((RelationSupport) relation).getRoles(roleNames);
0614: } else {
0615: // Relation MBean
0616: // Shall not throw InstanceNotFoundException, ReflectionException
0617: // or MBeanException
0618: try {
0619: result = (RoleResult) (mbeanServer
0620: .invoke(((ObjectName) relation), "getRoles",
0621: new Object[] { roleNames },
0622: new String[] { roleNames.getClass()
0623: .getName() }));
0624: } catch (MBeanException e) {
0625: throw new JMRuntimeException(e.getTargetException()
0626: .getMessage());
0627: } catch (Exception e) {
0628: throw new JMRuntimeException(e.getMessage());
0629: }
0630: }
0631:
0632: return result;
0633: }
0634:
0635: public List findRelationsOfType(String relTypeName)
0636: throws IllegalArgumentException,
0637: RelationTypeNotFoundException {
0638:
0639: if (relTypeName == null) {
0640: throw new IllegalArgumentException(
0641: "Invalid parameter: relTypeName can not be null.");
0642: }
0643:
0644: if (!relationTypeMap.containsKey(relTypeName)) {
0645: throw new RelationTypeNotFoundException(relTypeName);
0646: }
0647:
0648: RelationTypeRepository rtrepo = (RelationTypeRepository) relationTypeMap
0649: .get(relTypeName);
0650: return rtrepo.getAllRelationIds();
0651: }
0652:
0653: /**
0654: * Retrieves the relations where a given MBean is referenced.
0655: *
0656: * @param objectName ObjectName of MBean
0657: * @param relTypeName can be null; if specified, only the relations
0658: * of that type will be considered in the search. Else all relation types
0659: * are considered.
0660: * @param roleName can be null; if specified, only the relations
0661: * where the MBean is referenced in that role will be returned. Else all
0662: * roles are considered.
0663: *
0664: * @return an HashMap, where the keys are the relation ids of the relations
0665: * where the MBean is referenced, and the value is, for each key,
0666: * an ArrayList of role names (as a MBean can be referenced in several
0667: * roles in the same relation).
0668: */
0669: public Map findReferencingRelations(ObjectName objectName,
0670: String relTypeName, String roleName)
0671: throws IllegalArgumentException {
0672: if (objectName == null) {
0673: throw new IllegalArgumentException(
0674: "Invalid parameter: DEFAULT_OBJECTNAME can not be null.");
0675: }
0676: Map relationId2roleNames = new HashMap();
0677:
0678: List relationIds = new ArrayList();
0679: if (relTypeName == null) { // not specify the relType
0680: relationIds = this .getAllRelationIds();
0681: } else {
0682: if (!relationTypeMap.containsKey(relTypeName)) {
0683: throw new IllegalArgumentException(
0684: new RelationTypeNotFoundException(relTypeName)
0685: .getMessage());
0686: }
0687: relationIds = ((RelationTypeRepository) relationTypeMap
0688: .get(relTypeName)).getAllRelationIds();
0689: }
0690: for (Iterator relationIdIter = relationIds.iterator(); relationIdIter
0691: .hasNext();) {
0692: String relationId = (String) relationIdIter.next();
0693: List roleNames = new ArrayList();
0694: Map objectName2RoleNameList_Map;
0695: try {
0696: // get a Map (ObjectName => ArrayList of the roleNames)
0697: objectName2RoleNameList_Map = this
0698: .getReferencedMBeans(relationId);
0699: } catch (RelationNotFoundException e) {
0700: continue;
0701: }
0702:
0703: if (objectName2RoleNameList_Map.containsKey(objectName)) { //roleName found,means this relation has the mbean with this DEFAULT_OBJECTNAME
0704: List _roleNames = (List) objectName2RoleNameList_Map
0705: .get(objectName);
0706: if (roleName != null) { // roleName specified
0707: if (_roleNames.contains(roleName)) {
0708: roleNames.add(roleName);
0709: }
0710: } else {
0711: roleNames = _roleNames;
0712: }
0713:
0714: }
0715: if (!roleNames.isEmpty()) {
0716: relationId2roleNames.put(relationId, roleNames);
0717: }
0718: }
0719:
0720: return relationId2roleNames;
0721: }
0722:
0723: /**
0724: * Retrieves the MBeans associated to given one in a relation.
0725: * <P>This corresponds to CIM Associators and AssociatorNames operations.
0726: *
0727: * @param objectName ObjectName of MBean
0728: * @param relTypeName can be null; if specified, only the relations
0729: * of that type will be considered in the search. Else all
0730: * relation types are considered.
0731: * @param roleName can be null; if specified, only the relations
0732: * where the MBean is referenced in that role will be considered. Else all
0733: * roles are considered.
0734: *
0735: * @return an HashMap, where the keys are the ObjectNames of the MBeans
0736: * associated to given MBean, and the value is, for each key, an ArrayList
0737: * of the relation ids of the relations where the key MBean is
0738: * associated to given one (as they can be associated in several different
0739: * relations).
0740: *
0741: * @exception IllegalArgumentException if null parameter
0742: */
0743: public Map findAssociatedMBeans(ObjectName objectName,
0744: String relTypeName, String roleName)
0745: throws IllegalArgumentException {
0746:
0747: if (objectName == null) {
0748: throw new IllegalArgumentException(
0749: "Invalid parameter: DEFAULT_OBJECTNAME can not be null.");
0750: }
0751:
0752: HashMap objectName2relationIds = new HashMap();
0753:
0754: List relationIds = new ArrayList();
0755: if (relTypeName == null) { // not specify the relType
0756: relationIds = this .getAllRelationIds();
0757: } else {
0758: if (!relationTypeMap.containsKey(relTypeName)) {
0759: throw new IllegalArgumentException(
0760: new RelationTypeNotFoundException(relTypeName)
0761: .getMessage());
0762: }
0763: relationIds = ((RelationTypeRepository) relationTypeMap
0764: .get(relTypeName)).getAllRelationIds();
0765: }
0766:
0767: for (Iterator relationIdIter = relationIds.iterator(); relationIdIter
0768: .hasNext();) {
0769: String relationId = (String) relationIdIter.next();
0770: Map objectName2RoleNameList_Map = null;
0771: try {
0772: // get a Map (ObjectName => ArrayList of the roleNames)
0773: objectName2RoleNameList_Map = this
0774: .getReferencedMBeans(relationId);
0775: } catch (RelationNotFoundException e) {
0776: continue;
0777: }
0778: // this relation doesn't contain the DEFAULT_OBJECTNAME MBean, so continue
0779: if (!objectName2RoleNameList_Map.containsKey(objectName))
0780: continue;
0781:
0782: for (Iterator entryIter = objectName2RoleNameList_Map
0783: .entrySet().iterator(); entryIter.hasNext();) {
0784: Map.Entry entry = (Map.Entry) entryIter.next();
0785: ObjectName _objectName = (ObjectName) entry.getKey();
0786: List _roleNames = (List) entry.getValue();
0787:
0788: if (_objectName.equals(objectName))
0789: continue;
0790: if (roleName != null && !_roleNames.contains(roleName))
0791: continue;
0792:
0793: // _objectName not equals the DEFAULT_OBJECTNAME, so this MBean is associate with the DEFAULT_OBJECTNAME
0794: if (objectName2relationIds.containsKey(_objectName)) { // have added
0795: List _relationIds = (List) objectName2relationIds
0796: .get(_objectName);
0797: _relationIds.add(relationId);
0798: } else { // first add
0799: List _relationIds = new ArrayList();
0800: _relationIds.add(relationId);
0801: objectName2relationIds.put(_objectName,
0802: _relationIds);
0803: }
0804: }
0805: }
0806: return objectName2relationIds;
0807:
0808: }
0809:
0810: /**
0811: * Retrieves MBeans referenced in the various roles of the relation.
0812: *
0813: * @param relationId relation id
0814: *
0815: * @return a HashMap mapping:
0816: * <P> ObjectName -> ArrayList of String (role names)
0817: */
0818: public Map getReferencedMBeans(String relationId)
0819: throws IllegalArgumentException, RelationNotFoundException {
0820:
0821: if (relationId == null) {
0822: throw new IllegalArgumentException(
0823: "Invalid parameter: relationId can not be null.");
0824: }
0825: // Can throw a RelationNotFoundException
0826: Object relation = getRelation(relationId);
0827:
0828: Map result = null;
0829:
0830: if (relation instanceof RelationSupport) {
0831: // Internal relation
0832: result = ((RelationSupport) relation).getReferencedMBeans();
0833: } else {
0834: try {
0835: result = (Map) (mbeanServer.getAttribute(
0836: ((ObjectName) relation), "ReferencedMBeans"));
0837: // result = (Map)(mbeanServer.invoke(((ObjectName)relation),
0838: // "getReferencedMBeans",
0839: // null,
0840: // null));
0841: } catch (Exception e) {
0842: throw new JMRuntimeException(e.getMessage());
0843: }
0844: }
0845: return result;
0846: }
0847:
0848: public String getRelationTypeName(String relationId)
0849: throws IllegalArgumentException, RelationNotFoundException {
0850:
0851: if (relationId == null) {
0852: throw new IllegalArgumentException(
0853: "Invalid parameter: relationId can not be null.");
0854: }
0855:
0856: for (Iterator entryIter = relationTypeMap.entrySet().iterator(); entryIter
0857: .hasNext();) {
0858: Map.Entry entry = (Map.Entry) entryIter.next();
0859: String relTypeName = (String) entry.getKey();
0860: RelationTypeRepository rtrepo = (RelationTypeRepository) entry
0861: .getValue();
0862: List relationIds = rtrepo.getAllRelationIds();
0863: if (relationIds.contains(relationId))
0864: return relTypeName;
0865:
0866: }
0867:
0868: return null;
0869:
0870: /*
0871: System.out.println("getRelationTypeName: " + relationId);
0872: Object relation = this.getRelation(relationId);
0873: System.out.println("getRelationTypeName: " + relationId);
0874: String result = null;
0875:
0876: if (relation instanceof RelationSupport) {
0877: // Internal relation
0878: result = ((RelationSupport)relation).getRelationTypeName();
0879:
0880: }
0881: else if(relation instanceof ObjectName) { // Relation MBean ,external
0882: try {
0883: result = (String)(mbeanServer.invoke(((ObjectName)relation),
0884: "getRelationTypeName",
0885: null,null));
0886: }
0887: catch (Exception e) {
0888: throw new JMRuntimeException(e.getMessage());
0889: }
0890: }
0891: else {
0892: throw new JMRuntimeException("The relation object associate with " + relationId + " is neither RelationSupport nor ObjectName object");
0893: }
0894: System.out.println("getRelationTypeName: " + relationId);
0895:
0896: return result;
0897: */
0898: }
0899:
0900: public Boolean hasRelation(String relationId)
0901: throws IllegalArgumentException {
0902: if (relationId == null) {
0903: throw new IllegalArgumentException(
0904: "Invalid parameter: relationId can not be null.");
0905: }
0906:
0907: if (relationMap.containsKey(relationId)) {
0908: return Boolean.TRUE;
0909: }
0910:
0911: return Boolean.FALSE;
0912:
0913: }
0914:
0915: /**
0916: * return relation id (String) or null (if the ObjectName is not a relation handled by the Relation Service)
0917: */
0918: public String isRelation(ObjectName objectName)
0919: throws IllegalArgumentException {
0920: if (objectName == null) {
0921: throw new IllegalArgumentException(
0922: "Invalid parameter: DEFAULT_OBJECTNAME can not be null.");
0923: }
0924: for (Iterator entryIter = relationMap.entrySet().iterator(); entryIter
0925: .hasNext();) {
0926: Map.Entry entry = (Map.Entry) entryIter.next();
0927: Object relationObj = entry.getValue();
0928: if (relationObj instanceof ObjectName
0929: && objectName.equals(relationObj)) { // find it
0930: return (String) entry.getKey();
0931: }
0932: }
0933: return null;
0934: }
0935:
0936: /**
0937: * If the relation is represented by a MBean (created by the user and
0938: * added as a relation in the Relation Service), returns the ObjectName of
0939: * the MBean.
0940: *
0941: * @return ObjectName of the corresponding relation MBean, or null if
0942: * the relation is not a MBean. */
0943: public ObjectName isRelationMBean(String relationId)
0944: throws IllegalArgumentException, RelationNotFoundException {
0945:
0946: if (relationId == null) {
0947: throw new IllegalArgumentException(
0948: "Invalid parameter: relationId can not be null.");
0949: }
0950: // Can throw RelationNotFoundException
0951: Object result = getRelation(relationId);
0952: if (result instanceof ObjectName) {
0953: return ((ObjectName) result);
0954: }
0955: return null;
0956: }
0957:
0958: public Integer checkRoleReading(String roleName, String relTypeName)
0959: throws IllegalArgumentException,
0960: RelationTypeNotFoundException {
0961:
0962: if (roleName == null || relTypeName == null) {
0963: throw new IllegalArgumentException(
0964: "Invalid parameter: roleName and relTypeName can not be null.");
0965: }
0966:
0967: // Can throw a RelationTypeNotFoundException
0968: if (!relationTypeMap.containsKey(relTypeName)) {
0969: throw new RelationTypeNotFoundException(relTypeName);
0970: }
0971:
0972: RelationType relType = ((RelationTypeRepository) relationTypeMap
0973: .get(relTypeName)).getRelationType();
0974:
0975: RoleInfo roleInfo = null;
0976: try {
0977: roleInfo = relType.getRoleInfo(roleName);
0978: } catch (RoleInfoNotFoundException e) {
0979: return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
0980: }
0981:
0982: if (!roleInfo.isReadable()) {
0983: return new Integer(RoleStatus.ROLE_NOT_READABLE);
0984: }
0985: return new Integer(0);
0986: }
0987:
0988: public Integer checkRoleWriting(Role role, String relTypeName,
0989: Boolean initFlag) throws IllegalArgumentException,
0990: RelationTypeNotFoundException {
0991:
0992: if (role == null || relTypeName == null || initFlag == null) {
0993: throw new IllegalArgumentException(
0994: "Invalid parameter: role,relTypeName and initFlag can not be null.");
0995: }
0996:
0997: if (!relationTypeMap.containsKey(relTypeName)) {
0998: throw new RelationTypeNotFoundException(relTypeName);
0999: }
1000:
1001: RelationType relType = ((RelationTypeRepository) relationTypeMap
1002: .get(relTypeName)).getRelationType();
1003:
1004: String roleName = role.getRoleName();
1005: List roleValue = role.getRoleValue();
1006:
1007: RoleInfo roleInfo = null;
1008: try {
1009: roleInfo = relType.getRoleInfo(roleName);
1010: } catch (RoleInfoNotFoundException exc) {
1011: return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
1012: }
1013:
1014: if (!initFlag.booleanValue()) { // must check the writable
1015: boolean isWritable = roleInfo.isWritable();
1016: if (!isWritable) {
1017: return new Integer(RoleStatus.ROLE_NOT_WRITABLE);
1018: }
1019: }
1020:
1021: // check cardinality
1022: int cardinality = roleValue.size();
1023: // Checks minimum cardinality
1024: boolean chkMinFlag = roleInfo.checkMinDegree(cardinality);
1025: if (!chkMinFlag) {
1026: return new Integer(RoleStatus.LESS_THAN_MIN_ROLE_DEGREE);
1027: }
1028:
1029: // Checks maximum cardinality
1030: boolean chkMaxFlag = roleInfo.checkMaxDegree(cardinality);
1031: if (!chkMaxFlag) {
1032: return new Integer(RoleStatus.MORE_THAN_MAX_ROLE_DEGREE);
1033: }
1034:
1035: // Verifies that each referenced MBean is registered in the MBean
1036: // Server and that it is an instance of the class specified in the
1037: // role info, or of a subclass of it
1038: // Note that here again this is under the assumption that
1039: // referenced MBeans, relation MBeans and the Relation Service are
1040: // registered in the same MBean Server.
1041: String expClassName = roleInfo.getRefMBeanClassName();
1042:
1043: for (Iterator refMBeanIter = roleValue.iterator(); refMBeanIter
1044: .hasNext();) {
1045: ObjectName objectName = (ObjectName) (refMBeanIter.next());
1046: // Checks it is registered
1047: if (objectName == null) {
1048: return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
1049: }
1050: boolean isRegistered = mbeanServer.isRegistered(objectName);
1051: if (!isRegistered) {
1052: return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
1053: }
1054:
1055: // Checks if it is of the correct class
1056: // Can throw an InstanceNotFoundException, but not here as checked
1057: // above
1058: try {
1059: boolean isInstanceOf = mbeanServer.isInstanceOf(
1060: objectName, expClassName);
1061: if (!isInstanceOf) {
1062: return new Integer(
1063: RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS);
1064: }
1065: } catch (InstanceNotFoundException e) {
1066: return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
1067: }
1068: }
1069: // System.out.println("CheckWritable end");
1070: return new Integer(0); // check OK
1071: }
1072:
1073: /**
1074: * Invoked when a JMX notification occurs.
1075: * Currently handles notifications for unregistration of MBeans, either
1076: * referenced in a relation role or being a relation itself.
1077: *
1078: * @param notif The notification.
1079: * @param handback An opaque object which helps the listener to
1080: * associate information regarding the MBean emitter (can be null).
1081: */
1082: public void handleNotification(Notification notif, Object handback) {
1083: if (notif == null) {
1084: throw new IllegalArgumentException(
1085: "Invalid parameter: notification can not be null.");
1086: }
1087:
1088: if (!(notif instanceof MBeanServerNotification))
1089: return;
1090:
1091: String notifType = notif.getType();
1092: if (!notifType
1093: .equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION))
1094: return;
1095:
1096: ObjectName objectName = ((MBeanServerNotification) notif)
1097: .getMBeanName();
1098:
1099: unregNotifationFilter.disableObjectName(objectName);
1100:
1101: String relationId = this .isRelation(objectName);
1102: if (relationId != null) { // is a RelationSupportMBean
1103: try {
1104: // remove this relation
1105: this .removeRelation(relationId);
1106: } catch (RelationServiceNotRegisteredException e) {
1107: e.printStackTrace();
1108: } catch (RelationNotFoundException e) {
1109: e.printStackTrace();
1110: }
1111: } else { // common mbean
1112: boolean isInRelation = this .isInRelation(objectName);
1113: if (!isInRelation)
1114: return;
1115: unregNotifications.add(notif); // add unregistration notification
1116: if (!purgeFlag)
1117: return; // will manual run purgeRelations
1118: try {
1119: // MBean have been unregistered
1120: this .purgeRelations();
1121: } catch (RelationServiceNotRegisteredException e) {
1122: e.printStackTrace();
1123: }
1124: }
1125: }
1126:
1127: public void removeRelationType(String relTypeName)
1128: throws RelationServiceNotRegisteredException,
1129: IllegalArgumentException, RelationTypeNotFoundException {
1130:
1131: if (relTypeName == null) {
1132: throw new IllegalArgumentException(
1133: "Invalid parameter: relationTypeName can not be null.");
1134: }
1135:
1136: // Can throw RelationServiceNotRegisteredException
1137: isActive();
1138:
1139: if (!relationTypeMap.containsKey(relTypeName)) {
1140: throw new RelationTypeNotFoundException(relTypeName);
1141: }
1142:
1143: RelationTypeRepository rtrepo = (RelationTypeRepository) relationTypeMap
1144: .get(relTypeName);
1145: Iterator relationIds = rtrepo.getAllRelationIds().iterator();
1146: while (relationIds.hasNext()) {
1147: String relationId = (String) relationIds.next();
1148: try {
1149: this .removeRelation(relationId);
1150: } catch (RelationNotFoundException e) {
1151: e.printStackTrace();
1152: }
1153: }
1154: relationTypeMap.remove(relTypeName);
1155: }
1156:
1157: public void setRole(String relationId, Role role)
1158: throws RelationServiceNotRegisteredException,
1159: IllegalArgumentException, RelationNotFoundException,
1160: RoleNotFoundException, InvalidRoleValueException {
1161:
1162: if (relationId == null || role == null) {
1163: throw new IllegalArgumentException(
1164: "Invalid parameter: relationId and role can not be null.");
1165: }
1166:
1167: // Can throw RelationServiceNotRegisteredException
1168: isActive();
1169:
1170: // Can throw a RelationNotFoundException
1171: Object relation = getRelation(relationId);
1172:
1173: if (relation instanceof RelationSupport) {
1174: // Internal relation
1175: // Can throw RoleNotFoundException,
1176: // InvalidRoleValueException and
1177: // RelationServiceNotRegisteredException
1178: //
1179: // Shall not throw RelationTypeNotFoundException
1180: // (as relation exists in the RS, its relation type is known)
1181: try {
1182: ((RelationSupport) relation).setRole(role);
1183:
1184: } catch (RelationTypeNotFoundException exc) {
1185: throw new JMRuntimeException(exc.getMessage());
1186: }
1187:
1188: } else {
1189: // Relation MBean
1190: // Can throw MBeanException wrapping RoleNotFoundException,
1191: // InvalidRoleValueException
1192: //
1193: // Shall not MBeanException wrapping a MBeanException wrapping
1194: // RelationTypeNotFoundException, or ReflectionException, or
1195: // InstanceNotFoundException
1196: try {
1197: Attribute attribute = new Attribute("Role", role);
1198: mbeanServer.setAttribute((ObjectName) relation,
1199: attribute);
1200: // mbeanServer.invoke(((ObjectName)relation),
1201: // "setRole",
1202: // new Object[]{role},
1203: // new String[]{"javax.management.relation.Role"});
1204:
1205: } catch (MBeanException e) {
1206: Exception target = e.getTargetException();
1207: if (target instanceof RoleNotFoundException) {
1208: throw ((RoleNotFoundException) target);
1209: } else if (target instanceof InvalidRoleValueException) {
1210: throw ((InvalidRoleValueException) target);
1211: } else {
1212: throw new JMRuntimeException(target.getMessage());
1213:
1214: }
1215: } catch (Exception e) {
1216: throw new JMRuntimeException(e.getMessage());
1217: }
1218: }
1219:
1220: return;
1221: }
1222:
1223: public RoleResult setRoles(String relationId, RoleList roleList)
1224: throws RelationServiceNotRegisteredException,
1225: IllegalArgumentException, RelationNotFoundException {
1226:
1227: if (relationId == null || roleList == null) {
1228: throw new IllegalArgumentException(
1229: "Invalid parameter: relationId and roleList can not be null.");
1230: }
1231:
1232: // Can throw RelationServiceNotRegisteredException
1233: isActive();
1234:
1235: // Can throw a RelationNotFoundException
1236: Object relation = getRelation(relationId);
1237:
1238: RoleResult result = null;
1239:
1240: if (relation instanceof RelationSupport) {
1241: // Internal relation
1242: // Can throw RelationServiceNotRegisteredException
1243: //
1244: // Shall not throw RelationTypeNotFoundException (as relation is
1245: // known, its relation type exists)
1246: try {
1247: result = ((RelationSupport) relation)
1248: .setRoles(roleList);
1249: } catch (RelationTypeNotFoundException exc) {
1250: throw new JMRuntimeException(exc.getMessage());
1251: }
1252: } else {
1253: // Relation MBean
1254: // Shall not throw InstanceNotFoundException or a MBeanException
1255: // or ReflectionException
1256: try {
1257: result = (RoleResult) (mbeanServer
1258: .invoke(
1259: ((ObjectName) relation),
1260: "setRoles",
1261: new Object[] { roleList },
1262: new String[] { "javax.management.relation.RoleList" }));
1263: } catch (MBeanException e) {
1264: throw new JMRuntimeException((e.getTargetException())
1265: .getMessage());
1266: } catch (Exception e) {
1267: throw new JMRuntimeException(e.getMessage());
1268: }
1269: }
1270:
1271: return result;
1272: }
1273:
1274: // !!! note: some mbean may be have more than one role in a relation
1275: public void updateRoleMap(String relationId, Role role,
1276: List oldRoleValue) throws IllegalArgumentException,
1277: RelationServiceNotRegisteredException,
1278: RelationNotFoundException {
1279:
1280: if (relationId == null || role == null || oldRoleValue == null) {
1281: throw new IllegalArgumentException(
1282: "Invalid parameter: relationId,role and oldRoleValue can not be null.");
1283: }
1284:
1285: // Can throw RelationServiceNotRegisteredException
1286: isActive();
1287:
1288: Map objectName2roleNames = this .getReferencedMBeans(relationId);
1289:
1290: List newRoleValue = role.getRoleValue();
1291:
1292: // for(int i = 0; i<newRoleValue.size(); i++){
1293: // System.out.println("!!!!!!!!!enalble roleValue: " + newRoleValue.get(i));
1294: // }
1295:
1296: unregNotifationFilter
1297: .enableObjectNames((ObjectName[]) newRoleValue
1298: .toArray(new ObjectName[0]));
1299:
1300: // Each ObjectName remaining in oldRoleValue is an ObjectName no longer
1301: // referenced in new value
1302: for (Iterator oldRoleIter = oldRoleValue.iterator(); oldRoleIter
1303: .hasNext();) {
1304: ObjectName objectName = (ObjectName) (oldRoleIter.next());
1305: if (!objectName2roleNames.containsKey(objectName)) { // DEFAULT_OBJECTNAME not exist in the relation
1306: unregNotifationFilter.disableObjectName(objectName);
1307: }
1308: }
1309: }
1310:
1311: public void purgeRelations()
1312: throws RelationServiceNotRegisteredException {
1313:
1314: // Can throw RelationServiceNotRegisteredException
1315: isActive();
1316:
1317: // Clones the list of notifications to be able to still receive new
1318: // notifications while proceeding those ones
1319: ArrayList unregNofificationList = new ArrayList(
1320: unregNotifications);
1321: Set objectNames = new HashSet();
1322: for (Iterator notifIter = unregNofificationList.iterator(); notifIter
1323: .hasNext();) {
1324: MBeanServerNotification currNtf = (MBeanServerNotification) (notifIter
1325: .next());
1326: ObjectName unregMBeanName = currNtf.getMBeanName();
1327: objectNames.add(unregMBeanName);
1328: }
1329:
1330: for (Iterator objNameIter = objectNames.iterator(); objNameIter
1331: .hasNext();) {
1332: ObjectName unregMBeanName = (ObjectName) objNameIter.next();
1333: Map referencingRelations = this .findReferencingRelations(
1334: unregMBeanName, null, null);
1335:
1336: for (Iterator entryIter = referencingRelations.entrySet()
1337: .iterator(); entryIter.hasNext();) {
1338: Map.Entry entry = (Map.Entry) entryIter.next();
1339: String relationId = (String) entry.getKey();
1340: List roleNames = (List) entry.getValue();
1341: Object relation = null;
1342: try {
1343: relation = this .getRelation(relationId);
1344: } catch (RelationNotFoundException e) {
1345: break;
1346: }
1347: // Flag to specify if the relation has to be deleted
1348: boolean delRelationFlag = false;
1349: for (Iterator roleNameIter = roleNames.iterator(); roleNameIter
1350: .hasNext();) {
1351: if (delRelationFlag)
1352: break;
1353: String roleName = (String) (roleNameIter.next());
1354:
1355: // Shall not throw RelationTypeNotFoundException or
1356: // RoleInfoNotFoundException
1357: RoleInfo currRoleInfo = null;
1358: boolean chkMinFlag = true;
1359: try {
1360: int currRoleRefNbr = (this .getRoleCardinality(
1361: relationId, roleName)).intValue();
1362: int currRoleNewRefNbr = currRoleRefNbr - 1;
1363: String relTypeName = this
1364: .getRelationTypeName(relationId);
1365: currRoleInfo = this .getRoleInfo(relTypeName,
1366: roleName);
1367: chkMinFlag = currRoleInfo
1368: .checkMinDegree(currRoleNewRefNbr);
1369: } catch (Exception e) {
1370: throw new JMRuntimeException(e.getMessage());
1371: }
1372:
1373: if (!chkMinFlag) {
1374: // The relation has to be deleted
1375: delRelationFlag = true;
1376: }
1377: }
1378:
1379: if (delRelationFlag) {
1380: // Removes the relation
1381: try {
1382: removeRelation(relationId);
1383: } catch (RelationNotFoundException e) {
1384: e.printStackTrace();
1385: break;
1386: }
1387:
1388: } else { // do unregister this MBean
1389:
1390: // Updates each role in the relation using
1391: // handleMBeanUnregistration() callback
1392: //
1393: // BEWARE: this theRoleNameList list MUST BE A COPY of a role name
1394: // list for a referenced MBean in a relation, NOT a
1395: // reference to an ORIGINAL one part of the
1396: // myRefedMBeanObjName2RelIdsMap!!!! Because each role
1397: // which name is in that list will be updated (potentially
1398: // using setRole(). So the Relation Service will update the
1399: // myRefedMBeanObjName2RelIdsMap to refelect the new role
1400: // value!
1401: for (Iterator roleNameIter = roleNames.iterator(); roleNameIter
1402: .hasNext();) {
1403:
1404: String currRoleName = (String) (roleNameIter
1405: .next());
1406:
1407: if (relation instanceof RelationSupport) {
1408: // Internal relation
1409: // Can throw RoleNotFoundException (but already checked)
1410: //
1411: // Shall not throw
1412: // RelationTypeNotFoundException,
1413: // InvalidRoleValueException (value was correct, removing
1414: // one reference shall not invalidate it, else detected
1415: // above)
1416: try {
1417: ((RelationSupport) relation)
1418: .handleMBeanUnregistration(
1419: unregMBeanName,
1420: currRoleName);
1421: } catch (Exception e) {
1422: throw new JMRuntimeException(e
1423: .getMessage());
1424: }
1425:
1426: } else {
1427: // Relation MBean
1428: // Shall not throw InstanceNotFoundException, or
1429: // MBeanException (wrapping RoleNotFoundException or
1430: // MBeanException or InvalidRoleValueException) or
1431: // ReflectionException
1432: try {
1433: mbeanServer
1434: .invoke(
1435: ((ObjectName) relation),
1436: "handleMBeanUnregistration",
1437: new Object[] {
1438: unregMBeanName,
1439: currRoleName },
1440: new String[] {
1441: "javax.management.ObjectName",
1442: "java.lang.String" });
1443: } catch (MBeanException e) {
1444: Exception target = e
1445: .getTargetException();
1446: throw new JMRuntimeException(target
1447: .getMessage());
1448: } catch (Exception e) {
1449: throw new JMRuntimeException(e
1450: .getMessage());
1451: }
1452:
1453: }
1454: }
1455: }
1456: }
1457: }
1458: }
1459:
1460: public void removeRelation(String relationId)
1461: throws RelationServiceNotRegisteredException,
1462: IllegalArgumentException, RelationNotFoundException {
1463:
1464: // Can throw RelationServiceNotRegisteredException
1465: isActive();
1466:
1467: if (relationId == null) {
1468: throw new IllegalArgumentException(
1469: "Invalid parameter: relationId can not be null.");
1470: }
1471: // Checks there is a relation with this id
1472: // Can throw RelationNotFoundException
1473: Object relation = getRelation(relationId);
1474: if (relation instanceof ObjectName) {
1475: // Removes it from listener filter
1476: unregNotifationFilter
1477: .disableObjectName((ObjectName) relation);
1478: }
1479: sendRelationRemovalNotification(relationId, null);
1480: String relTypeName = this .getRelationTypeName(relationId);
1481: RelationTypeRepository rtrepo = (RelationTypeRepository) relationTypeMap
1482: .get(relTypeName);
1483: rtrepo.removeRelationId(relationId);
1484: relationMap.remove(relationId);
1485: }
1486:
1487: public void sendRelationCreationNotification(String relationId)
1488: throws IllegalArgumentException, RelationNotFoundException {
1489:
1490: if (relationId == null) {
1491: throw new IllegalArgumentException(
1492: "Invalid parameter: relationId can not be null.");
1493: }
1494:
1495: String relTypeName = this .getRelationTypeName(relationId);
1496:
1497: String msg = "Creation of relation " + relationId;
1498:
1499: ObjectName objName = isRelationMBean(relationId);
1500: String notifType = null;
1501: if (objName != null) {
1502: notifType = RelationNotification.RELATION_MBEAN_CREATION;
1503: } else {
1504: notifType = RelationNotification.RELATION_BASIC_CREATION;
1505: }
1506:
1507: RelationNotification notif = new RelationNotification(
1508: notifType, this , notifSequence++, System
1509: .currentTimeMillis(), msg, relationId,
1510: relTypeName, objName, null);
1511:
1512: this .sendNotification(notif);
1513: }
1514:
1515: public void sendRelationRemovalNotification(String relationId,
1516: List unregMBeanList) throws IllegalArgumentException,
1517: RelationNotFoundException {
1518:
1519: if (relationId == null) {
1520: throw new IllegalArgumentException(
1521: "Invalid parameter: relationId can not be null.");
1522: }
1523: String relTypeName = this .getRelationTypeName(relationId);
1524: String msg = "Removal of relation " + relationId;
1525:
1526: ObjectName objName = isRelationMBean(relationId);
1527: String notifType = null;
1528: if (objName != null) {
1529: notifType = RelationNotification.RELATION_MBEAN_REMOVAL;
1530: } else {
1531: notifType = RelationNotification.RELATION_BASIC_REMOVAL;
1532: }
1533:
1534: RelationNotification notif = new RelationNotification(
1535: notifType, this , notifSequence++, System
1536: .currentTimeMillis(), msg, relationId,
1537: relTypeName, objName, unregMBeanList);
1538:
1539: this .sendNotification(notif);
1540: }
1541:
1542: public void sendRoleUpdateNotification(String relationId,
1543: Role newRole, List oldRoleValue)
1544: throws IllegalArgumentException, RelationNotFoundException {
1545:
1546: if (relationId == null || newRole == null
1547: || oldRoleValue == null) {
1548: throw new IllegalArgumentException(
1549: "Invalid parameter: relationId, newRole and oldRoleValue cant not be null.");
1550: }
1551:
1552: String relTypeName = this .getRelationTypeName(relationId);
1553:
1554: String roleName = newRole.getRoleName();
1555: ArrayList newRoleVal = (ArrayList) (newRole.getRoleValue());
1556:
1557: // Message
1558: String newRoleValString = Role.roleValueToString(newRoleVal);
1559: String oldRoleValString = Role.roleValueToString(oldRoleValue);
1560: // Revisit [cebro] Localize message
1561: String notifMsg = "Value of role " + roleName
1562: + " has changed\nOld value:\n" + oldRoleValString
1563: + "\nNew value:\n" + newRoleValString;
1564:
1565: ObjectName objName = isRelationMBean(relationId);
1566: String notifType = null;
1567: if (objName != null) {
1568: notifType = RelationNotification.RELATION_MBEAN_UPDATE;
1569: } else {
1570: notifType = RelationNotification.RELATION_BASIC_UPDATE;
1571: }
1572:
1573: RelationNotification notif = new RelationNotification(
1574: notifType, this , notifSequence++, System
1575: .currentTimeMillis(), notifMsg, relationId,
1576: relTypeName, objName, roleName, newRoleVal,
1577: oldRoleValue);
1578:
1579: this .sendNotification(notif);
1580: }
1581:
1582: public MBeanNotificationInfo[] getNotificationInfo() {
1583: String[] types = {
1584: RelationNotification.RELATION_BASIC_CREATION,
1585: RelationNotification.RELATION_BASIC_REMOVAL,
1586: RelationNotification.RELATION_BASIC_UPDATE,
1587: RelationNotification.RELATION_MBEAN_CREATION,
1588: RelationNotification.RELATION_MBEAN_REMOVAL,
1589: RelationNotification.RELATION_MBEAN_UPDATE };
1590: MBeanNotificationInfo[] notifsInfo = { new MBeanNotificationInfo(
1591: types, "javax.management.monitor.RelationNotification",
1592: "Notifications sent by the RelationService MBean") };
1593: return notifsInfo;
1594: }
1595:
1596: // if name is null, construct it
1597: public ObjectName preRegister(MBeanServer server, ObjectName name)
1598: throws Exception {
1599: mbeanServer = server;
1600: if (name == null)
1601: name = new ObjectName(server.getDefaultDomain()
1602: + ":service=" + this .toString());
1603: relServObjectName = name;
1604: return name;
1605: }
1606:
1607: // Post-registration: add the notification listener
1608: public void postRegister(Boolean registrationDone) {
1609: try {
1610: mbeanServer.addNotificationListener(
1611: ExtendedMBeanServerDelegate.getObjectName(), this ,
1612: unregNotifationFilter, null);
1613: // TODO: comment
1614: mbeanServer.addNotificationListener(
1615: ExtendedMBeanServerDelegate.getObjectName(), this ,
1616: unregNotifationFilter, null);
1617: } catch (InstanceNotFoundException e) {
1618: e.printStackTrace();
1619: }
1620: }
1621:
1622: // Pre-unregistration: does nothing
1623: public void preDeregister() throws Exception {
1624:
1625: }
1626:
1627: // Post-unregistration: does nothing
1628: public void postDeregister() {
1629:
1630: }
1631:
1632: // test if DEFAULT_OBJECTNAME is in some relation
1633: private boolean isInRelation(ObjectName objectName) {
1634: for (Iterator relIdIter = relationMap.keySet().iterator(); relIdIter
1635: .hasNext();) {
1636: String relationId = (String) relIdIter.next();
1637: try {
1638: RoleResult roleResult = this .getAllRoles(relationId);
1639: RoleList roleList = roleResult.getRoles();
1640: for (int i = 0; i < roleList.size(); i++) {
1641: Role role = (Role) roleList.get(i);
1642: List roleValue = role.getRoleValue();
1643: for (int j = 0; j < roleValue.size(); j++) {
1644: if (objectName.equals(roleValue.get(j)))
1645: return true;
1646: }
1647: }
1648: } catch (RelationServiceNotRegisteredException e) {
1649: e.printStackTrace();
1650: } catch (RelationNotFoundException e) {
1651: e.printStackTrace();
1652: }
1653: }
1654: return false;
1655: }
1656:
1657: // Retrieves relation corresponding to given relation id.
1658: // Returns either:
1659: // - a RelationSupport object if the relation is internal
1660: // or
1661: // - the ObjectName of the corresponding MBean
1662:
1663: private Object getRelation(String relationId)
1664: throws IllegalArgumentException, RelationNotFoundException {
1665:
1666: if (relationId == null) {
1667: throw new IllegalArgumentException(
1668: "Invalid parameter: relationId can not be null.");
1669: }
1670:
1671: if (!relationMap.containsKey(relationId)) {
1672: throw new RelationNotFoundException(relationId);
1673: }
1674:
1675: return relationMap.get(relationId);
1676: }
1677:
1678: // InternalRelation doCreate by RelationService, will use the RelationService object directly invoke someting method
1679: private class InternalRelationSupport extends RelationSupport {
1680:
1681: InternalRelationSupport(String relationId,
1682: String relationTypeName, RoleList roleList)
1683: throws InvalidRoleValueException,
1684: IllegalArgumentException {
1685: super (relationId, relServObjectName, mbeanServer,
1686: relationTypeName, roleList);
1687: }
1688:
1689: // get a role, success,return Role; failed,return RoleUnresolved
1690: // override the method, not use mbeanserver.invoke, use relation service object directly
1691: protected Object _getRole(String roleName)
1692: throws IllegalArgumentException,
1693: RelationServiceNotRegisteredException {
1694: if (roleName == null) {
1695: throw new IllegalArgumentException(
1696: "Invalid parameter: roleName can not be null.");
1697: }
1698:
1699: Role role = (Role) roleMap.get(roleName);
1700: if (role == null) { // role not exist
1701: return new RoleUnresolved(roleName, null,
1702: RoleStatus.NO_ROLE_WITH_NAME);
1703: }
1704:
1705: if (mbeanServer == null) {
1706: throw new JMRuntimeException(
1707: "the RelationSupport object doesn't reference a MBeanServer object.");
1708: }
1709:
1710: Integer status;
1711: try {
1712: status = RelationService.this .checkRoleReading(
1713: roleName, relationTypeName);
1714: } catch (RelationTypeNotFoundException e) {
1715: throw new JMRuntimeException(e.getMessage());
1716: }
1717: if (status.intValue() == 0) {
1718: return (Role) (role.clone());
1719: } else { // status may be RoleStatus.ROLE_NOT_READABLE,RoleStatus.ROLE_NOT_WRITABLE
1720: return new RoleUnresolved(roleName, null, status
1721: .intValue());
1722: }
1723: }
1724:
1725: // set role to the roleMap, success return itself, failed return RoleUnresolved
1726: // override the method, not use mbeanserver.invoke, use relation service object directly
1727: protected Object _setRole(Role role)
1728: throws IllegalArgumentException,
1729: RelationServiceNotRegisteredException,
1730: RelationTypeNotFoundException,
1731: RelationNotFoundException {
1732: if (role == null) {
1733: throw new IllegalArgumentException(
1734: "Invalid parameter: role can not be null.");
1735: }
1736: if (mbeanServer == null) {
1737: throw new JMRuntimeException(
1738: "the RelationSupport object doesn't reference a MBeanServer object.");
1739: }
1740:
1741: Object result = null;
1742:
1743: String roleName = role.getRoleName();
1744: List oldValue = new ArrayList();
1745: Boolean initFlag = new Boolean(true);
1746: Role oldRole = (Role) roleMap.get(roleName);
1747: if (oldRole != null) {
1748: initFlag = new Boolean(false);
1749: oldValue = oldRole.getRoleValue();
1750: }
1751:
1752: Integer status = RelationService.this .checkRoleWriting(
1753: role, relationTypeName, initFlag);
1754: if (status.intValue() == 0) { // success,return Role
1755: synchronized (roleMap) {
1756: roleMap.put(roleName, role);
1757: }
1758: if (!initFlag.booleanValue()) { // it's update operation, not init, so must sendNotification & updateRoleMap
1759: // sendRoleUpdataNotification through RelationService
1760: RelationService.this .sendRoleUpdateNotification(id,
1761: role, oldValue);
1762: // updateRoleMap of the RelationService
1763: RelationService.this .updateRoleMap(id, role,
1764: oldValue);
1765: }
1766:
1767: result = role.clone();
1768: } else {
1769: result = new RoleUnresolved(roleName, role
1770: .getRoleValue(), status.intValue());
1771: }
1772:
1773: return result;
1774: }
1775: }
1776:
1777: }
1778:
1779: // repository contain the RelationType object & it's relation object map (id = > RelationSupport/ ObjectName)
1780: class RelationTypeRepository {
1781: private RelationType relationType = null;
1782: // the relationIds string the RelationType contains
1783: private Set relationIds = new HashSet();
1784:
1785: RelationTypeRepository(RelationType relationType) {
1786: if (relationType == null) {
1787: throw new IllegalArgumentException(
1788: "Invalid parameter: relationType can not be null.");
1789: }
1790: this .relationType = relationType;
1791: }
1792:
1793: boolean addRelationId(String relationId) {
1794: return relationIds.add(relationId);
1795: }
1796:
1797: void removeRelationId(String relationId) {
1798: relationIds.remove(relationId);
1799: }
1800:
1801: RelationType getRelationType() {
1802: return relationType;
1803: }
1804:
1805: List getAllRelationIds() {
1806: return new ArrayList(relationIds);
1807: }
1808:
1809: }
|