Source Code Cross Referenced for RelationService.java in  » JMX » mx4j » javax » management » relation » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » JMX » mx4j » javax.management.relation 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /**
0002:         * Copyright (C) The MX4J Contributors.
0003:         * All rights reserved.
0004:         *
0005:         * This software is distributed under the terms of the MX4J License version 1.0.
0006:         * See the terms of the MX4J License in the documentation provided with this software.
0007:         */package javax.management.relation;
0008:
0009:        import java.util.ArrayList;
0010:        import java.util.Date;
0011:        import java.util.HashMap;
0012:        import java.util.Iterator;
0013:        import java.util.List;
0014:        import java.util.Map;
0015:        import java.util.Set;
0016:        import javax.management.InstanceNotFoundException;
0017:        import javax.management.MBeanNotificationInfo;
0018:        import javax.management.MBeanRegistration;
0019:        import javax.management.MBeanServer;
0020:        import javax.management.MBeanServerInvocationHandler;
0021:        import javax.management.MBeanServerNotification;
0022:        import javax.management.MalformedObjectNameException;
0023:        import javax.management.Notification;
0024:        import javax.management.NotificationBroadcasterSupport;
0025:        import javax.management.NotificationListener;
0026:        import javax.management.ObjectName;
0027:        import javax.management.RuntimeOperationsException;
0028:
0029:        import mx4j.log.Log;
0030:        import mx4j.log.Logger;
0031:
0032:        /**
0033:         * @version $Revision: 1.35 $
0034:         */
0035:
0036:        /**
0037:         * An MBean that maintains the consistency of all relation types and all relation instances within a JMX agent.
0038:         * It provides query operations to fins related and associated mbeans and their roles in the relation.
0039:         */
0040:        public class RelationService extends NotificationBroadcasterSupport
0041:                implements  RelationServiceMBean, MBeanRegistration,
0042:                NotificationListener {
0043:            private boolean m_purgeFlag;
0044:            private Long m_notificationCounter = new Long(0);
0045:
0046:            private MBeanServer m_server = null;
0047:            private RelationSupportMBean m_proxy = null;
0048:            private ObjectName m_relationServiceObjectName = null;
0049:
0050:            private MBeanServerNotificationFilter m_notificationFilter = null;
0051:
0052:            private Map m_relationIdToRelationObject = new HashMap();
0053:            private Map m_relationIdToRelationTypeName = new HashMap();
0054:            private Map m_relationMBeanObjectNameToRelationId = new HashMap();
0055:            private Map m_relationTypeNameToRelationTypeObject = new HashMap();
0056:            private Map m_relationTypeNameToRelationIds = new HashMap();
0057:            private Map m_referencedMBeanObjectNameToRelationIds = new HashMap();
0058:
0059:            private List m_deregisteredNotificationList = new ArrayList();
0060:
0061:            /**
0062:             * constructor
0063:             *
0064:             * @param purgeFlag - this is a flag, if true indicates an immediate update of relations is to be done when a
0065:             *                  notification is recieved for the unregistration of an MBean referenced in a relation
0066:             *                  - if false update of relations must be performed explicitly by calling purgeRelations()
0067:             * @see #purgeRelations
0068:             */
0069:            public RelationService(boolean purgeFlag) {
0070:                m_purgeFlag = purgeFlag;
0071:            }
0072:
0073:            /**
0074:             * @throws RelationServiceNotRegisteredException
0075:             *          - thrown if the RelationService is not registered in the MBeanServer
0076:             *          <p>Currently this class must be registered in the MBeanServer before any relations can be created or added</p>
0077:             */
0078:            public void isActive() throws RelationServiceNotRegisteredException {
0079:                Logger logger = getLogger();
0080:                if (m_server == null) {
0081:                    logger
0082:                            .error("RelationService has not been registered in the MBeanServer");
0083:                    throw new RelationServiceNotRegisteredException(
0084:                            "Relation Service is not registered");
0085:                }
0086:            }
0087:
0088:            /**
0089:             * @return true - if the purgeFlag has been set, false if updates of a relation must be called explicitly
0090:             * @see #purgeRelations
0091:             */
0092:            public boolean getPurgeFlag() {
0093:                return m_purgeFlag;
0094:            }
0095:
0096:            /**
0097:             * @param purgeFlag - a flag that when set to true indicates to the <code>RelationService</code> that it must update all relations
0098:             *                  when it recieves a unregistration notification
0099:             *                  if false this will not occur and purgeRelations must be called explicitly
0100:             */
0101:            public void setPurgeFlag(boolean purgeFlag) {
0102:                m_purgeFlag = purgeFlag;
0103:            }
0104:
0105:            /**
0106:             * @param relationTypeName - a string giving relations a type name this must be a unique name
0107:             * @param roleInfos        - an array of RoleInfo objects.
0108:             *                         Which are used to define the roles a relation plays a part in. It defines attributes
0109:             *                         such as cardinality, role reading and writing...
0110:             *                         The RelationService will then use these RoleInfo to maintain the relation
0111:             * @throws IllegalArgumentException     - thrown if any of the parameters are null
0112:             * @throws InvalidRelationTypeException - thrown if the role name, contained in the RoleInfo, already exists.
0113:             *                                      <p/>
0114:             *                                      <p>This method creates a relationType (a RelationTypeSupport Object) from the parameters passed in.</p>
0115:             *                                      <p>The RelationTypeSupport represents an internal relation</p>
0116:             */
0117:            public void createRelationType(String relationTypeName,
0118:                    RoleInfo[] roleInfos) throws IllegalArgumentException,
0119:                    InvalidRelationTypeException {
0120:                if (relationTypeName == null)
0121:                    throw new IllegalArgumentException(
0122:                            "Illegal Null Relation Type Name value");
0123:                if (roleInfos == null)
0124:                    throw new IllegalArgumentException("Illegal Null RoleInfo");
0125:
0126:                Logger logger = getLogger();
0127:                if (logger.isEnabledFor(Logger.DEBUG))
0128:                    logger
0129:                            .debug("Creating Relation Type with relationTypeName: "
0130:                                    + relationTypeName);
0131:
0132:                RelationTypeSupport relationType = new RelationTypeSupport(
0133:                        relationTypeName, roleInfos);
0134:                // created a new RelationType add it to our map
0135:                addRelationTypeToMap(relationTypeName, relationType);
0136:            }
0137:
0138:            /* Adds a relationTypeName as the key to a Map and the RelationType as the value */
0139:            private void addRelationTypeToMap(String relationTypeName,
0140:                    RelationType relationType)
0141:                    throws InvalidRelationTypeException {
0142:                Logger logger = getLogger();
0143:                // synchronize all activities to map.
0144:                synchronized (m_relationTypeNameToRelationTypeObject) {
0145:                    if ((m_relationTypeNameToRelationTypeObject
0146:                            .get(relationTypeName)) != null) {
0147:                        logger
0148:                                .warn("Cannot addRelationType as a relationType of the same name: "
0149:                                        + relationTypeName
0150:                                        + " already exists in the RelationService");
0151:                        throw new InvalidRelationTypeException(
0152:                                "RelationType with name: "
0153:                                        + relationTypeName
0154:                                        + " already exists in the RelationService");
0155:                    }
0156:                    // set the RelationTypeSupport internal flag to true indicating that the relationType has been declared in the relation service
0157:                    if (relationType instanceof  RelationTypeSupport) {
0158:                        ((RelationTypeSupport) relationType)
0159:                                .setRelationServiceFlag(true);
0160:                    }
0161:                    // store the instance in the map
0162:                    m_relationTypeNameToRelationTypeObject.put(
0163:                            relationTypeName, relationType);
0164:                }
0165:            }
0166:
0167:            /* returns the RelationType stored in the Map given the relationTypeName */
0168:            private RelationType getRelationType(String relationTypeName)
0169:                    throws IllegalArgumentException,
0170:                    RelationTypeNotFoundException {
0171:                RelationType relationType;
0172:                synchronized (m_relationTypeNameToRelationTypeObject) {
0173:                    relationType = ((RelationType) (m_relationTypeNameToRelationTypeObject
0174:                            .get(relationTypeName)));
0175:                    // exception is caught by calling classes testing for RelationTypeNotFound.
0176:                    if (relationType == null) {
0177:                        throw new RelationTypeNotFoundException(
0178:                                "No RelationType found for relationTypeName: "
0179:                                        + relationTypeName);
0180:                    }
0181:                    return relationType;
0182:                }
0183:            }
0184:
0185:            /**
0186:             * @param relationType - an Object implementing the RelationType interface a utility implementation is provided by the
0187:             *                     <code>RelationTypeSupport</code> class
0188:             * @throws IllegalArgumentException     if a null RelationType is passed in as a parameter or if that RelationType has no RoleInfo defined
0189:             * @throws InvalidRelationTypeException if the RoleInfo obtained from the RelationType is
0190:             *                                      - empty
0191:             *                                      - null
0192:             *                                      - the RoleName is already in use
0193:             *                                      <p>This method makes an externally defined relation type available through the relationService</p>
0194:             *                                      <p>The RelationType is immutable, hence the returned values should never change while the relationType is registered
0195:             *                                      with the realtion service</p>
0196:             */
0197:            public void addRelationType(RelationType relationType)
0198:                    throws IllegalArgumentException,
0199:                    InvalidRelationTypeException {
0200:                if (relationType == null)
0201:                    throw new IllegalArgumentException(
0202:                            "Relation Type should not be null.");
0203:
0204:                // check type name
0205:                String relationTypeName = relationType.getRelationTypeName();
0206:                if (relationTypeName == null)
0207:                    throw new IllegalArgumentException(
0208:                            "RelationTypeName must not be null");
0209:
0210:                Logger logger = getLogger();
0211:                if (logger.isEnabledFor(Logger.DEBUG))
0212:                    logger.debug("Adding a RelationType");
0213:
0214:                List roleInfoList = relationType.getRoleInfos();
0215:                if (roleInfoList == null) {
0216:                    logger
0217:                            .warn("Cannot add RelationType: "
0218:                                    + relationType.getClass().getName()
0219:                                    + " RoleInfo information was not provided with the RelationType.");
0220:                    throw new InvalidRelationTypeException(
0221:                            "No RoleInfo provided with Relation Type");
0222:                }
0223:                // build the roleInfo[] to validate the RoleInfo
0224:                RoleInfo[] roleInfos = new RoleInfo[roleInfoList.size()];
0225:                int index = 0;
0226:                for (Iterator i = roleInfoList.iterator(); i.hasNext();) {
0227:                    RoleInfo currentRoleInfo = (RoleInfo) i.next();
0228:                    roleInfos[index] = currentRoleInfo;
0229:                    index++;
0230:                }
0231:                // need to validateRoleInfos before adding
0232:                RelationTypeSupport.checkRoleInfos(roleInfos);
0233:
0234:                // validated add the RelationType
0235:                addRelationTypeToMap(relationTypeName, relationType);
0236:            }
0237:
0238:            /**
0239:             * @return a list containing all the relationTypeNames registered with the relation service
0240:             */
0241:            public List getAllRelationTypeNames() {
0242:                List result;
0243:                synchronized (m_relationTypeNameToRelationTypeObject) {
0244:                    result = new ArrayList(
0245:                            m_relationTypeNameToRelationTypeObject.keySet());
0246:                }
0247:                // return all relationTypeNames or an empty list if none
0248:                return result;
0249:            }
0250:
0251:            /**
0252:             * @param relationTypeName - the string name representation of this RelationType
0253:             * @return - List containing the RoleInfos for this RelationType Object
0254:             * @throws IllegalArgumentException      - if the relationTypeName is null
0255:             * @throws RelationTypeNotFoundException - if the Relationtype for the given relationTypeName is not found
0256:             */
0257:            public List getRoleInfos(String relationTypeName)
0258:                    throws IllegalArgumentException,
0259:                    RelationTypeNotFoundException {
0260:                if (relationTypeName == null)
0261:                    throw new IllegalArgumentException(
0262:                            "Illegal relationType name is null.");
0263:                RelationType relationType = getRelationType(relationTypeName);
0264:                // returns a List of RoleInfo objects
0265:                return relationType.getRoleInfos();
0266:            }
0267:
0268:            /**
0269:             * @param relationTypeName - string name representing the RelationType
0270:             * @param roleInfoName     - string name representing the RoleInfo object
0271:             * @return - the corresponding RoleInfo Object for the given parameters
0272:             * @throws IllegalArgumentException      - if either the relationtypeName or the roleInfoName is null
0273:             * @throws RelationTypeNotFoundException - if the RelationType is not in the realtion service
0274:             * @throws RoleInfoNotFoundException     - if the RoleInfo has not been found
0275:             */
0276:            public RoleInfo getRoleInfo(String relationTypeName,
0277:                    String roleInfoName) throws IllegalArgumentException,
0278:                    RelationTypeNotFoundException, RoleInfoNotFoundException {
0279:                if (relationTypeName == null)
0280:                    throw new IllegalArgumentException(
0281:                            "Null relation type name");
0282:                if (roleInfoName == null)
0283:                    throw new IllegalArgumentException("Null RoleInfo name");
0284:                // gets the RelationType then gets the RoleInfo object
0285:                return (getRelationType(relationTypeName)
0286:                        .getRoleInfo(roleInfoName));
0287:            }
0288:
0289:            /**
0290:             * @param relationTypeName - a string name representing the Relationtype Object
0291:             * @throws IllegalArgumentException      - if the relationTypeName is null
0292:             * @throws RelationServiceNotRegisteredException
0293:             *                                       - if the RelationService has not been registered in the MBeanServer
0294:             * @throws RelationTypeNotFoundException - if the RelationType has not been found
0295:             *                                       <p/>
0296:             *                                       <p>This method removes a RelationType, it's name(represented by the relationTypeName) and any relationIds associated with it,
0297:             *                                       and all MBeans referenced in it's roles</p>
0298:             *                                       <p>Note: this will not remove any mbeans registered with the MBeanServer this must be done if required via the MBeanServer.
0299:             *                                       Any Mbeans registered with the MBean server will continue to be accessed via the MBeanServer, they will no longer be able to be
0300:             *                                       referenced, queried via the relation service though.</p>
0301:             */
0302:            public void removeRelationType(String relationTypeName)
0303:                    throws IllegalArgumentException,
0304:                    RelationServiceNotRegisteredException,
0305:                    RelationTypeNotFoundException {
0306:                Logger logger = getLogger();
0307:                isActive();
0308:                if (relationTypeName == null)
0309:                    throw new IllegalArgumentException(
0310:                            "Illegal: relationType name cannot be null.");
0311:                if (logger.isEnabledFor(Logger.DEBUG))
0312:                    logger
0313:                            .debug("Removing RelationType with relationTypeName: "
0314:                                    + relationTypeName);
0315:
0316:                // will throw RelationTypeNotFoundException if not found
0317:                getRelationType(relationTypeName);
0318:
0319:                // no need to clone as relationIdList is internal and get its values from a private method.
0320:                List relationIdList = getRelationIds(relationTypeName);
0321:
0322:                removeRelationTypeObject(relationTypeName);
0323:                removeRelationTypeName(relationTypeName);
0324:
0325:                if (relationIdList != null) {
0326:                    for (Iterator i = relationIdList.iterator(); i.hasNext();) {
0327:                        String currentRelationId = (String) i.next();
0328:                        try {
0329:                            // removed the relationType now remove the relation
0330:                            removeRelation(currentRelationId);
0331:                        } catch (RelationNotFoundException ex) {
0332:                            throw new RuntimeOperationsException(null, ex
0333:                                    .toString());
0334:                        }
0335:                    }
0336:                }
0337:            }
0338:
0339:            private void removeRelationTypeObject(String relationTypeName) {
0340:                synchronized (m_relationTypeNameToRelationTypeObject) {
0341:                    m_relationTypeNameToRelationTypeObject
0342:                            .remove(relationTypeName);
0343:                }
0344:            }
0345:
0346:            private List getRelationIds(String relationTypeName) {
0347:                synchronized (m_relationTypeNameToRelationIds) {
0348:                    return ((List) (m_relationTypeNameToRelationIds
0349:                            .get(relationTypeName)));
0350:                }
0351:            }
0352:
0353:            /**
0354:             * @param relationId       - the id through which this relation is referenced
0355:             * @param relationTypeName - a unique name for the RelationType
0356:             * @param roleList         - a list of roles to be associated with this relation
0357:             * @throws IllegalArgumentException      - if the relationId, or relationTypeName is null
0358:             * @throws RelationServiceNotRegisteredException
0359:             *                                       - if the relationService has not been registered in the MBeanServer
0360:             * @throws RoleNotFoundException         - if a role defined in the RoleList is null or empty
0361:             * @throws InvalidRelationIdException    - if the relationId is already in use.
0362:             * @throws RelationTypeNotFoundException - if the relationType is not found
0363:             * @throws InvalidRoleValueException     - if cardinality is not correct i.e min cardinality is greater than max cardinality
0364:             *                                       <p/>
0365:             *                                       <p>According to the RI spec this method is used only to create internal relations - hence creates an InternalRelation</p>
0366:             *                                       <p>This creates a relation represented by a RelationSupport Object, and a RelationNotification,
0367:             *                                       with type RELATION_BASIC_CREATION, is sent</p>
0368:             */
0369:            public void createRelation(String relationId,
0370:                    String relationTypeName, RoleList roleList)
0371:                    throws IllegalArgumentException,
0372:                    RelationServiceNotRegisteredException,
0373:                    RoleNotFoundException, InvalidRelationIdException,
0374:                    RelationTypeNotFoundException, InvalidRoleValueException {
0375:                isActive();
0376:                if (relationId == null)
0377:                    throw new IllegalArgumentException("Null Relation Id");
0378:                if (relationTypeName == null)
0379:                    throw new IllegalArgumentException(
0380:                            "Null Relation Type Name");
0381:                Logger logger = getLogger();
0382:                if (logger.isEnabledFor(Logger.DEBUG)) {
0383:                    logger.debug("Creating an InternalRelation with ID: "
0384:                            + relationId + " and relationType name: "
0385:                            + relationTypeName);
0386:                }
0387:                // creating InternalRelation to represent the internal relations
0388:                InternalRelation internalRelation = new InternalRelation(
0389:                        relationId, m_relationServiceObjectName,
0390:                        relationTypeName, roleList);
0391:                try {
0392:                    if (getRelationObject(relationId) != null) {
0393:                        logger
0394:                                .warn("There is a Relation already registered in the RelationServcie with ID: "
0395:                                        + relationId);
0396:                        throw new InvalidRelationIdException(
0397:                                "There is already a relation with id: "
0398:                                        + relationId);
0399:                    }
0400:                } catch (RelationNotFoundException ex) {/*Do nothing as should not be found*/
0401:                }
0402:
0403:                RelationType relationType = getRelationType(relationTypeName);
0404:                ArrayList roleInfoList = (ArrayList) (buildRoleInfoList(
0405:                        relationType, roleList));
0406:                if (!(roleInfoList.isEmpty())) {
0407:                    initializeMissingCreateRoles(roleInfoList,
0408:                            internalRelation, relationId, relationTypeName);
0409:                }
0410:
0411:                synchronized (m_relationIdToRelationObject) {
0412:                    m_relationIdToRelationObject.put(relationId,
0413:                            internalRelation);
0414:                }
0415:                addRelationId(relationId, relationTypeName);
0416:                addRelationTypeName(relationId, relationTypeName);
0417:                updateRoles(roleList, relationId);
0418:                try {
0419:                    if (logger.isEnabledFor(Logger.DEBUG))
0420:                        logger
0421:                                .debug("sending RelationCreation notification to all listeners");
0422:                    sendRelationCreationNotification(relationId);
0423:                } catch (RelationNotFoundException ex) {
0424:                    throw new RuntimeOperationsException(null,
0425:                            "Unable to send notification as Relation not found");
0426:                }
0427:            }
0428:
0429:            /* updates roles given the roleList and the relationId */
0430:            private void updateRoles(RoleList roleList, String relationId)
0431:                    throws RelationServiceNotRegisteredException,
0432:                    IllegalArgumentException {
0433:                if (roleList == null)
0434:                    throw new IllegalArgumentException("Null RoleList");
0435:                if (relationId == null)
0436:                    throw new IllegalArgumentException("Null relationId");
0437:                for (Iterator i = roleList.iterator(); i.hasNext();) {
0438:                    Role currentRole = (Role) i.next();
0439:                    ArrayList tempList = new ArrayList();
0440:                    try {
0441:                        updateRoleMap(relationId, currentRole, tempList);
0442:                    } catch (RelationNotFoundException ex) {
0443:                        throw new RuntimeOperationsException(null,
0444:                                "Cannot update the roleMap as Relation not found");
0445:                    }
0446:                }
0447:            }
0448:
0449:            private List buildRoleInfoList(RelationType relationType,
0450:                    List roleList) throws InvalidRoleValueException,
0451:                    RoleNotFoundException {
0452:                List roleInfoList = relationType.getRoleInfos();
0453:                if (roleList != null) {
0454:                    for (Iterator i = roleList.iterator(); i.hasNext();) {
0455:                        Role currentRole = (Role) i.next();
0456:                        String currentRoleName = currentRole.getRoleName();
0457:                        List currentRoleValue = currentRole.getRoleValue();
0458:                        RoleInfo roleInfo;
0459:                        try {
0460:                            roleInfo = relationType
0461:                                    .getRoleInfo(currentRoleName);
0462:                        } catch (RoleInfoNotFoundException ex) {
0463:                            throw new RoleNotFoundException(ex.getMessage());
0464:                        }
0465:                        int problemType = (checkRoleCardinality(
0466:                                currentRoleName, currentRoleValue, roleInfo))
0467:                                .intValue();
0468:                        if (problemType != 0) {
0469:                            throwRoleProblemException(problemType,
0470:                                    currentRoleName);
0471:                        }
0472:                        roleInfoList.remove(roleInfoList.indexOf(roleInfo));
0473:                    }
0474:                }
0475:                return roleInfoList;
0476:            }
0477:
0478:            private void addRelationTypeName(String relationId,
0479:                    String relationTypeName) {
0480:                synchronized (m_relationTypeNameToRelationIds) {
0481:                    ArrayList idList = (ArrayList) m_relationTypeNameToRelationIds
0482:                            .get(relationTypeName);
0483:                    boolean isNewRelation = false;
0484:                    if (idList == null) {
0485:                        isNewRelation = true;
0486:                        idList = new ArrayList();
0487:                    }
0488:                    idList.add(relationId);
0489:                    if (isNewRelation)
0490:                        m_relationTypeNameToRelationIds.put(relationTypeName,
0491:                                idList);
0492:                }
0493:            }
0494:
0495:            private void addRelationObjectName(String relationId,
0496:                    ObjectName relationObjectName) {
0497:                synchronized (m_relationIdToRelationObject) {
0498:                    m_relationIdToRelationObject.put(relationId,
0499:                            relationObjectName);
0500:                }
0501:            }
0502:
0503:            private void addRelationId(String relationId,
0504:                    String relationTypeName) {
0505:                synchronized (m_relationIdToRelationTypeName) {
0506:                    m_relationIdToRelationTypeName.put(relationId,
0507:                            relationTypeName);
0508:                }
0509:            }
0510:
0511:            // method gets called only for internal relations
0512:            private void initializeMissingCreateRoles(List roleInfoList,
0513:                    InternalRelation internalRelation, String relationId,
0514:                    String relationTypeName)
0515:                    throws RelationTypeNotFoundException,
0516:                    RelationServiceNotRegisteredException,
0517:                    InvalidRoleValueException, RoleNotFoundException,
0518:                    IllegalArgumentException {
0519:                isActive();
0520:                if (roleInfoList == null)
0521:                    throw new IllegalArgumentException("RoleInfoList is Null");
0522:                if (relationId == null)
0523:                    throw new IllegalArgumentException("RelationId is Null.");
0524:                if (relationTypeName == null)
0525:                    throw new IllegalArgumentException(
0526:                            "Relation Type Name is Null.");
0527:
0528:                for (Iterator i = roleInfoList.iterator(); i.hasNext();) {
0529:                    RoleInfo currentRoleInfo = (RoleInfo) i.next();
0530:                    String roleName = currentRoleInfo.getName();
0531:
0532:                    ArrayList temp = new ArrayList();
0533:                    Role role = new Role(roleName, temp);
0534:                    try {
0535:                        internalRelation.setRole(role);
0536:                    } catch (RelationNotFoundException ex) {
0537:                        throw new RuntimeOperationsException(null, ex
0538:                                .getMessage());
0539:                    }
0540:                }
0541:            }
0542:
0543:            private Integer checkRoleCardinality(String roleName,
0544:                    List roleValue, RoleInfo roleInfo) {
0545:                if (roleName == null)
0546:                    throw new IllegalArgumentException("Null Role Name");
0547:                if (roleValue == null)
0548:                    throw new IllegalArgumentException("Null roleValue List");
0549:                if (roleInfo == null)
0550:                    throw new IllegalArgumentException("Null RoleInfo");
0551:                Logger logger = getLogger();
0552:                if (logger.isEnabledFor(Logger.DEBUG))
0553:                    logger.debug("checking role cardinality");
0554:
0555:                if (!(roleName.equals(roleInfo.getName()))) {
0556:                    logger.warn("Role does not have a valid roleName");
0557:                    return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
0558:                }
0559:                if (!(roleInfo.checkMinDegree(roleValue.size()))) {
0560:                    logger
0561:                            .warn("Minimum number of references defined in the RoleInfo has fallen below minimum");
0562:                    return (new Integer(RoleStatus.LESS_THAN_MIN_ROLE_DEGREE));
0563:                }
0564:                if (!(roleInfo.checkMaxDegree(roleValue.size()))) {
0565:                    logger
0566:                            .warn("Maximum number of references defined in the RoleInfo has gone above the maximum");
0567:                    return new Integer(RoleStatus.MORE_THAN_MAX_ROLE_DEGREE);
0568:                }
0569:
0570:                String referencedClassName = roleInfo.getRefMBeanClassName();
0571:                for (Iterator i = roleValue.iterator(); i.hasNext();) {
0572:                    ObjectName currentObjectName = (ObjectName) i.next();
0573:                    if (currentObjectName == null) {
0574:                        logger.warn("The mbean with RoleName: " + roleName
0575:                                + " is not registered in the MBeanServer");
0576:                        return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
0577:                    }
0578:                    if (!(m_server.isRegistered(currentObjectName))) {
0579:                        logger.warn("The mbean with ObjectName: "
0580:                                + currentObjectName.getCanonicalName()
0581:                                + " is not registered in the MBeanServer");
0582:                        return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
0583:                    }
0584:                    try {
0585:                        if (!(m_server.isInstanceOf(currentObjectName,
0586:                                referencedClassName))) {
0587:                            logger.warn("The class referenced: "
0588:                                    + currentObjectName.toString()
0589:                                    + " does not match the class expected: "
0590:                                    + referencedClassName + " in RoleInfo: "
0591:                                    + roleInfo.toString());
0592:                            return new Integer(
0593:                                    RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS);
0594:                        }
0595:                    } catch (InstanceNotFoundException ex) {
0596:                        return null;
0597:                    }
0598:                }
0599:                return new Integer(0);
0600:            }
0601:
0602:            /**
0603:             * @param relationMBeanObjectName - ObjectName of the relation MBean to be added
0604:             * @throws IllegalArgumentException      - if parameter is null
0605:             * @throws RelationServiceNotRegisteredException
0606:             *                                       - if the Relation Service is not registered in the MBean Server
0607:             * @throws NoSuchMethodException         - If the MBean does not implement the Relation interface
0608:             * @throws InvalidRelationIdException    - if there is no relation identifier (ID) in the MBean
0609:             *                                       - if relation identifier (ID) is already used in the Relation Service
0610:             * @throws InstanceNotFoundException     - if the MBean for given ObjectName has not been registered
0611:             * @throws InvalidRelationServiceException
0612:             *                                       - if no Relation Service name in MBean
0613:             *                                       - if the Relation Service name in the MBean is not the one of the current Relation Service
0614:             * @throws RelationTypeNotFoundException - if no relation type name in MBean
0615:             *                                       - if the relation type name in MBean does not correspond to a relation type created in the Relation Service
0616:             * @throws RoleNotFoundException         - if a value is provided for a role that does not exist in the relation type
0617:             * @throws InvalidRoleValueException     - if the number of referenced MBeans in a role is less than expected minimum degree
0618:             *                                       - if the number of referenced MBeans in a role exceeds expected maximum degree
0619:             *                                       - if one referenced MBean in the value is not an Object of the MBean class expected for that role
0620:             *                                       - if an MBean provided for a role does not exist
0621:             *                                       <p/>
0622:             *                                       <p>Adds an MBean created by the user (and registered by him in the MBean Server) as a relation in the Relation Service </p>
0623:             *                                       <p>To be added as a relation, the MBean must conform to the following:
0624:             *                                       <ul>
0625:             *                                       <li>implement the Relation interface</li>
0626:             *                                       <li>have for RelationService ObjectName the ObjectName of current Relation Service </li>
0627:             *                                       <li>have a relation id unique and unused in current Relation Service </li>
0628:             *                                       <li>have for relation type a relation type created in the Relation Service </li>
0629:             *                                       <li>have roles conforming to the role info provided in the relation type</li>
0630:             *                                       </ul>
0631:             */
0632:            public void addRelation(ObjectName relationMBeanObjectName)
0633:                    throws IllegalArgumentException,
0634:                    RelationServiceNotRegisteredException,
0635:                    NoSuchMethodException, InvalidRelationIdException,
0636:                    InstanceNotFoundException, InvalidRelationServiceException,
0637:                    RelationTypeNotFoundException, RoleNotFoundException,
0638:                    InvalidRoleValueException {
0639:                isActive();
0640:                Logger logger = getLogger();
0641:                if (logger.isEnabledFor(Logger.DEBUG))
0642:                    logger.debug("adding a Relation with ObjectName: "
0643:                            + relationMBeanObjectName.toString());
0644:                // checks through the MBeanServer that the class is an instance of the Relation interface which
0645:                // RelationSupport implements
0646:                checkValidRelation(relationMBeanObjectName);
0647:                //create the proxy
0648:
0649:                m_proxy = (RelationSupportMBean) MBeanServerInvocationHandler
0650:                        .newProxyInstance(m_server, relationMBeanObjectName,
0651:                                RelationSupportMBean.class, false);
0652:                // get the relationId of the class through the MBeanServer
0653:                String relationId = m_proxy.getRelationId(); //getRelationIdAttribute(relationMBeanObjectName);
0654:                if (relationId == null)
0655:                    throw new InvalidRelationIdException(
0656:                            "No RelationId provided");
0657:                // obtains the objectname of the RelationService defined by the user
0658:
0659:                ObjectName relationServiceObjectName = m_proxy
0660:                        .getRelationServiceName();
0661:                // checks that the RelationService objectName is running in the server
0662:                if (!(checkRelationServiceIsCurrent(relationServiceObjectName))) {
0663:                    throw new InvalidRelationServiceException(
0664:                            "The Relation Service referenced in the MBean is not the current one.");
0665:                }
0666:                // get the relationTypeName through the server for the user defined RelationSupport subclass
0667:                String relationTypeName = m_proxy.getRelationTypeName();
0668:                if (relationTypeName == null)
0669:                    throw new RelationTypeNotFoundException(
0670:                            "RelationType not found");
0671:                // get the roles
0672:                RoleList roleList = m_proxy.retrieveAllRoles();
0673:                try {
0674:                    // already have defined relation registered cannot add another with the same id
0675:                    if (getRelationObject(relationId) != null)
0676:                        throw new InvalidRelationIdException(
0677:                                "Relation with ID " + relationId
0678:                                        + " already exists");
0679:                } catch (RelationNotFoundException ex) {/*Do nothing should not be found*/
0680:                }
0681:
0682:                RelationType relationType = getRelationType(relationTypeName);
0683:                ArrayList roleInfoList = (ArrayList) buildRoleInfoList(
0684:                        relationType, roleList);
0685:                if (!(roleInfoList.isEmpty())) {
0686:                    for (Iterator i = roleInfoList.iterator(); i.hasNext();) {
0687:                        RoleInfo currentRoleInfo = (RoleInfo) i.next();
0688:                        String currentRoleName = currentRoleInfo.getName();
0689:                        ArrayList emptyValueList = new ArrayList();
0690:                        Role role = new Role(currentRoleName, emptyValueList);
0691:                        try {
0692:                            m_proxy.setRole(role);
0693:                        } catch (RelationNotFoundException ex) {
0694:                            throw new RuntimeOperationsException(null, ex
0695:                                    .getMessage());
0696:                        }
0697:                    }
0698:                }
0699:                // add all info to our corresponding maps
0700:                updateAllInternals(relationId, relationMBeanObjectName,
0701:                        relationTypeName, roleList);
0702:            }
0703:
0704:            private void updateAllInternals(String relationId,
0705:                    ObjectName relationMBeanObjectName,
0706:                    String relationTypeName, RoleList roleList)
0707:                    throws RelationServiceNotRegisteredException {
0708:                // adds key -> relationId value -> relationMBeanObjectName to HashMap
0709:                addRelationObjectName(relationId, relationMBeanObjectName);
0710:                addRelationId(relationId, relationTypeName);
0711:                addRelationTypeName(relationId, relationTypeName);
0712:                updateRoles(roleList, relationId);
0713:                try {
0714:                    sendRelationCreationNotification(relationId);
0715:                } catch (RelationNotFoundException ex) {
0716:                    throw new RuntimeOperationsException(null,
0717:                            "Cannot send a notification for relationId "
0718:                                    + relationId + " as relation not found.");
0719:                }
0720:
0721:                synchronized (m_relationMBeanObjectNameToRelationId) {
0722:                    m_relationMBeanObjectNameToRelationId.put(
0723:                            relationMBeanObjectName, relationId);
0724:                }
0725:                m_proxy.setRelationServiceManagementFlag(new Boolean(true));
0726:                List newReferenceList = new ArrayList();
0727:                newReferenceList.add(relationMBeanObjectName);
0728:                updateUnregistrationListener(newReferenceList, null);
0729:            }
0730:
0731:            private boolean checkRelationServiceIsCurrent(
0732:                    ObjectName relationServiceObjectName) {
0733:                if (relationServiceObjectName == null)
0734:                    return false;
0735:                if (!(relationServiceObjectName
0736:                        .equals(m_relationServiceObjectName)))
0737:                    return false;
0738:                return true;
0739:            }
0740:
0741:            private void checkValidRelation(ObjectName relationMBeanObjectName)
0742:                    throws IllegalArgumentException, InstanceNotFoundException,
0743:                    NoSuchMethodException {
0744:                if (relationMBeanObjectName == null)
0745:                    throw new IllegalArgumentException(
0746:                            "Cannot have a null Relation ObjectName");
0747:                Logger logger = getLogger();
0748:                if (!(m_server.isInstanceOf(relationMBeanObjectName,
0749:                        "javax.management.relation.Relation"))) {
0750:                    logger
0751:                            .warn("An MBean which is to be added as a Relation must implement the Relation interface");
0752:                    throw new NoSuchMethodException(
0753:                            "MBean does implement the Relation interface");
0754:                }
0755:            }
0756:
0757:            /**
0758:             * @param relationId - relation id identifying the relation
0759:             * @return - the ObjectName corresponding to the relationId given or null if it is not found
0760:             * @throws IllegalArgumentException  - if a null parameter
0761:             * @throws RelationNotFoundException - if there is no relation associated to that id
0762:             *                                   <p/>
0763:             *                                   <p>If the relation is represented by an MBean (created by the user and added as a relation in the Relation Service),
0764:             *                                   returns the ObjectName of the MBean</p>
0765:             */
0766:            public ObjectName isRelationMBean(String relationId)
0767:                    throws IllegalArgumentException, RelationNotFoundException {
0768:                if (relationId == null)
0769:                    throw new IllegalArgumentException("Null Relation Id.");
0770:                Object result = getRelationObject(relationId);
0771:                if (result instanceof  ObjectName) {
0772:                    return ((ObjectName) result);
0773:                }
0774:                return null;
0775:            }
0776:
0777:            /**
0778:             * <p>Returns the relation id associated to the given ObjectName if the MBean has been added as a relation in the Relation Service</p>
0779:             *
0780:             * @param objectName - the ObjectName of supposed relation
0781:             * @return - the relation id (String) or null (if the ObjectName is not a relation handled by the Relation Service)
0782:             * @throws IllegalArgumentException - if the parameter is null
0783:             */
0784:            public String isRelation(ObjectName objectName)
0785:                    throws IllegalArgumentException {
0786:                if (objectName == null)
0787:                    throw new IllegalArgumentException("Null ObjectName");
0788:                return (getMBeanObjectName(objectName));
0789:            }
0790:
0791:            /**
0792:             * <p>Checks if there is a relation identified in Relation Service with given relation id.</p>
0793:             *
0794:             * @param relationId - the relation id identifying the relation
0795:             * @return boolean: true if there is a relation, false otherwise
0796:             * @throws IllegalArgumentException - if parameter is null
0797:             */
0798:            public Boolean hasRelation(String relationId)
0799:                    throws IllegalArgumentException {
0800:                if (relationId == null)
0801:                    throw new IllegalArgumentException("Null Relation Id");
0802:                Boolean hasRelation = null;
0803:                try {
0804:                    Object result = getRelationObject(relationId);
0805:                    if (result != null)
0806:                        hasRelation = Boolean.TRUE;
0807:                } catch (RelationNotFoundException ex) {
0808:                    hasRelation = Boolean.FALSE;
0809:                }
0810:                return hasRelation;
0811:            }
0812:
0813:            /**
0814:             * <p>Returns all the relation ids for all the relations handled by the Relation Service</p>
0815:             *
0816:             * @return an arrayList containing the relation ids
0817:             */
0818:            public List getAllRelationIds() {
0819:                synchronized (m_relationIdToRelationObject) {
0820:                    return (new ArrayList(m_relationIdToRelationObject.keySet()));
0821:                }
0822:            }
0823:
0824:            /**
0825:             * <p>Checks if given Role can be read in a relation of the given type</p>
0826:             *
0827:             * @param roleName         - name of role to be checked
0828:             * @param relationTypeName - name of the relation type
0829:             * @return - an Integer wrapping an integer corresponding to possible problems represented as constants in RoleUnresolved:
0830:             *         <ul>
0831:             *         <li>0 if role can be read </li>
0832:             *         <li>integer corresponding to RoleStatus.NO_ROLE_WITH_NAME </li>
0833:             *         <li>integer corresponding to RoleStatus.ROLE_NOT_READABLE </li>
0834:             *         </ul>
0835:             * @throws IllegalArgumentException      - if null parameter
0836:             * @throws RelationTypeNotFoundException - if the relation type is not known in the Relation Service
0837:             */
0838:            public Integer checkRoleReading(String roleName,
0839:                    String relationTypeName) throws IllegalArgumentException,
0840:                    RelationTypeNotFoundException {
0841:                if (roleName == null)
0842:                    throw new IllegalArgumentException("Null RoleName");
0843:                if (relationTypeName == null)
0844:                    throw new IllegalArgumentException(
0845:                            "Null RelationType name.");
0846:                Logger logger = getLogger();
0847:                if (logger.isEnabledFor(Logger.DEBUG))
0848:                    logger.debug("checking if Role with RoleName: " + roleName
0849:                            + " is readable");
0850:                RelationType relationType = getRelationType(relationTypeName);
0851:                try {
0852:                    RoleInfo roleInfo = relationType.getRoleInfo(roleName);
0853:                    if (!(roleName.equals(roleInfo.getName())))
0854:                        return (new Integer(RoleStatus.NO_ROLE_WITH_NAME));
0855:                    if (!(roleInfo.isReadable())) {
0856:                        logger.warn("RoleInfo: " + roleInfo.toString()
0857:                                + " cannot be read");
0858:                        return (new Integer(RoleStatus.ROLE_NOT_READABLE));
0859:                    }
0860:                } catch (RoleInfoNotFoundException ex) {
0861:                    logger.warn("roleInfo for roleName: " + roleName
0862:                            + " has not been found.");
0863:                    return (new Integer(RoleStatus.NO_ROLE_WITH_NAME));
0864:                }
0865:                return new Integer(0);
0866:            }
0867:
0868:            /**
0869:             * <p>Checks if given Role can be set in a relation of given type</p>
0870:             *
0871:             * @param role             - role to be checked
0872:             * @param relationTypeName - name of relation type
0873:             * @param isInitialized    - flag to specify that the checking is done for the initialization of a role, write access shall not be verified
0874:             * @return - an Integer wrapping an integer corresponding to possible problems represented as constants in RoleUnresolved:
0875:             *         <ul>
0876:             *         <li>0 if role can be set </li>
0877:             *         <li>integer corresponding to RoleStatus.NO_ROLE_WITH_NAME </li>
0878:             *         <li>integer for RoleStatus.ROLE_NOT_WRITABLE </li>
0879:             *         <li>integer for RoleStatus.LESS_THAN_MIN_ROLE_DEGREE </li>
0880:             *         <li>integer for RoleStatus.MORE_THAN_MAX_ROLE_DEGREE </li>
0881:             *         <li>integer for RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS </li>
0882:             *         <li>integer for RoleStatus.REF_MBEAN_NOT_REGISTERED </li>
0883:             *         </ul>
0884:             * @throws IllegalArgumentException      - if null parameter
0885:             * @throws RelationTypeNotFoundException - if unknown relation type
0886:             */
0887:            public Integer checkRoleWriting(Role role, String relationTypeName,
0888:                    Boolean isInitialized) throws IllegalArgumentException,
0889:                    RelationTypeNotFoundException {
0890:                if (role == null)
0891:                    throw new IllegalArgumentException(
0892:                            "checkRoleWriting was given a null Role");
0893:                if (relationTypeName == null)
0894:                    throw new IllegalArgumentException(
0895:                            "checkRoleWriting was given a null RelationTypeName");
0896:                if (isInitialized == null)
0897:                    throw new IllegalArgumentException(
0898:                            "checkRoleWriting was given a null Boolean");
0899:                Logger logger = getLogger();
0900:                RelationType relationType = getRelationType(relationTypeName);
0901:                String roleName = role.getRoleName();
0902:                if (logger.isEnabledFor(Logger.DEBUG))
0903:                    logger.debug("checking if Role with RoleName: " + roleName
0904:                            + " is readable");
0905:                ArrayList roleValue = (ArrayList) role.getRoleValue();
0906:                boolean canWrite = true;
0907:                if (isInitialized.booleanValue())
0908:                    canWrite = false;
0909:                RoleInfo roleInfo;
0910:                try {
0911:                    roleInfo = relationType.getRoleInfo(roleName);
0912:                } catch (RoleInfoNotFoundException ex) {
0913:                    logger.warn("roleInfo for roleName: " + roleName
0914:                            + " has not been found.");
0915:                    return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
0916:                }
0917:                if (canWrite) {
0918:                    if (!(roleInfo.isWritable())) {
0919:                        logger.warn("RoleInfo: " + roleInfo.toString()
0920:                                + " cannot be written to.");
0921:                        return new Integer(RoleStatus.ROLE_NOT_WRITABLE);
0922:                    }
0923:                }
0924:                return (checkRoleCardinality(roleName, roleValue, roleInfo));
0925:            }
0926:
0927:            /**
0928:             * <p>Sends a notification (RelationNotification) for a relation creation. The notification type is:
0929:             * <ul>
0930:             * <li>RelationNotification.RELATION_BASIC_CREATION if the relation is an object internal to the Relation Service </li>
0931:             * <li>RelationNotification.RELATION_MBEAN_CREATION if the relation is a MBean added as a relation</li>
0932:             * </ul>
0933:             * The source object is the Relation Service itself<br/>
0934:             * It is called in Relation Service createRelation() and addRelation() methods
0935:             * </p>
0936:             *
0937:             * @param relationId - relation identifier of the updated relation
0938:             * @throws IllegalArgumentException  - if null parameter
0939:             * @throws RelationNotFoundException - if there is no relation for given relation id
0940:             */
0941:            public void sendRelationCreationNotification(String relationId)
0942:                    throws IllegalArgumentException, RelationNotFoundException {
0943:                if (relationId == null)
0944:                    throw new IllegalArgumentException("Null Relation Id.");
0945:                Logger logger = getLogger();
0946:                String message = "Creation of relation " + relationId;
0947:                String relationTypeName = getRelationTypeNameFromMap(relationId);
0948:
0949:                if (logger.isEnabledFor(Logger.DEBUG))
0950:                    logger.debug("A relation has been created with ID: "
0951:                            + relationId + " and relationTypeName: "
0952:                            + relationTypeName + " ..sending notification");
0953:
0954:                ObjectName relationObjectName = isRelationMBean(relationId);
0955:                String notificationType = getCreationNotificationType(relationObjectName);
0956:                long sequenceNumber = getNotificationSequenceNumber()
0957:                        .longValue();
0958:                Date currentDate = new Date();
0959:                long timestamp = currentDate.getTime();
0960:                RelationNotification relationNotification = new RelationNotification(
0961:                        notificationType, this , sequenceNumber, timestamp,
0962:                        message, relationId, relationTypeName,
0963:                        relationObjectName, null);
0964:                sendNotification(relationNotification);
0965:            }
0966:
0967:            private Long getNotificationSequenceNumber() {
0968:                Long result;
0969:                synchronized (m_notificationCounter) {
0970:                    result = new Long(m_notificationCounter.longValue() + 1);
0971:                    m_notificationCounter = new Long(result.longValue());
0972:                }
0973:                return result;
0974:            }
0975:
0976:            private String getCreationNotificationType(
0977:                    ObjectName relationObjectName) {
0978:                if (relationObjectName != null) {
0979:                    return RelationNotification.RELATION_MBEAN_CREATION;
0980:                }
0981:                return RelationNotification.RELATION_BASIC_CREATION;
0982:            }
0983:
0984:            /**
0985:             * <p>Sends a notification (RelationNotification) for a role update in the given relation. The notification type is:
0986:             * <ul>
0987:             * <li>RelationNotification.RELATION_BASIC_UPDATE if the relation is an object internal to the Relation Service </li>
0988:             * <li>RelationNotification.RELATION_MBEAN_UPDATE if the relation is a MBean added as a relation</li>
0989:             * </ul></p>
0990:             * <p>The source object is the Relation Service itself.</p>
0991:             * <p>This method is called in relation MBean setRole() (for given role) and setRoles() (for each role) methods
0992:             * (implementation provided in RelationSupport class)</p>
0993:             * <p>It is also called in Relation Service setRole() (for given role) and setRoles() (for each role) methods</p>
0994:             *
0995:             * @param relationId    - the relation identifier of the updated relation
0996:             * @param newRole       - new role (name and new value)
0997:             * @param oldRoleValues - old role value (ArrayList of ObjectName objects)
0998:             * @throws IllegalArgumentException  - if null parameter
0999:             * @throws RelationNotFoundException - if there is no relation for given relation id
1000:             */
1001:            public void sendRoleUpdateNotification(String relationId,
1002:                    Role newRole, List oldRoleValues)
1003:                    throws IllegalArgumentException, RelationNotFoundException {
1004:                if (relationId == null)
1005:                    throw new IllegalArgumentException("Null RelationId");
1006:                if (newRole == null)
1007:                    throw new IllegalArgumentException("Null Role");
1008:                if (oldRoleValues == null)
1009:                    throw new IllegalArgumentException(
1010:                            "Null List of role values");
1011:
1012:                Logger logger = getLogger();
1013:                if (logger.isEnabledFor(Logger.DEBUG))
1014:                    logger
1015:                            .debug("Sending a roleUpdateNotification of Relation with ID: "
1016:                                    + relationId);
1017:                String roleName = newRole.getRoleName();
1018:                List newRoleValues = newRole.getRoleValue();
1019:                String newRoleValueMessage = Role
1020:                        .roleValueToString(newRoleValues);
1021:                String oldRoleValueMessage = Role
1022:                        .roleValueToString(oldRoleValues);
1023:                StringBuffer message = new StringBuffer("Value of the role ");
1024:                message.append(roleName);
1025:                message.append(" has changed\nOld value:\n");
1026:                message.append(oldRoleValueMessage);
1027:                message.append("\nNew value:\n");
1028:                message.append(newRoleValueMessage);
1029:                if (logger.isEnabledFor(Logger.DEBUG))
1030:                    logger.debug("Notification message: " + message.toString());
1031:                String relationTypeName = getRelationTypeNameFromMap(relationId);
1032:
1033:                // determine if this is a relation update or a relation mbean update
1034:                ObjectName relationObjectName = isRelationMBean(relationId);
1035:                String notificationType;
1036:                if (relationObjectName != null)
1037:                    notificationType = RelationNotification.RELATION_MBEAN_UPDATE;
1038:                else
1039:                    notificationType = RelationNotification.RELATION_BASIC_UPDATE;
1040:
1041:                long sequenceNumber = getNotificationSequenceNumber()
1042:                        .longValue();
1043:                Date currentDate = new Date();
1044:                long timeStamp = currentDate.getTime();
1045:
1046:                RelationNotification notification = new RelationNotification(
1047:                        notificationType, this , sequenceNumber, timeStamp,
1048:                        message.toString(), relationId, relationTypeName,
1049:                        relationObjectName, roleName, newRoleValues,
1050:                        oldRoleValues);
1051:                sendNotification(notification);
1052:            }
1053:
1054:            /**
1055:             * <p>Sends a notification (RelationNotification) for a relation removal. The notification type is:
1056:             * <ul>
1057:             * <li>RelationNotification.RELATION_BASIC_REMOVAL if the relation is an object internal to the Relation Service </li>
1058:             * <li>RelationNotification.RELATION_MBEAN_REMOVAL if the relation is a MBean added as a relation</li>
1059:             * </ul>
1060:             * The source object is the Relation Service itself</p>
1061:             * <p>It is called in Relation Service removeRelation() method</p>
1062:             *
1063:             * @param relationId            - relation identifier of the updated relation
1064:             * @param unregisteredMBeanList - ArrayList of ObjectNames of MBeans expected to be unregistered due to relation removal (can be null)
1065:             * @throws IllegalArgumentException  - if relationId is null
1066:             * @throws RelationNotFoundException - if there is no relation for given relation id
1067:             */
1068:            public void sendRelationRemovalNotification(String relationId,
1069:                    List unregisteredMBeanList)
1070:                    throws IllegalArgumentException, RelationNotFoundException {
1071:                if (relationId == null)
1072:                    throw new IllegalArgumentException("Null RelationId");
1073:
1074:                Logger logger = getLogger();
1075:                if (logger.isEnabledFor(Logger.DEBUG))
1076:                    logger.debug("sending relationRemovalNotification of ID: "
1077:                            + relationId);
1078:                StringBuffer message = new StringBuffer("Removal of relation ");
1079:                message.append(relationId);
1080:                String relationTypeName = getRelationTypeNameFromMap(relationId);
1081:                ObjectName relationObjectName = isRelationMBean(relationId);
1082:                String notificationType;
1083:                if (relationObjectName != null)
1084:                    notificationType = RelationNotification.RELATION_MBEAN_REMOVAL;
1085:                else
1086:                    notificationType = RelationNotification.RELATION_BASIC_REMOVAL;
1087:                long sequenceNumber = getNotificationSequenceNumber()
1088:                        .longValue();
1089:                Date currentDate = new Date();
1090:                long timeStamp = currentDate.getTime();
1091:                RelationNotification notification = new RelationNotification(
1092:                        notificationType, this , sequenceNumber, timeStamp,
1093:                        message.toString(), relationId, relationTypeName,
1094:                        relationObjectName, unregisteredMBeanList);
1095:
1096:                sendNotification(notification);
1097:            }
1098:
1099:            /**
1100:             * <p>Handles update of the Relation Service role map for the update of given role in given relation</p>
1101:             * <p>It is called in relation MBean setRole() (for given role) and setRoles()(for each role) methods
1102:             * (implementation provided in RelationSupport class).</p>
1103:             * <p>It is also called in Relation Service setRole() (for given role) and setRoles() (for each role) methods.</p>
1104:             * <p>To allow the Relation Service to maintain the consistency (in case of MBean unregistration) and to be able to
1105:             * perform queries, this method must be called when a role is updated. </p>
1106:             *
1107:             * @param relationId    - relation identifier of the updated relation
1108:             * @param role          - new role (name and new value)
1109:             * @param oldRoleValues - old role value (ArrayList of ObjectName objects)
1110:             * @throws IllegalArgumentException  - if null parameter
1111:             * @throws RelationServiceNotRegisteredException
1112:             *                                   - if the Relation Service is not registered in the MBean Server
1113:             * @throws RelationNotFoundException - if no relation for given id
1114:             */
1115:            public void updateRoleMap(String relationId, Role role,
1116:                    List oldRoleValues) throws IllegalArgumentException,
1117:                    RelationServiceNotRegisteredException,
1118:                    RelationNotFoundException {
1119:                isActive();
1120:                if (relationId == null)
1121:                    throw new IllegalArgumentException("Null Relation Id");
1122:                if (role == null)
1123:                    throw new IllegalArgumentException("Null Role");
1124:                if (oldRoleValues == null)
1125:                    throw new IllegalArgumentException("Null Role value list.");
1126:
1127:                Logger logger = getLogger();
1128:                if (logger.isEnabledFor(Logger.DEBUG))
1129:                    logger.debug("Updating the RelationService RoleMap");
1130:
1131:                String roleName = role.getRoleName();
1132:                List newRoleValue = role.getRoleValue();
1133:
1134:                // clone as the list is to be modified later, cast to ArrayList as List does not define clone()
1135:                List oldValues = (ArrayList) (((ArrayList) oldRoleValues)
1136:                        .clone());
1137:
1138:                // List of ObjectNames of new referenced MBeans
1139:                List newReferenceList = new ArrayList();
1140:                for (Iterator i = newRoleValue.iterator(); i.hasNext();) {
1141:                    ObjectName currentObjectName = (ObjectName) i.next();
1142:                    // Check if this ObjectName was already present in oldValueList
1143:                    int currentObjectNamePosition = oldValues
1144:                            .indexOf(currentObjectName);
1145:                    // we have a new Reference
1146:                    if (currentObjectNamePosition == -1) {
1147:                        // returns true if we have a new reference, false if the MBean is already referenced
1148:                        if (addNewMBeanReference(currentObjectName, relationId,
1149:                                roleName)) {
1150:                            // add to new references list
1151:                            newReferenceList.add(currentObjectName);
1152:                        }
1153:                    } else {
1154:                        // MBean referenced in an old value remove
1155:                        oldValues.remove(currentObjectNamePosition);
1156:                    }
1157:                }
1158:                List obsoleteReferenceList = getObsoleteReferenceList(
1159:                        oldValues, relationId, roleName);
1160:                // update listeners as to the new references
1161:                updateUnregistrationListener(newReferenceList,
1162:                        obsoleteReferenceList);
1163:            }
1164:
1165:            private List getObsoleteReferenceList(List oldValues,
1166:                    String relationId, String roleName)
1167:                    throws IllegalArgumentException {
1168:                List obsoleteReferenceList = new ArrayList();
1169:                for (Iterator i = oldValues.iterator(); i.hasNext();) {
1170:                    ObjectName currentObjectName = (ObjectName) i.next();
1171:                    if (removeMBeanReference(currentObjectName, relationId,
1172:                            roleName)) {
1173:                        obsoleteReferenceList.add(currentObjectName);
1174:                    }
1175:                }
1176:                return obsoleteReferenceList;
1177:            }
1178:
1179:            private boolean removeMBeanReference(ObjectName objectName,
1180:                    String relationId, String roleName)
1181:                    throws IllegalArgumentException {
1182:                if (relationId == null)
1183:                    throw new IllegalArgumentException("Null Relation Id");
1184:                if (objectName == null)
1185:                    throw new IllegalArgumentException("Null ObjectName");
1186:                if (roleName == null)
1187:                    throw new IllegalArgumentException("Null Role Name.");
1188:                // first check if we have any references for MBean
1189:                HashMap mbeanReferenceMap = (HashMap) getReferencedMBeansFromMap(objectName);
1190:
1191:                // no references nothing to remove
1192:                if (mbeanReferenceMap == null)
1193:                    return true;
1194:                // we have references get the roleNames for the relationId
1195:                ArrayList roleNames = (ArrayList) (mbeanReferenceMap
1196:                        .get(relationId));
1197:
1198:                //check the roleNames is not null before removing
1199:                if (roleNames != null) {
1200:                    // roleName found remove it
1201:                    if (roleNames.indexOf(roleName) != -1)
1202:                        roleNames.remove(roleNames.indexOf(roleName));
1203:                    // no more references remove the relationId key
1204:                    if (roleNames.isEmpty())
1205:                        mbeanReferenceMap.remove(relationId);
1206:                }
1207:                if (mbeanReferenceMap.isEmpty()) {
1208:                    // now we can remove the MBean ObejctName with all references removed
1209:                    removeObjectName(objectName);
1210:                    return true;
1211:                }
1212:                return false;
1213:            }
1214:
1215:            private Map getReferencedMBeansFromMap(ObjectName objectName) {
1216:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1217:                    return ((HashMap) m_referencedMBeanObjectNameToRelationIds
1218:                            .get(objectName));
1219:                }
1220:            }
1221:
1222:            private boolean addNewMBeanReference(ObjectName objectName,
1223:                    String relationId, String roleName)
1224:                    throws IllegalArgumentException {
1225:                if (relationId == null)
1226:                    throw new IllegalArgumentException("Null Relation Id");
1227:                if (roleName == null)
1228:                    throw new IllegalArgumentException("Null Role Name");
1229:                if (objectName == null)
1230:                    throw new IllegalArgumentException("Null ObjectName.");
1231:
1232:                // get the ObjectNames of the referenced ObjectName
1233:                HashMap mbeanReferenceMap;
1234:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1235:                    mbeanReferenceMap = ((HashMap) m_referencedMBeanObjectNameToRelationIds
1236:                            .get(objectName));
1237:                }
1238:                // it is null, add it to our map and return true - we have a new reference
1239:                if (mbeanReferenceMap == null) {
1240:                    mbeanReferenceMap = new HashMap();
1241:                }
1242:                List roleNames = (List) mbeanReferenceMap.get(relationId);
1243:                if (roleNames == null) {
1244:                    roleNames = new ArrayList();
1245:                    roleNames.add(roleName);
1246:
1247:                    mbeanReferenceMap.put(relationId, roleNames);
1248:                    addObjectNameToMBeanReference(objectName, mbeanReferenceMap);
1249:                    return true;
1250:                } else {
1251:                    roleNames.add(roleName);
1252:                    addObjectNameToMBeanReference(objectName, mbeanReferenceMap);
1253:                    // not a new MBeanReference return false
1254:                    return false;
1255:                }
1256:            }
1257:
1258:            private void addObjectNameToMBeanReference(ObjectName objectName,
1259:                    HashMap mbeanReferenceMap) {
1260:                // get the mapfirst, then update it
1261:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1262:                    Map temp = (Map) m_referencedMBeanObjectNameToRelationIds
1263:                            .get(objectName);
1264:                    if (temp != null) {
1265:                        mbeanReferenceMap.putAll(temp);
1266:                    }
1267:                    m_referencedMBeanObjectNameToRelationIds.put(objectName,
1268:                            mbeanReferenceMap);
1269:                }
1270:            }
1271:
1272:            /**
1273:             * <p>Removes given relation from the Relation Service.</p>
1274:             * <p>A RelationNotification notification is sent, its type being:
1275:             * <ul>
1276:             * <li>RelationNotification.RELATION_BASIC_REMOVAL if the relation was only internal to the Relation Service </li>
1277:             * <li>RelationNotification.RELATION_MBEAN_REMOVAL if the relation is registered as an MBean</li>
1278:             * </ul></p>
1279:             * <p>For MBeans referenced in such relation, nothing will be done</p>
1280:             *
1281:             * @param relationId - relation id of the relation to be removed
1282:             * @throws IllegalArgumentException  - if null parameter
1283:             * @throws RelationServiceNotRegisteredException
1284:             *                                   - if the Relation Service is not registered in the MBean Server
1285:             * @throws RelationNotFoundException - if no relation corresponding to given relation id
1286:             */
1287:            public void removeRelation(String relationId)
1288:                    throws IllegalArgumentException,
1289:                    RelationServiceNotRegisteredException,
1290:                    RelationNotFoundException {
1291:                isActive();
1292:                if (relationId == null)
1293:                    throw new IllegalArgumentException("Null Relation Id");
1294:                Logger logger = getLogger();
1295:                if (logger.isEnabledFor(Logger.DEBUG))
1296:                    logger
1297:                            .debug("Removing a Relation from the RelationService.");
1298:                Object result = getRelationObject(relationId);
1299:                if (result instanceof  ObjectName) {
1300:                    // add the objectName to List
1301:                    List obsoleteReferences = new ArrayList();
1302:                    obsoleteReferences.add(result);
1303:                    // update Listener with the list of ObjectNames to be deregistered
1304:                    updateUnregistrationListener(null, obsoleteReferences);
1305:                }
1306:                // notify all listeners a relation has been removed
1307:                sendRelationRemovalNotification(relationId, null);
1308:
1309:                List nonReferencedObjectNameList = getNonReferencedMBeans(relationId);
1310:                // remove ObjectNames from global Map
1311:                removeNonReferencedMBeans(nonReferencedObjectNameList);
1312:                // remove relationId for our nonReferencedMBeans
1313:                removeRelationId(relationId);
1314:                // we have an MBean remove it from our Map
1315:                if (result instanceof  ObjectName)
1316:                    removeRelationMBean((ObjectName) result);
1317:                // get the corresponding relationTypeName for the relationId
1318:                String relationTypeName = getRelationTypeNameFromMap(relationId);
1319:                // remove relationId from our Map
1320:                removeRelationIdToRelationTypeName(relationId);
1321:                // get all the corresponding relationIds
1322:                List relationIdsList = getRelationIds(relationTypeName);
1323:
1324:                // we have relationIds for the removed relationTypeName remove them from our Map
1325:                if (relationIdsList != null) {
1326:                    relationIdsList.remove(relationId);
1327:                    if (relationIdsList.isEmpty()) {
1328:                        // now we can remove the relationTypeName
1329:                        removeRelationTypeName(relationTypeName);
1330:                    }
1331:                }
1332:            }
1333:
1334:            private void removeRelationMBean(ObjectName objectName) {
1335:                synchronized (m_relationMBeanObjectNameToRelationId) {
1336:                    m_relationMBeanObjectNameToRelationId.remove(objectName);
1337:                }
1338:            }
1339:
1340:            private void removeNonReferencedMBeans(List nonReferencedMBeansList) {
1341:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1342:                    for (Iterator i = nonReferencedMBeansList.iterator(); i
1343:                            .hasNext();) {
1344:                        ObjectName currentObjectName = (ObjectName) i.next();
1345:                        m_referencedMBeanObjectNameToRelationIds
1346:                                .remove(currentObjectName);
1347:                    }
1348:                }
1349:            }
1350:
1351:            private List getNonReferencedMBeans(String relationId) {
1352:                List referencedMBeanList = new ArrayList();
1353:                List nonReferencedObjectNameList = new ArrayList();
1354:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1355:                    for (Iterator i = (m_referencedMBeanObjectNameToRelationIds
1356:                            .keySet()).iterator(); i.hasNext();) {
1357:                        ObjectName currentObjectName = (ObjectName) i.next();
1358:                        HashMap relationIdMap = (HashMap) (m_referencedMBeanObjectNameToRelationIds
1359:                                .get(currentObjectName));
1360:                        if (relationIdMap.containsKey(relationId)) {
1361:                            relationIdMap.remove(relationId);
1362:                            referencedMBeanList.add(currentObjectName);
1363:                        }
1364:                        if (relationIdMap.isEmpty())
1365:                            nonReferencedObjectNameList.add(currentObjectName);
1366:                    }
1367:                }
1368:                return nonReferencedObjectNameList;
1369:            }
1370:
1371:            private void removeRelationTypeName(String relationTypeName) {
1372:                synchronized (m_relationTypeNameToRelationIds) {
1373:                    m_relationTypeNameToRelationIds.remove(relationTypeName);
1374:                }
1375:            }
1376:
1377:            private String getRelationTypeNameFromMap(String relationId) {
1378:                synchronized (m_relationIdToRelationTypeName) {
1379:                    return ((String) m_relationIdToRelationTypeName
1380:                            .get(relationId));
1381:                }
1382:            }
1383:
1384:            private void removeRelationIdToRelationTypeName(String relationId) {
1385:                synchronized (m_relationIdToRelationTypeName) {
1386:                    m_relationIdToRelationTypeName.remove(relationId);
1387:                }
1388:            }
1389:
1390:            private String getMBeanObjectName(ObjectName objectName) {
1391:                synchronized (m_relationMBeanObjectNameToRelationId) {
1392:                    return ((String) m_relationMBeanObjectNameToRelationId
1393:                            .get(objectName));
1394:                }
1395:            }
1396:
1397:            private void removeRelationId(String relationId) {
1398:                synchronized (m_relationIdToRelationObject) {
1399:                    m_relationIdToRelationObject.remove(relationId);
1400:                }
1401:            }
1402:
1403:            private void updateUnregistrationListener(List newReferenceList,
1404:                    List obsoleteReferences)
1405:                    throws RelationServiceNotRegisteredException {
1406:                if (newReferenceList != null && obsoleteReferences != null) {
1407:                    // nothing to do
1408:                    if (newReferenceList.isEmpty()
1409:                            && obsoleteReferences.isEmpty())
1410:                        return;
1411:                }
1412:                isActive();
1413:                if (newReferenceList != null || obsoleteReferences != null) {
1414:                    boolean isNewListener = false;
1415:                    if (m_notificationFilter == null) {
1416:                        m_notificationFilter = new MBeanServerNotificationFilter();
1417:                        isNewListener = true;
1418:                    }
1419:                    synchronized (m_notificationFilter) {
1420:                        // we have new references - update (Enable in NotificationFilter)
1421:                        if (newReferenceList != null)
1422:                            updateNewReferences(newReferenceList);
1423:
1424:                        // we have obsolete references - update (disable from notificationFilter)
1425:                        if (obsoleteReferences != null)
1426:                            updateObsoleteReferences(obsoleteReferences);
1427:
1428:                        ObjectName mbeanServerDelegateName = null;
1429:                        try {
1430:                            mbeanServerDelegateName = new ObjectName(
1431:                                    "JMImplementation:type=MBeanServerDelegate");
1432:                        } catch (MalformedObjectNameException ignored) {
1433:                        }
1434:
1435:                        if (isNewListener) {
1436:                            try {
1437:                                m_server.addNotificationListener(
1438:                                        mbeanServerDelegateName, this ,
1439:                                        m_notificationFilter, null);
1440:                            } catch (InstanceNotFoundException ex) {
1441:                                throw new RelationServiceNotRegisteredException(
1442:                                        ex.getMessage());
1443:                            }
1444:                        }
1445:                    }
1446:                }
1447:            }
1448:
1449:            private void updateObsoleteReferences(List obsoleteReferences) {
1450:                for (Iterator i = obsoleteReferences.iterator(); i.hasNext();) {
1451:                    ObjectName name = (ObjectName) i.next();
1452:                    m_notificationFilter.disableObjectName(name);
1453:                }
1454:            }
1455:
1456:            private void updateNewReferences(List newReferencesList) {
1457:                for (Iterator i = newReferencesList.iterator(); i.hasNext();) {
1458:                    ObjectName name = (ObjectName) i.next();
1459:                    m_notificationFilter.enableObjectName(name);
1460:                }
1461:            }
1462:
1463:            // if null we have an instance of the internalRelation otherwise we have an MBean and can use the proxy
1464:            private Relation getRelation(String relationId)
1465:                    throws RelationNotFoundException {
1466:                if (relationId == null)
1467:                    throw new IllegalArgumentException(
1468:                            "Null relation id passed into getRelation.");
1469:                Relation relation;
1470:                // if this is null we have a Relation not an ObjectName so we can return the Relation
1471:                if (isRelationMBean(relationId) == null) {
1472:                    synchronized (m_relationIdToRelationObject) {
1473:                        relation = (Relation) m_relationIdToRelationObject
1474:                                .get(relationId);
1475:                        return relation;
1476:                    }
1477:                }
1478:
1479:                final ObjectName relationObjectName = (ObjectName) m_relationIdToRelationObject
1480:                        .get(relationId);
1481:                // oops no relation at all
1482:                if (relationObjectName == null) {
1483:                    throw new RelationNotFoundException(
1484:                            "Relation not found with ID: " + relationId);
1485:                }
1486:                // good we have a relation lets return the proxy
1487:                m_proxy = (RelationSupportMBean) MBeanServerInvocationHandler
1488:                        .newProxyInstance(m_server, relationObjectName,
1489:                                RelationSupportMBean.class, false);
1490:                return m_proxy;
1491:            }
1492:
1493:            // will return an ObjectName or a Relation object
1494:            private Object getRelationObject(String relationId)
1495:                    throws IllegalArgumentException, RelationNotFoundException {
1496:                if (relationId == null)
1497:                    throw new IllegalArgumentException("Null Relation Id");
1498:                Object relationObject;
1499:                synchronized (m_relationIdToRelationObject) {
1500:                    relationObject = m_relationIdToRelationObject
1501:                            .get(relationId);
1502:                    if (relationObject == null) {
1503:                        // if this happens is caught by method looking for a null.
1504:                        throw new RelationNotFoundException("Null Relation");
1505:                    }
1506:                    // we return either an ObjectName or an InternalRelation
1507:                    return relationObject;
1508:                }
1509:            }
1510:
1511:            /**
1512:             * <p>Purges the relations</p>
1513:             * <p/>
1514:             * <p>Depending on the purgeFlag value, this method is either called automatically when a notification is received for the
1515:             * 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>
1516:             * <p/>
1517:             * <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
1518:             * unregistered and the purge not done immediately, if the ObjectName is reused and assigned to another MBean referenced in a relation,
1519:             * calling manually this purgeRelations() method will cause trouble, as will consider the ObjectName as corresponding to the unregistered MBean,
1520:             * not seeing the new one.</p>
1521:             * <p/>
1522:             * <p/>
1523:             * <ul>
1524:             * <li>if removing one MBean reference in the role makes its number of references less than the minimum degree, the relation has to be removed.</li>
1525:             * <li>if the remaining number of references after removing the MBean reference is still in the cardinality range, keep the relation and update
1526:             * it calling its handleMBeanUnregistration() callback.</li>
1527:             * </ul></p>
1528:             *
1529:             * @throws RelationServiceNotRegisteredException
1530:             *          - if the Relation Service is not registered in the MBean Server.
1531:             */
1532:            public void purgeRelations()
1533:                    throws RelationServiceNotRegisteredException {
1534:                isActive();
1535:                Logger logger = getLogger();
1536:                if (logger.isEnabledFor(Logger.DEBUG))
1537:                    logger.debug("purging relations");
1538:
1539:                ArrayList localDeregisteredNotificationList;
1540:                synchronized (m_deregisteredNotificationList) {
1541:                    // cone the list of notifications to be able to recieve notification while processing current ones
1542:                    localDeregisteredNotificationList = ((ArrayList) ((ArrayList) m_deregisteredNotificationList)
1543:                            .clone());
1544:                    // now reset
1545:                    m_deregisteredNotificationList = new ArrayList();
1546:                }
1547:
1548:                List obsoleteReferenceList = new ArrayList();
1549:                Map localMBeanToRelationId = new HashMap();
1550:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1551:                    for (Iterator i = localDeregisteredNotificationList
1552:                            .iterator(); i.hasNext();) {
1553:                        MBeanServerNotification serverNotification = (MBeanServerNotification) i
1554:                                .next();
1555:                        ObjectName deregisteredMBeanName = serverNotification
1556:                                .getMBeanName();
1557:                        obsoleteReferenceList.add(deregisteredMBeanName);
1558:
1559:                        HashMap relationIdMap = (HashMap) m_referencedMBeanObjectNameToRelationIds
1560:                                .get(deregisteredMBeanName);
1561:                        localMBeanToRelationId.put(deregisteredMBeanName,
1562:                                relationIdMap);
1563:                        m_referencedMBeanObjectNameToRelationIds
1564:                                .remove(deregisteredMBeanName);
1565:                    }
1566:                }
1567:
1568:                // update listener filter to avoid recieving notifications for same MBeans
1569:                updateUnregistrationListener(null, obsoleteReferenceList);
1570:                for (Iterator i = localDeregisteredNotificationList.iterator(); i
1571:                        .hasNext();) {
1572:                    MBeanServerNotification currentNotification = (MBeanServerNotification) i
1573:                            .next();
1574:                    ObjectName unregisteredMBeanObjectName = currentNotification
1575:                            .getMBeanName();
1576:                    HashMap localRelationIdMap = (HashMap) (localMBeanToRelationId
1577:                            .get(unregisteredMBeanObjectName));
1578:
1579:                    Set localRelationIdSet = localRelationIdMap.keySet();
1580:                    // handles the unregistration of mbeans
1581:                    unregisterReferences(localRelationIdSet,
1582:                            localRelationIdMap, unregisteredMBeanObjectName);
1583:                }
1584:            }
1585:
1586:            private void unregisterReferences(Set relationIdSet,
1587:                    Map relationIdMap, ObjectName objectName)
1588:                    throws RelationServiceNotRegisteredException {
1589:                for (Iterator iter = relationIdSet.iterator(); iter.hasNext();) {
1590:                    String currentRelationId = (String) iter.next();
1591:                    ArrayList localRoleNamesList = (ArrayList) (relationIdMap
1592:                            .get(currentRelationId));
1593:                    try {
1594:                        handleReferenceUnregistration(currentRelationId,
1595:                                objectName, localRoleNamesList);
1596:                    } catch (RelationTypeNotFoundException ex) {
1597:                        throw new RuntimeOperationsException(null, ex
1598:                                .getMessage());
1599:                    } catch (RelationNotFoundException ex) {
1600:                        throw new RuntimeOperationsException(null, ex
1601:                                .getMessage());
1602:                    } catch (RoleNotFoundException ex) {
1603:                        throw new RuntimeOperationsException(null, ex
1604:                                .getMessage());
1605:                    }
1606:                }
1607:            }
1608:
1609:            private void handleReferenceUnregistration(String relationId,
1610:                    ObjectName unregisteredObjectName, List roleNames)
1611:                    throws IllegalArgumentException,
1612:                    RelationServiceNotRegisteredException,
1613:                    RelationNotFoundException, RoleNotFoundException,
1614:                    RelationTypeNotFoundException {
1615:                if (relationId == null)
1616:                    throw new IllegalArgumentException("Null relationId");
1617:                if (unregisteredObjectName == null)
1618:                    throw new IllegalArgumentException("Null ObjectName");
1619:                if (roleNames == null)
1620:                    throw new IllegalArgumentException("Null roleName list");
1621:
1622:                isActive();
1623:                String relationTypeName = getRelationTypeName(relationId);
1624:
1625:                boolean canDeleteRelation = false;
1626:                for (Iterator i = roleNames.iterator(); i.hasNext();) {
1627:                    String currentRoleName = (String) i.next();
1628:                    int currentRoleCardinality = (getRoleCardinality(
1629:                            relationId, currentRoleName)).intValue();
1630:                    int newRoleCardinality = currentRoleCardinality - 1;
1631:                    RoleInfo currentRoleInfo;
1632:                    try {
1633:                        currentRoleInfo = getRoleInfo(relationTypeName,
1634:                                currentRoleName);
1635:                    } catch (RelationTypeNotFoundException ex) {
1636:                        throw new RuntimeOperationsException(null, ex
1637:                                .getMessage());
1638:                    } catch (RoleInfoNotFoundException ex) {
1639:                        throw new RuntimeOperationsException(null, ex
1640:                                .getMessage());
1641:                    }
1642:                    // check that the role cardinality is maintained by the removal
1643:                    if (!(currentRoleInfo.checkMinDegree(newRoleCardinality))) {
1644:                        canDeleteRelation = true;
1645:                    }
1646:                }
1647:                // roleMinValue been checked everything ok, can now remove the relation
1648:                if (canDeleteRelation) {
1649:                    removeRelation(relationId);
1650:                } else {
1651:                    for (Iterator i = roleNames.iterator(); i.hasNext();) {
1652:                        String currentRoleName = (String) i.next();
1653:                        try {
1654:                            Relation relation = getRelation(relationId);
1655:                            relation.handleMBeanUnregistration(
1656:                                    unregisteredObjectName, currentRoleName);
1657:                        } catch (InvalidRoleValueException ex) {
1658:                            throw new RuntimeOperationsException(null, ex
1659:                                    .getMessage());
1660:                        }
1661:                    }
1662:                }
1663:            }
1664:
1665:            private void removeObjectName(ObjectName objectName) {
1666:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
1667:                    m_referencedMBeanObjectNameToRelationIds.remove(objectName);
1668:                }
1669:            }
1670:
1671:            /**
1672:             * <p>Retrieves the relations where a given MBean is referenced.</p>
1673:             *
1674:             * @param mbeanObjectName  - ObjectName of MBean
1675:             * @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.
1676:             * @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.
1677:             * @return - HashMap, where the keys are the relation ids of the relations where the MBean is referenced, and the value is, for each key,
1678:             *         an ArrayList of role names (as an MBean can be referenced in several roles in the same relation).
1679:             * @throws IllegalArgumentException - if mbeanObjectName is null
1680:             */
1681:            public Map findReferencingRelations(ObjectName mbeanObjectName,
1682:                    String relationTypeName, String roleName)
1683:                    throws IllegalArgumentException {
1684:                if (mbeanObjectName == null)
1685:                    throw new IllegalArgumentException(
1686:                            "Cannot find references for a null ObjectName");
1687:                Logger logger = getLogger();
1688:                if (logger.isEnabledFor(Logger.DEBUG))
1689:                    logger
1690:                            .debug("finding referencing relations for MBean with ObjectName: "
1691:                                    + mbeanObjectName.getCanonicalName()
1692:                                    + " and relationTypeName: "
1693:                                    + relationTypeName
1694:                                    + " and roleName: "
1695:                                    + roleName);
1696:                HashMap result = new HashMap();
1697:                HashMap relationIdMap = (HashMap) getReferencedMBeansFromMap(mbeanObjectName);
1698:                if (relationIdMap != null) {
1699:                    Set allRelationIds = relationIdMap.keySet();
1700:                    List relationIdList;
1701:                    if (relationTypeName == null) {
1702:                        relationIdList = new ArrayList(allRelationIds);
1703:                    } else {
1704:                        relationIdList = findReferencesFromIds(allRelationIds,
1705:                                relationTypeName);
1706:                    }
1707:
1708:                    for (Iterator i = relationIdList.iterator(); i.hasNext();) {
1709:                        String currentRelationId = (String) i.next();
1710:                        ArrayList currentRoleNameList = (ArrayList) relationIdMap
1711:                                .get(currentRelationId);
1712:                        if (roleName == null) {
1713:                            result.put(currentRelationId, currentRoleNameList
1714:                                    .clone());
1715:                        } else if (currentRoleNameList.contains(roleName)) {
1716:                            ArrayList roleNameList = new ArrayList();
1717:                            roleNameList.add(roleName);
1718:                            result.put(currentRelationId, roleNameList);
1719:                        }
1720:                    }
1721:                }
1722:                return result;
1723:            }
1724:
1725:            private ArrayList findReferencesFromIds(Set allRelationIds,
1726:                    String relationTypeName) {
1727:                ArrayList relationIdList = new ArrayList();
1728:                for (Iterator i = allRelationIds.iterator(); i.hasNext();) {
1729:                    String currentRelationId = (String) i.next();
1730:                    String currentRelationTypeName = getRelationTypeNameFromMap(currentRelationId);
1731:                    if (currentRelationTypeName.equals(relationTypeName)) {
1732:                        relationIdList.add(currentRelationId);
1733:                    }
1734:                }
1735:                return relationIdList;
1736:            }
1737:
1738:            /**
1739:             * <p>Retrieves the MBeans associated to given one in a relation.</p>
1740:             *
1741:             * @param mbeanObjectName  - ObjectName of MBean
1742:             * @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
1743:             * @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.
1744:             * @return - 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
1745:             *         relation ids of the relations where the key MBean is associated to given one (as they can be associated in
1746:             *         several different relations).
1747:             * @throws IllegalArgumentException - if mbeanObjectName is null
1748:             */
1749:            public Map findAssociatedMBeans(ObjectName mbeanObjectName,
1750:                    String relationTypeName, String roleName)
1751:                    throws IllegalArgumentException {
1752:                if (mbeanObjectName == null)
1753:                    throw new IllegalArgumentException(
1754:                            "mbean ObjectName cannot be null.");
1755:                Logger logger = getLogger();
1756:                if (logger.isEnabledFor(Logger.DEBUG))
1757:                    logger
1758:                            .debug("finding associated relations for MBean with ObjectName: "
1759:                                    + mbeanObjectName.getCanonicalName()
1760:                                    + " and relationTypeName: "
1761:                                    + relationTypeName
1762:                                    + " and roleName: "
1763:                                    + roleName);
1764:                Map relationIdsToRoleNames = findReferencingRelations(
1765:                        mbeanObjectName, relationTypeName, roleName);
1766:                Map result = new HashMap();
1767:                for (Iterator i = (relationIdsToRoleNames.keySet()).iterator(); i
1768:                        .hasNext();) {
1769:                    String currentRelationId = (String) i.next();
1770:                    HashMap objectNamesToRoleMap;
1771:                    try {
1772:                        objectNamesToRoleMap = (HashMap) (getReferencedMBeans(currentRelationId));
1773:                    } catch (RelationNotFoundException ex) {
1774:                        logger.warn("Relation with ID: " + currentRelationId
1775:                                + " not found.");
1776:                        throw new RuntimeOperationsException(null,
1777:                                "Relation Not Found");
1778:                    }
1779:                    for (Iterator iter = (objectNamesToRoleMap.keySet())
1780:                            .iterator(); iter.hasNext();) {
1781:                        ObjectName objectName = (ObjectName) iter.next();
1782:                        if (!(objectName.equals(mbeanObjectName))) {
1783:                            ArrayList currentRelationIdList = (ArrayList) result
1784:                                    .get(objectName);
1785:                            if (currentRelationIdList == null) {
1786:                                currentRelationIdList = new ArrayList();
1787:                                result.put(objectName, currentRelationIdList);
1788:                            }
1789:                            currentRelationIdList.add(currentRelationId);
1790:                        }
1791:                    }
1792:                }
1793:                return result;
1794:            }
1795:
1796:            /**
1797:             * <p>Returns the relation ids for relations of the given type. </p>
1798:             *
1799:             * @param relationTypeName - relation type name
1800:             * @return - arrayList of relationIds
1801:             * @throws IllegalArgumentException      - if relationTypeName is null
1802:             * @throws RelationTypeNotFoundException - if there is no relation type with that name
1803:             */
1804:            public List findRelationsOfType(String relationTypeName)
1805:                    throws IllegalArgumentException,
1806:                    RelationTypeNotFoundException {
1807:                if (relationTypeName == null)
1808:                    throw new IllegalArgumentException(
1809:                            "relation type name cannot be null.");
1810:                Logger logger = getLogger();
1811:                if (logger.isEnabledFor(Logger.DEBUG))
1812:                    logger
1813:                            .debug("finding relations matching relationTypeName: "
1814:                                    + relationTypeName);
1815:
1816:                // throws RelationTypeNotFoundException if not found
1817:                getRelationType(relationTypeName);
1818:
1819:                List relationIdList = getRelationIds(relationTypeName);
1820:                if (relationIdList == null)
1821:                    return new ArrayList();
1822:
1823:                return new ArrayList(relationIdList);
1824:            }
1825:
1826:            /**
1827:             * <P>Retrieves role value for given role name in given relation</p>
1828:             *
1829:             * @param relationId - the relation identifier
1830:             * @param roleName   - the name of the role
1831:             * @return - an ArrayList of ObjectName objects being the role value
1832:             * @throws IllegalArgumentException  - if null parameter
1833:             * @throws RelationServiceNotRegisteredException
1834:             *                                   - if the Relation Service is not registered
1835:             * @throws RelationNotFoundException - if no relation with given id
1836:             * @throws RoleNotFoundException     - if there is no role with given name or
1837:             *                                   the role is not readable
1838:             */
1839:            public List getRole(String relationId, String roleName)
1840:                    throws IllegalArgumentException,
1841:                    RelationServiceNotRegisteredException,
1842:                    RelationNotFoundException, RoleNotFoundException {
1843:                isActive();
1844:                if (relationId == null)
1845:                    throw new IllegalArgumentException(
1846:                            "RelationId cannot have a null value.");
1847:                if (roleName == null)
1848:                    throw new IllegalArgumentException(
1849:                            "Role Name cannot have a null value.");
1850:                Relation relationObject = getRelation(relationId);
1851:                return relationObject.getRole(roleName);
1852:            }
1853:
1854:            /**
1855:             * <p>Retrieves values of roles with given names in given relation</p>
1856:             *
1857:             * @param relationId - the relation identifier
1858:             * @param roleNames  - array of names of roles to be retrieved
1859:             * @return - a RoleResult object, including a RoleList (for roles succcessfully retrieved) and a RoleUnresolvedList (for roles not retrieved).
1860:             * @throws IllegalArgumentException  - if either parameter is null
1861:             * @throws RelationNotFoundException - if no relation with given id
1862:             * @throws RelationServiceNotRegisteredException
1863:             *                                   - if the Relation Service is not registered in the MBean Server
1864:             */
1865:            public RoleResult getRoles(String relationId, String[] roleNames)
1866:                    throws IllegalArgumentException, RelationNotFoundException,
1867:                    RelationServiceNotRegisteredException {
1868:                if (relationId == null)
1869:                    throw new IllegalArgumentException(
1870:                            "Illegal Argument relationId is null.");
1871:                if (roleNames == null)
1872:                    throw new IllegalArgumentException(
1873:                            "Array of Roles Names should not be null");
1874:                isActive();
1875:                Relation relation = getRelation(relationId);
1876:                return relation.getRoles(roleNames);
1877:            }
1878:
1879:            /**
1880:             * <p>Returns all roles present in the relation</p>
1881:             *
1882:             * @param relationId - the relation identifier
1883:             * @return - a  RoleResult object, including a RoleList (for roles succcessfully retrieved) and a RoleUnresolvedList (for roles not readable).
1884:             * @throws IllegalArgumentException  - if the relation id is null
1885:             * @throws RelationNotFoundException - if no relation for given id
1886:             * @throws RelationServiceNotRegisteredException
1887:             *                                   - if the Relation Service is not registered in the MBean Server
1888:             */
1889:            public RoleResult getAllRoles(String relationId)
1890:                    throws IllegalArgumentException, RelationNotFoundException,
1891:                    RelationServiceNotRegisteredException {
1892:                if (relationId == null)
1893:                    throw new IllegalArgumentException(
1894:                            "RelationId cannot be null");
1895:                //Object relationObject = getRelationObject(relationId);
1896:                Relation relation = getRelation(relationId);
1897:                return relation.getAllRoles();
1898:            }
1899:
1900:            /**
1901:             * <p>Retrieves the number of MBeans currently referenced in the given role.</p>
1902:             *
1903:             * @param relationId - relation id
1904:             * @param roleName   - name of role
1905:             * @return - the number of currently referenced MBeans in that role
1906:             * @throws IllegalArgumentException  - if a null parameter
1907:             * @throws RelationNotFoundException - if no relation with given id
1908:             * @throws RoleNotFoundException     - if there is no role with given name
1909:             */
1910:            public Integer getRoleCardinality(String relationId, String roleName)
1911:                    throws IllegalArgumentException, RelationNotFoundException,
1912:                    RoleNotFoundException {
1913:                if (relationId == null)
1914:                    throw new IllegalArgumentException("Relation Id is null.");
1915:                if (roleName == null)
1916:                    throw new IllegalArgumentException("Role Name is null.");
1917:                Object relationObject = getRelationObject(relationId);
1918:                if (relationObject instanceof  InternalRelation)
1919:                    return (((InternalRelation) relationObject)
1920:                            .getRoleCardinality(roleName));
1921:                else
1922:                    return m_proxy.getRoleCardinality(roleName);
1923:            }
1924:
1925:            /**
1926:             * <p>Sets the given role in given relation</p>
1927:             * <p>Will check the role according to its corresponding role definition provided in relation's relation type </p>
1928:             * <p>The Relation Service will keep track of the change to keep the consistency of relations by handling referenced MBean unregistrations</p>
1929:             *
1930:             * @param relationId - the relation identifier
1931:             * @param role       - role to be set (name and new value)
1932:             * @throws IllegalArgumentException  - if null parameter
1933:             * @throws RelationServiceNotRegisteredException
1934:             *                                   - if relation service is not registered in the MBean Server
1935:             * @throws RelationNotFoundException - if no relation with given id
1936:             * @throws RoleNotFoundException     - if the role does not exist or is not writable
1937:             * @throws InvalidRoleValueException - if value provided for role is not valid i.e.
1938:             *                                   <ul>
1939:             *                                   <li>the number of referenced MBeans in given value is less than expected minimum degree</li>
1940:             *                                   <li>the number of referenced MBeans in provided value exceeds expected maximum degree </li>
1941:             *                                   <li>one referenced MBean in the value is not an Object of the MBean class expected for that role </li>
1942:             *                                   <li>an MBean provided for that role does not exist</li>
1943:             *                                   </ul>
1944:             */
1945:            public void setRole(String relationId, Role role)
1946:                    throws IllegalArgumentException,
1947:                    RelationServiceNotRegisteredException,
1948:                    RelationNotFoundException, RoleNotFoundException,
1949:                    InvalidRoleValueException {
1950:                if (relationId == null)
1951:                    throw new IllegalArgumentException(
1952:                            "Illegal Null Relation Id.");
1953:                if (role == null)
1954:                    throw new IllegalArgumentException("Illegal Null Role.");
1955:                isActive();
1956:                Relation relation = getRelation(relationId);
1957:                try {
1958:                    relation.setRole(role);
1959:                } catch (RelationTypeNotFoundException e) {
1960:                    throw new RelationNotFoundException(
1961:                            "RelationType not found error: " + e.getMessage());
1962:                }
1963:            }
1964:
1965:            /**
1966:             * <p>Sets the given roles in given relation</p>
1967:             * <p>Will check the role according to its corresponding role definition provided in relation's relation type </p>
1968:             * <p>The Relation Service keeps track of the changes to keep the consistency of relations by handling referenced MBean unregistrations</p>
1969:             *
1970:             * @param relationId - the relation identifier
1971:             * @param roleList   - the list of roles to be set
1972:             * @return -  RoleResult object, including a RoleList(for roles succcessfully set) and a RoleUnresolvedList(for roles not set).
1973:             * @throws RelationServiceNotRegisteredException
1974:             *                                   - if the realtionService has not been registered in the mbean server
1975:             * @throws IllegalArgumentException  - if any of the parameters are null
1976:             * @throws RelationNotFoundException - if no relation for the given id has been found
1977:             */
1978:            public RoleResult setRoles(String relationId, RoleList roleList)
1979:                    throws RelationServiceNotRegisteredException,
1980:                    IllegalArgumentException, RelationNotFoundException {
1981:                if (relationId == null)
1982:                    throw new IllegalArgumentException("Relation Id is null");
1983:                if (roleList == null)
1984:                    throw new IllegalArgumentException("RoleList is null");
1985:                isActive();
1986:                Relation relation = getRelation(relationId);
1987:                try {
1988:                    return relation.setRoles(roleList);
1989:                } catch (RelationTypeNotFoundException ex) {
1990:                    throw new RuntimeOperationsException(null,
1991:                            "Unable to find a RelationTypeName for relation ID: "
1992:                                    + relationId);
1993:                }
1994:            }
1995:
1996:            /**
1997:             * <p>Retrieves MBeans referenced in the various roles of the relation</p>
1998:             *
1999:             * @param relationId - the relation identifier
2000:             * @return - a hashMap mapping as key the MBean ObjectName and an arrayList of String roleNames.
2001:             * @throws IllegalArgumentException  - if relation id is null
2002:             * @throws RelationNotFoundException - if no relation for given relation id
2003:             */
2004:            public Map getReferencedMBeans(String relationId)
2005:                    throws IllegalArgumentException, RelationNotFoundException {
2006:                if (relationId == null)
2007:                    throw new IllegalArgumentException("Null Relation Id");
2008:                Logger logger = getLogger();
2009:                if (logger.isEnabledFor(Logger.DEBUG))
2010:                    logger.debug("getting MBeans referenced for ID: "
2011:                            + relationId);
2012:                Relation relation = getRelation(relationId);
2013:                return relation.getReferencedMBeans();
2014:            }
2015:
2016:            /**
2017:             * <p>Returns name of associated relation type for given relation</p>
2018:             *
2019:             * @param relationId - the relation identifier
2020:             * @return - the name of the associated relation type
2021:             * @throws IllegalArgumentException  - if null parameter
2022:             * @throws RelationNotFoundException - if no relation for given relation id
2023:             */
2024:            public String getRelationTypeName(String relationId)
2025:                    throws IllegalArgumentException, RelationNotFoundException {
2026:                if (relationId == null)
2027:                    throw new IllegalArgumentException("Null Relation Id");
2028:                Logger logger = getLogger();
2029:                if (logger.isEnabledFor(Logger.DEBUG))
2030:                    logger.debug("getting the relationType for ID: "
2031:                            + relationId);
2032:                Relation relation = getRelation(relationId);
2033:                return relation.getRelationTypeName();
2034:            }
2035:
2036:            /**
2037:             * <p>Invoked when a JMX notification occurs. Currently handles notifications for unregistration of MBeans,
2038:             * either referenced in a relation role or being a relation itself.</p>
2039:             *
2040:             * @param notification - the notification needs to be of type MBeanServerNotification
2041:             * @param handback     - An opaque object which helps the listener to associate information regarding the MBean emitter (can be null).
2042:             */
2043:            public void handleNotification(Notification notification,
2044:                    Object handback) {
2045:                if (notification == null)
2046:                    throw new IllegalArgumentException("Null Notification");
2047:                if (notification instanceof  MBeanServerNotification) {
2048:                    String notificationType = notification.getType();
2049:                    if (notificationType
2050:                            .equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
2051:                        ObjectName mbeanName = ((MBeanServerNotification) notification)
2052:                                .getMBeanName();
2053:                        // handle unregistration by purging relations
2054:                        handleUnregistration(notification, mbeanName);
2055:                        // remove mbeans now
2056:                        handleMBeanRemoval(mbeanName);
2057:                    }
2058:                }
2059:            }
2060:
2061:            private void handleMBeanRemoval(ObjectName mbeanName) {
2062:                String relationId = getMBeanObjectName(mbeanName);
2063:                if (relationId != null) {
2064:                    try {
2065:                        // we have a relationId now removeRelation
2066:                        removeRelation(relationId);
2067:                    } catch (Exception ex) {
2068:                        throw new RuntimeOperationsException(null, ex
2069:                                .getMessage());
2070:                    }
2071:                }
2072:            }
2073:
2074:            private void handleUnregistration(Notification notification,
2075:                    ObjectName objectName) {
2076:                boolean isReferenced = false;
2077:                synchronized (m_referencedMBeanObjectNameToRelationIds) {
2078:                    // check the mbeanObjectName can be found
2079:                    if (m_referencedMBeanObjectNameToRelationIds
2080:                            .containsKey(objectName)) {
2081:                        // it does so add it to our list of deregistrations
2082:                        synchronized (m_deregisteredNotificationList) {
2083:                            m_deregisteredNotificationList.add(notification);
2084:                        }
2085:                        isReferenced = true;
2086:                    }
2087:                    if (isReferenced && m_purgeFlag) {
2088:                        try {
2089:                            // purge the RelationService
2090:                            purgeRelations();
2091:                        } catch (Exception ex) {
2092:                            throw new RuntimeOperationsException(null, ex
2093:                                    .getMessage());
2094:                        }
2095:                    }
2096:                }
2097:            }
2098:
2099:            /**
2100:             * <p>Returns a NotificationInfo object containing the name of the Java class of the notification and the notification types sent</p>
2101:             *
2102:             * @return - the array of possible notifications
2103:             */
2104:            public MBeanNotificationInfo[] getNotificationInfo() {
2105:                MBeanNotificationInfo[] notificationInfo = new MBeanNotificationInfo[1];
2106:                String[] notificationTypes = new String[6];
2107:                notificationTypes[0] = RelationNotification.RELATION_BASIC_CREATION;
2108:                notificationTypes[1] = RelationNotification.RELATION_MBEAN_CREATION;
2109:                notificationTypes[2] = RelationNotification.RELATION_BASIC_UPDATE;
2110:                notificationTypes[3] = RelationNotification.RELATION_MBEAN_UPDATE;
2111:                notificationTypes[4] = RelationNotification.RELATION_BASIC_REMOVAL;
2112:                notificationTypes[5] = RelationNotification.RELATION_MBEAN_REMOVAL;
2113:
2114:                String notificationDescription = "Sent when a relation is created, updated or deleted.";
2115:                notificationInfo[0] = new MBeanNotificationInfo(
2116:                        notificationTypes, "RelationNotification",
2117:                        notificationDescription);
2118:                return notificationInfo;
2119:            }
2120:
2121:            /**
2122:             * <p>Implementation of interface MBeanRegistration @see MBeanRegistration</p>
2123:             * <p>Allows the MBean to perform any operations it needs before being registered in the MBean server. If the name of the MBean is
2124:             * not specified, the MBean can provide a name for its registration. If any exception is raised, the MBean will not be registered
2125:             * in the MBean server.</p>
2126:             *
2127:             * @param server - The MBean server in which the MBean will be registered
2128:             * @param name   - The object name of the MBean. This name is null if the name parameter to one of the createMBean or registerMBean
2129:             *               methods in the @see MBeanServer interface is null. In that case, this method must return a non-null ObjectName for the new MBean.
2130:             * @return - The name under which the MBean is to be registered. This value must not be null. If the name parameter is
2131:             *         not null, it will usually but not necessarily be the returned value
2132:             * @throws Exception - This exception will be caught by the MBean server and re-thrown as an
2133:             * @see javax.management.MBeanRegistrationException or a @see RuntimeMBeanException.
2134:             */
2135:            public ObjectName preRegister(MBeanServer server, ObjectName name)
2136:                    throws Exception {
2137:                m_server = server;
2138:                m_relationServiceObjectName = name == null ? new ObjectName(
2139:                        m_server.getDefaultDomain(), "service", "Relation")
2140:                        : name;
2141:                return m_relationServiceObjectName;
2142:            }
2143:
2144:            /**
2145:             * <p>Allows the MBean to perform any operations needed after having been registered in the MBean server or after the registration has failed</p>
2146:             *
2147:             * @param registrationDone - Indicates whether or not the MBean has been successfully registered in the MBean server.
2148:             *                         The value false means that the registration phase has failed
2149:             * @see MBeanRegistration
2150:             */
2151:            public void postRegister(Boolean registrationDone) {
2152:                Logger logger = getLogger();
2153:                boolean done = registrationDone.booleanValue();
2154:                if (!done) {
2155:                    m_server = null;
2156:                    logger.warn("Relation service was NOT registered");
2157:                } else {
2158:                    if (logger.isEnabledFor(Logger.DEBUG)) {
2159:                        logger.debug("Relation service postRegistered");
2160:                    }
2161:                }
2162:            }
2163:
2164:            /**
2165:             * <p>Allows the MBean to perform any operations it needs before being unregistered by the MBean server.
2166:             *
2167:             * @throws Exception - This exception will be caught by the MBean server and re-thrown as an
2168:             * @see MBeanRegistration </p>
2169:             *      <p>The impmentation does nothing but log registration of the relation service</p>
2170:             * @see javax.management.MBeanRegistrationException or a @see RuntimeMBeanException
2171:             */
2172:            public void preDeregister() throws Exception {
2173:                Logger logger = getLogger();
2174:                if (logger.isEnabledFor(Logger.DEBUG)) {
2175:                    logger.debug("Relation service preDeregistered");
2176:                }
2177:            }
2178:
2179:            /**
2180:             * <p> logs nothing but log postRegisration</p>
2181:             * <p> Implementation of MBeanRegistration</p>
2182:             */
2183:            public void postDeregister() {
2184:                Logger logger = getLogger();
2185:                if (logger.isEnabledFor(Logger.DEBUG)) {
2186:                    logger.debug("Relation service postDeregistered");
2187:                }
2188:            }
2189:
2190:            static void throwRoleProblemException(int problemType,
2191:                    String roleName) throws IllegalArgumentException,
2192:                    RoleNotFoundException, InvalidRoleValueException {
2193:                switch (problemType) {
2194:                case RoleStatus.NO_ROLE_WITH_NAME:
2195:                    throw new RoleNotFoundException("RoleName: " + roleName
2196:                            + " does not exist in the relation");
2197:                case RoleStatus.ROLE_NOT_READABLE:
2198:                    throw new RoleNotFoundException("RoleName: " + roleName
2199:                            + " is not readable");
2200:                case RoleStatus.ROLE_NOT_WRITABLE:
2201:                    throw new RoleNotFoundException("RoleName: " + roleName
2202:                            + " is not writable");
2203:                case RoleStatus.LESS_THAN_MIN_ROLE_DEGREE:
2204:                    throw new InvalidRoleValueException("RoleName: " + roleName
2205:                            + " has references less than the expected minimum.");
2206:                case RoleStatus.MORE_THAN_MAX_ROLE_DEGREE:
2207:                    throw new InvalidRoleValueException("RoleName: " + roleName
2208:                            + " has references more than the expected maximum.");
2209:                case RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS:
2210:                    throw new InvalidRoleValueException(
2211:                            "RoleName: "
2212:                                    + roleName
2213:                                    + " has a MBean reference to a MBean not of the expected class of references for that role.");
2214:                case RoleStatus.REF_MBEAN_NOT_REGISTERED:
2215:                    throw new InvalidRoleValueException(
2216:                            "RoleName: "
2217:                                    + roleName
2218:                                    + "  has a reference to null MBean or to a MBean not registered.");
2219:                }
2220:            }
2221:
2222:            private Logger getLogger() {
2223:                return Log.getLogger(getClass().getName());
2224:            }
2225:
2226:            // inner class to represent internal relations defined in the relationService
2227:            final class InternalRelation extends RelationSupport {
2228:                InternalRelation(String relationId,
2229:                        ObjectName relationServiceObjectName,
2230:                        String relationTypeName, RoleList roleList)
2231:                        throws InvalidRoleValueException,
2232:                        IllegalArgumentException {
2233:                    super (relationId, relationServiceObjectName,
2234:                            relationTypeName, roleList);
2235:                }
2236:
2237:                // checks role can be read
2238:                int getReadingProblemType(Role role, String roleName,
2239:                        String relationTypeName) {
2240:                    if (roleName == null)
2241:                        throw new IllegalArgumentException("Null RoleName");
2242:                    if (role == null)
2243:                        return (RoleStatus.NO_ROLE_WITH_NAME);
2244:                    else {
2245:                        try {
2246:                            return ((checkRoleReading(roleName,
2247:                                    relationTypeName)).intValue());
2248:                        } catch (RelationTypeNotFoundException ex) {
2249:                            throw new RuntimeOperationsException(null, ex
2250:                                    .getMessage());
2251:                        }
2252:                    }
2253:                }
2254:
2255:                // overridden from RelationSupport
2256:                int getRoleWritingValue(Role role, String relationTypeName,
2257:                        Boolean toBeInitialized)
2258:                        throws RelationTypeNotFoundException {
2259:                    try { // check role is writable
2260:                        return (checkRoleWriting(role, relationTypeName,
2261:                                toBeInitialized)).intValue();
2262:                    } catch (RelationTypeNotFoundException ex) {
2263:                        throw new RuntimeOperationsException(null, ex
2264:                                .getMessage());
2265:                    }
2266:                }
2267:
2268:                // sends role update notification
2269:                void sendUpdateRoleNotification(String relationId, Role role,
2270:                        List oldRoleValue)
2271:                        throws RelationServiceNotRegisteredException,
2272:                        RelationNotFoundException {
2273:                    if (relationId == null)
2274:                        throw new IllegalArgumentException(
2275:                                "Null RelationId passed into sendUpdateRoleNotification");
2276:                    if (role == null)
2277:                        throw new IllegalArgumentException(
2278:                                "Null role passed into sendUpdateRoleNotification");
2279:                    if (oldRoleValue == null)
2280:                        throw new IllegalArgumentException(
2281:                                "Null list of role Values passed into sendUpdateRoleNotification");
2282:                    sendRoleUpdateNotification(relationId, role, oldRoleValue);
2283:                }
2284:
2285:                void updateRelationServiceMap(String relationId, Role role,
2286:                        List oldRoleValue) throws IllegalArgumentException,
2287:                        RelationServiceNotRegisteredException,
2288:                        RelationNotFoundException {
2289:                    if (relationId == null)
2290:                        throw new IllegalArgumentException(
2291:                                "Null RelationId passed into updateRelationServiceMap");
2292:                    if (role == null)
2293:                        throw new IllegalArgumentException(
2294:                                "Null role passed into updateRelationServiceMap");
2295:                    if (oldRoleValue == null)
2296:                        throw new IllegalArgumentException(
2297:                                "Null list of role Values passed into updateRelationServiceMap");
2298:                    updateRoleMap(relationId, role, oldRoleValue);
2299:                }
2300:            }
2301:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.