1 /*
2 * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26 package javax.management.relation;
27
28 import static com.sun.jmx.defaults.JmxProperties.RELATION_LOGGER;
29 import static com.sun.jmx.mbeanserver.Util.cast;
30
31 import java.util.ArrayList;
32 import java.util.Date;
33 import java.util.HashMap;
34 import java.util.Iterator;
35 import java.util.List;
36 import java.util.Map;
37 import java.util.Set;
38 import java.util.concurrent.atomic.AtomicLong;
39 import java.util.logging.Level;
40
41 import javax.management.Attribute;
42 import javax.management.AttributeNotFoundException;
43 import javax.management.InstanceNotFoundException;
44 import javax.management.InvalidAttributeValueException;
45 import javax.management.MBeanException;
46 import javax.management.MBeanNotificationInfo;
47 import javax.management.MBeanRegistration;
48 import javax.management.MBeanServer;
49 import javax.management.MBeanServerDelegate;
50 import javax.management.MBeanServerNotification;
51 import javax.management.Notification;
52 import javax.management.NotificationBroadcasterSupport;
53 import javax.management.NotificationListener;
54 import javax.management.ObjectName;
55 import javax.management.ReflectionException;
56
57 /**
58 * The Relation Service is in charge of creating and deleting relation types
59 * and relations, of handling the consistency and of providing query
60 * mechanisms.
61 * <P>It implements the NotificationBroadcaster by extending
62 * NotificationBroadcasterSupport to send notifications when a relation is
63 * removed from it.
64 * <P>It implements the NotificationListener interface to be able to receive
65 * notifications concerning unregistration of MBeans referenced in relation
66 * roles and of relation MBeans.
67 * <P>It implements the MBeanRegistration interface to be able to retrieve
68 * its ObjectName and MBean Server.
69 *
70 * @since 1.5
71 */
72 public class RelationService extends NotificationBroadcasterSupport
73 implements RelationServiceMBean, MBeanRegistration, NotificationListener {
74
75 //
76 // Private members
77 //
78
79 // Map associating:
80 // <relation id> -> <RelationSupport object/ObjectName>
81 // depending if the relation has been created using createRelation()
82 // method (so internally handled) or is an MBean added as a relation by the
83 // user
84 private Map<String,Object> myRelId2ObjMap = new HashMap<String,Object>();
85
86 // Map associating:
87 // <relation id> -> <relation type name>
88 private Map<String,String> myRelId2RelTypeMap = new HashMap<String,String>();
89
90 // Map associating:
91 // <relation MBean Object Name> -> <relation id>
92 private Map<ObjectName,String> myRelMBeanObjName2RelIdMap =
93 new HashMap<ObjectName,String>();
94
95 // Map associating:
96 // <relation type name> -> <RelationType object>
97 private Map<String,RelationType> myRelType2ObjMap =
98 new HashMap<String,RelationType>();
99
100 // Map associating:
101 // <relation type name> -> ArrayList of <relation id>
102 // to list all the relations of a given type
103 private Map<String,List<String>> myRelType2RelIdsMap =
104 new HashMap<String,List<String>>();
105
106 // Map associating:
107 // <ObjectName> -> HashMap
108 // the value HashMap mapping:
109 // <relation id> -> ArrayList of <role name>
110 // to track where a given MBean is referenced.
111 private Map<ObjectName,Map<String,List<String>>>
112 myRefedMBeanObjName2RelIdsMap =
113 new HashMap<ObjectName,Map<String,List<String>>>();
114
115 // Flag to indicate if, when a notification is received for the
116 // unregistration of an MBean referenced in a relation, if an immediate
117 // "purge" of the relations (look for the relations no
118 // longer valid) has to be performed , or if that will be performed only
119 // when the purgeRelations method will be explicitly called.
120 // true is immediate purge.
121 private boolean myPurgeFlag = true;
122
123 // Internal counter to provide sequence numbers for notifications sent by:
124 // - the Relation Service
125 // - a relation handled by the Relation Service
126 private final AtomicLong atomicSeqNo = new AtomicLong();
127
128 // ObjectName used to register the Relation Service in the MBean Server
129 private ObjectName myObjName = null;
130
131 // MBean Server where the Relation Service is registered
132 private MBeanServer myMBeanServer = null;
133
134 // Filter registered in the MBean Server with the Relation Service to be
135 // informed of referenced MBean unregistrations
136 private MBeanServerNotificationFilter myUnregNtfFilter = null;
137
138 // List of unregistration notifications received (storage used if purge
139 // of relations when unregistering a referenced MBean is not immediate but
140 // on user request)
141 private List<MBeanServerNotification> myUnregNtfList =
142 new ArrayList<MBeanServerNotification>();
143
144 //
145 // Constructor
146 //
147
148 /**
149 * Constructor.
150 *
151 * @param immediatePurgeFlag flag to indicate when a notification is
152 * received for the unregistration of an MBean referenced in a relation, if
153 * an immediate "purge" of the relations (look for the relations no
154 * longer valid) has to be performed , or if that will be performed only
155 * when the purgeRelations method will be explicitly called.
156 * <P>true is immediate purge.
157 */
158 public RelationService(boolean immediatePurgeFlag) {
159
160 RELATION_LOGGER.entering(RelationService.class.getName(),
161 "RelationService");
162
163 setPurgeFlag(immediatePurgeFlag);
164
165 RELATION_LOGGER.exiting(RelationService.class.getName(),
166 "RelationService");
167 return;
168 }
169
170 /**
171 * Checks if the Relation Service is active.
172 * Current condition is that the Relation Service must be registered in the
173 * MBean Server
174 *
175 * @exception RelationServiceNotRegisteredException if it is not
176 * registered
177 */
178 public void isActive()
179 throws RelationServiceNotRegisteredException {
180 if (myMBeanServer == null) {
181 // MBean Server not set by preRegister(): relation service not
182 // registered
183 String excMsg =
184 "Relation Service not registered in the MBean Server.";
185 throw new RelationServiceNotRegisteredException(excMsg);
186 }
187 return;
188 }
189
190 //
191 // MBeanRegistration interface
192 //
193
194 // Pre-registration: retrieves its ObjectName and MBean Server
195 //
196 // No exception thrown.
197 public ObjectName preRegister(MBeanServer server,
198 ObjectName name)
199 throws Exception {
200
201 myMBeanServer = server;
202 myObjName = name;
203 return name;
204 }
205
206 // Post-registration: does nothing
207 public void postRegister(Boolean registrationDone) {
208 return;
209 }
210
211 // Pre-unregistration: does nothing
212 public void preDeregister()
213 throws Exception {
214 return;
215 }
216
217 // Post-unregistration: does nothing
218 public void postDeregister() {
219 return;
220 }
221
222 //
223 // Accessors
224 //
225
226 /**
227 * Returns the flag to indicate if when a notification is received for the
228 * unregistration of an MBean referenced in a relation, if an immediate
229 * "purge" of the relations (look for the relations no longer valid)
230 * has to be performed , or if that will be performed only when the
231 * purgeRelations method will be explicitly called.
232 * <P>true is immediate purge.
233 *
234 * @return true if purges are automatic.
235 *
236 * @see #setPurgeFlag
237 */
238 public boolean getPurgeFlag() {
239 return myPurgeFlag;
240 }
241
242 /**
243 * Sets the flag to indicate if when a notification is received for the
244 * unregistration of an MBean referenced in a relation, if an immediate
245 * "purge" of the relations (look for the relations no longer valid)
246 * has to be performed , or if that will be performed only when the
247 * purgeRelations method will be explicitly called.
248 * <P>true is immediate purge.
249 *
250 * @param purgeFlag flag
251 *
252 * @see #getPurgeFlag
253 */
254 public void setPurgeFlag(boolean purgeFlag) {
255
256 myPurgeFlag = purgeFlag;
257 return;
258 }
259
260 //
261 // Relation type handling
262 //
263
264 /**
265 * Creates a relation type (a RelationTypeSupport object) with given
266 * role infos (provided by the RoleInfo objects), and adds it in the
267 * Relation Service.
268 *
269 * @param relationTypeName name of the relation type
270 * @param roleInfoArray array of role infos
271 *
272 * @exception IllegalArgumentException if null parameter
273 * @exception InvalidRelationTypeException If:
274 * <P>- there is already a relation type with that name
275 * <P>- the same name has been used for two different role infos
276 * <P>- no role info provided
277 * <P>- one null role info provided
278 */
279 public void createRelationType(String relationTypeName,
280 RoleInfo[] roleInfoArray)
281 throws IllegalArgumentException,
282 InvalidRelationTypeException {
283
284 if (relationTypeName == null || roleInfoArray == null) {
285 String excMsg = "Invalid parameter.";
286 throw new IllegalArgumentException(excMsg);
287 }
288
289 RELATION_LOGGER.entering(RelationService.class.getName(),
290 "createRelationType", relationTypeName);
291
292 // Can throw an InvalidRelationTypeException
293 RelationType relType =
294 new RelationTypeSupport(relationTypeName, roleInfoArray);
295
296 addRelationTypeInt(relType);
297
298 RELATION_LOGGER.exiting(RelationService.class.getName(),
299 "createRelationType");
300 return;
301 }
302
303 /**
304 * Adds given object as a relation type. The object is expected to
305 * implement the RelationType interface.
306 *
307 * @param relationTypeObj relation type object (implementing the
308 * RelationType interface)
309 *
310 * @exception IllegalArgumentException if null parameter or if
311 * {@link RelationType#getRelationTypeName
312 * relationTypeObj.getRelationTypeName()} returns null.
313 * @exception InvalidRelationTypeException if:
314 * <P>- the same name has been used for two different roles
315 * <P>- no role info provided
316 * <P>- one null role info provided
317 * <P>- there is already a relation type with that name
318 */
319 public void addRelationType(RelationType relationTypeObj)
320 throws IllegalArgumentException,
321 InvalidRelationTypeException {
322
323 if (relationTypeObj == null) {
324 String excMsg = "Invalid parameter.";
325 throw new IllegalArgumentException(excMsg);
326 }
327
328 RELATION_LOGGER.entering(RelationService.class.getName(),
329 "addRelationType");
330
331 // Checks the role infos
332 List<RoleInfo> roleInfoList = relationTypeObj.getRoleInfos();
333 if (roleInfoList == null) {
334 String excMsg = "No role info provided.";
335 throw new InvalidRelationTypeException(excMsg);
336 }
337
338 RoleInfo[] roleInfoArray = new RoleInfo[roleInfoList.size()];
339 int i = 0;
340 for (RoleInfo currRoleInfo : roleInfoList) {
341 roleInfoArray[i] = currRoleInfo;
342 i++;
343 }
344 // Can throw InvalidRelationTypeException
345 RelationTypeSupport.checkRoleInfos(roleInfoArray);
346
347 addRelationTypeInt(relationTypeObj);
348
349 RELATION_LOGGER.exiting(RelationService.class.getName(),
350 "addRelationType");
351 return;
352 }
353
354 /**
355 * Retrieves names of all known relation types.
356 *
357 * @return ArrayList of relation type names (Strings)
358 */
359 public List<String> getAllRelationTypeNames() {
360 ArrayList<String> result;
361 synchronized(myRelType2ObjMap) {
362 result = new ArrayList<String>(myRelType2ObjMap.keySet());
363 }
364 return result;
365 }
366
367 /**
368 * Retrieves list of role infos (RoleInfo objects) of a given relation
369 * type.
370 *
371 * @param relationTypeName name of relation type
372 *
373 * @return ArrayList of RoleInfo.
374 *
375 * @exception IllegalArgumentException if null parameter
376 * @exception RelationTypeNotFoundException if there is no relation type
377 * with that name.
378 */
379 public List<RoleInfo> getRoleInfos(String relationTypeName)
380 throws IllegalArgumentException,
381 RelationTypeNotFoundException {
382
383 if (relationTypeName == null) {
384 String excMsg = "Invalid parameter.";
385 throw new IllegalArgumentException(excMsg);
386 }
387
388 RELATION_LOGGER.entering(RelationService.class.getName(),
389 "getRoleInfos", relationTypeName);
390
391 // Can throw a RelationTypeNotFoundException
392 RelationType relType = getRelationType(relationTypeName);
393
394 RELATION_LOGGER.exiting(RelationService.class.getName(),
395 "getRoleInfos");
396 return relType.getRoleInfos();
397 }
398
399 /**
400 * Retrieves role info for given role name of a given relation type.
401 *
402 * @param relationTypeName name of relation type
403 * @param roleInfoName name of role
404 *
405 * @return RoleInfo object.
406 *
407 * @exception IllegalArgumentException if null parameter
408 * @exception RelationTypeNotFoundException if the relation type is not
409 * known in the Relation Service
410 * @exception RoleInfoNotFoundException if the role is not part of the
411 * relation type.
412 */
413 public RoleInfo getRoleInfo(String relationTypeName,
414 String roleInfoName)
415 throws IllegalArgumentException,
416 RelationTypeNotFoundException,
417 RoleInfoNotFoundException {
418
419 if (relationTypeName == null || roleInfoName == null) {
420 String excMsg = "Invalid parameter.";
421 throw new IllegalArgumentException(excMsg);
422 }
423
424 RELATION_LOGGER.entering(RelationService.class.getName(),
425 "getRoleInfo", new Object[] {relationTypeName, roleInfoName});
426
427 // Can throw a RelationTypeNotFoundException
428 RelationType relType = getRelationType(relationTypeName);
429
430 // Can throw a RoleInfoNotFoundException
431 RoleInfo roleInfo = relType.getRoleInfo(roleInfoName);
432
433 RELATION_LOGGER.exiting(RelationService.class.getName(),
434 "getRoleInfo");
435 return roleInfo;
436 }
437
438 /**
439 * Removes given relation type from Relation Service.
440 * <P>The relation objects of that type will be removed from the
441 * Relation Service.
442 *
443 * @param relationTypeName name of the relation type to be removed
444 *
445 * @exception RelationServiceNotRegisteredException if the Relation
446 * Service is not registered in the MBean Server
447 * @exception IllegalArgumentException if null parameter
448 * @exception RelationTypeNotFoundException If there is no relation type
449 * with that name
450 */
451 public void removeRelationType(String relationTypeName)
452 throws RelationServiceNotRegisteredException,
453 IllegalArgumentException,
454 RelationTypeNotFoundException {
455
456 // Can throw RelationServiceNotRegisteredException
457 isActive();
458
459 if (relationTypeName == null) {
460 String excMsg = "Invalid parameter.";
461 throw new IllegalArgumentException(excMsg);
462 }
463
464 RELATION_LOGGER.entering(RelationService.class.getName(),
465 "removeRelationType", relationTypeName);
466
467 // Checks if the relation type to be removed exists
468 // Can throw a RelationTypeNotFoundException
469 RelationType relType = getRelationType(relationTypeName);
470
471 // Retrieves the relation ids for relations of that type
472 List<String> relIdList = null;
473 synchronized(myRelType2RelIdsMap) {
474 // Note: take a copy of the list as it is a part of a map that
475 // will be updated by removeRelation() below.
476 List<String> relIdList1 =
477 myRelType2RelIdsMap.get(relationTypeName);
478 if (relIdList1 != null) {
479 relIdList = new ArrayList<String>(relIdList1);
480 }
481 }
482
483 // Removes the relation type from all maps
484 synchronized(myRelType2ObjMap) {
485 myRelType2ObjMap.remove(relationTypeName);
486 }
487 synchronized(myRelType2RelIdsMap) {
488 myRelType2RelIdsMap.remove(relationTypeName);
489 }
490
491 // Removes all relations of that type
492 if (relIdList != null) {
493 for (String currRelId : relIdList) {
494 // Note: will remove it from myRelId2RelTypeMap :)
495 //
496 // Can throw RelationServiceNotRegisteredException (detected
497 // above)
498 // Shall not throw a RelationNotFoundException
499 try {
500 removeRelation(currRelId);
501 } catch (RelationNotFoundException exc1) {
502 throw new RuntimeException(exc1.getMessage());
503 }
504 }
505 }
506
507 RELATION_LOGGER.exiting(RelationService.class.getName(),
508 "removeRelationType");
509 return;
510 }
511
512 //
513 // Relation handling
514 //
515
516 /**
517 * Creates a simple relation (represented by a RelationSupport object) of
518 * given relation type, and adds it in the Relation Service.
519 * <P>Roles are initialized according to the role list provided in
520 * parameter. The ones not initialized in this way are set to an empty
521 * ArrayList of ObjectNames.
522 * <P>A RelationNotification, with type RELATION_BASIC_CREATION, is sent.
523 *
524 * @param relationId relation identifier, to identify uniquely the relation
525 * inside the Relation Service
526 * @param relationTypeName name of the relation type (has to be created
527 * in the Relation Service)
528 * @param roleList role list to initialize roles of the relation (can
529 * be null).
530 *
531 * @exception RelationServiceNotRegisteredException if the Relation
532 * Service is not registered in the MBean Server
533 * @exception IllegalArgumentException if null parameter, except the role
534 * list which can be null if no role initialization
535 * @exception RoleNotFoundException if a value is provided for a role
536 * that does not exist in the relation type
537 * @exception InvalidRelationIdException if relation id already used
538 * @exception RelationTypeNotFoundException if relation type not known in
539 * Relation Service
540 * @exception InvalidRoleValueException if:
541 * <P>- the same role name is used for two different roles
542 * <P>- the number of referenced MBeans in given value is less than
543 * expected minimum degree
544 * <P>- the number of referenced MBeans in provided value exceeds expected
545 * maximum degree
546 * <P>- one referenced MBean in the value is not an Object of the MBean
547 * class expected for that role
548 * <P>- an MBean provided for that role does not exist
549 */
550 public void createRelation(String relationId,
551 String relationTypeName,
552 RoleList roleList)
553 throws RelationServiceNotRegisteredException,
554 IllegalArgumentException,
555 RoleNotFoundException,
556 InvalidRelationIdException,
557 RelationTypeNotFoundException,
558 InvalidRoleValueException {
559
560 // Can throw RelationServiceNotRegisteredException
561 isActive();
562
563 if (relationId == null ||
564 relationTypeName == null) {
565 String excMsg = "Invalid parameter.";
566 throw new IllegalArgumentException(excMsg);
567 }
568
569 RELATION_LOGGER.entering(RelationService.class.getName(),
570 "createRelation",
571 new Object[] {relationId, relationTypeName, roleList});
572
573 // Creates RelationSupport object
574 // Can throw InvalidRoleValueException
575 RelationSupport relObj = new RelationSupport(relationId,
576 myObjName,
577 relationTypeName,
578 roleList);
579
580 // Adds relation object as a relation into the Relation Service
581 // Can throw RoleNotFoundException, InvalidRelationId,
582 // RelationTypeNotFoundException, InvalidRoleValueException
583 //
584 // Cannot throw MBeanException
585 addRelationInt(true,
586 relObj,
587 null,
588 relationId,
589 relationTypeName,
590 roleList);
591 RELATION_LOGGER.exiting(RelationService.class.getName(),
592 "createRelation");
593 return;
594 }
595
596 /**
597 * Adds an MBean created by the user (and registered by him in the MBean
598 * Server) as a relation in the Relation Service.
599 * <P>To be added as a relation, the MBean must conform to the
600 * following:
601 * <P>- implement the Relation interface
602 * <P>- have for RelationService ObjectName the ObjectName of current
603 * Relation Service
604 * <P>- have a relation id unique and unused in current Relation Service
605 * <P>- have for relation type a relation type created in the Relation
606 * Service
607 * <P>- have roles conforming to the role info provided in the relation
608 * type.
609 *
610 * @param relationObjectName ObjectName of the relation MBean to be added.
611 *
612 * @exception IllegalArgumentException if null parameter
613 * @exception RelationServiceNotRegisteredException if the Relation
614 * Service is not registered in the MBean Server
615 * @exception NoSuchMethodException If the MBean does not implement the
616 * Relation interface
617 * @exception InvalidRelationIdException if:
618 * <P>- no relation identifier in MBean
619 * <P>- the relation identifier is already used in the Relation Service
620 * @exception InstanceNotFoundException if the MBean for given ObjectName
621 * has not been registered
622 * @exception InvalidRelationServiceException if:
623 * <P>- no Relation Service name in MBean
624 * <P>- the Relation Service name in the MBean is not the one of the
625 * current Relation Service
626 * @exception RelationTypeNotFoundException if:
627 * <P>- no relation type name in MBean
628 * <P>- the relation type name in MBean does not correspond to a relation
629 * type created in the Relation Service
630 * @exception InvalidRoleValueException if:
631 * <P>- the number of referenced MBeans in a role is less than
632 * expected minimum degree
633 * <P>- the number of referenced MBeans in a role exceeds expected
634 * maximum degree
635 * <P>- one referenced MBean in the value is not an Object of the MBean
636 * class expected for that role
637 * <P>- an MBean provided for a role does not exist
638 * @exception RoleNotFoundException if a value is provided for a role
639 * that does not exist in the relation type
640 */
641 public void addRelation(ObjectName relationObjectName)
642 throws IllegalArgumentException,
643 RelationServiceNotRegisteredException,
644 NoSuchMethodException,
645 InvalidRelationIdException,
646 InstanceNotFoundException,
647 InvalidRelationServiceException,
648 RelationTypeNotFoundException,
649 RoleNotFoundException,
650 InvalidRoleValueException {
651
652 if (relationObjectName == null) {
653 String excMsg = "Invalid parameter.";
654 throw new IllegalArgumentException(excMsg);
655 }
656
657 RELATION_LOGGER.entering(RelationService.class.getName(),
658 "addRelation", relationObjectName);
659
660 // Can throw RelationServiceNotRegisteredException
661 isActive();
662
663 // Checks that the relation MBean implements the Relation interface.
664 // It will also check that the provided ObjectName corresponds to a
665 // registered MBean (else will throw an InstanceNotFoundException)
666 if ((!(myMBeanServer.isInstanceOf(relationObjectName, "javax.management.relation.Relation")))) {
667 String excMsg = "This MBean does not implement the Relation interface.";
668 throw new NoSuchMethodException(excMsg);
669 }
670 // Checks there is a relation id in the relation MBean (its uniqueness
671 // is checked in addRelationInt())
672 // Can throw InstanceNotFoundException (but detected above)
673 // No MBeanException as no exception raised by this method, and no
674 // ReflectionException
675 String relId;
676 try {
677 relId = (String)(myMBeanServer.getAttribute(relationObjectName,
678 "RelationId"));
679
680 } catch (MBeanException exc1) {
681 throw new RuntimeException(
682 (exc1.getTargetException()).getMessage());
683 } catch (ReflectionException exc2) {
684 throw new RuntimeException(exc2.getMessage());
685 } catch (AttributeNotFoundException exc3) {
686 throw new RuntimeException(exc3.getMessage());
687 }
688
689 if (relId == null) {
690 String excMsg = "This MBean does not provide a relation id.";
691 throw new InvalidRelationIdException(excMsg);
692 }
693 // Checks that the Relation Service where the relation MBean is
694 // expected to be added is the current one
695 // Can throw InstanceNotFoundException (but detected above)
696 // No MBeanException as no exception raised by this method, no
697 // ReflectionException
698 ObjectName relServObjName;
699 try {
700 relServObjName = (ObjectName)
701 (myMBeanServer.getAttribute(relationObjectName,
702 "RelationServiceName"));
703
704 } catch (MBeanException exc1) {
705 throw new RuntimeException(
706 (exc1.getTargetException()).getMessage());
707 } catch (ReflectionException exc2) {
708 throw new RuntimeException(exc2.getMessage());
709 } catch (AttributeNotFoundException exc3) {
710 throw new RuntimeException(exc3.getMessage());
711 }
712
713 boolean badRelServFlag = false;
714 if (relServObjName == null) {
715 badRelServFlag = true;
716
717 } else if (!(relServObjName.equals(myObjName))) {
718 badRelServFlag = true;
719 }
720 if (badRelServFlag) {
721 String excMsg = "The Relation Service referenced in the MBean is not the current one.";
722 throw new InvalidRelationServiceException(excMsg);
723 }
724 // Checks that a relation type has been specified for the relation
725 // Can throw InstanceNotFoundException (but detected above)
726 // No MBeanException as no exception raised by this method, no
727 // ReflectionException
728 String relTypeName;
729 try {
730 relTypeName = (String)(myMBeanServer.getAttribute(relationObjectName,
731 "RelationTypeName"));
732
733 } catch (MBeanException exc1) {
734 throw new RuntimeException(
735 (exc1.getTargetException()).getMessage());
736 }catch (ReflectionException exc2) {
737 throw new RuntimeException(exc2.getMessage());
738 } catch (AttributeNotFoundException exc3) {
739 throw new RuntimeException(exc3.getMessage());
740 }
741 if (relTypeName == null) {
742 String excMsg = "No relation type provided.";
743 throw new RelationTypeNotFoundException(excMsg);
744 }
745 // Retrieves all roles without considering read mode
746 // Can throw InstanceNotFoundException (but detected above)
747 // No MBeanException as no exception raised by this method, no
748 // ReflectionException
749 RoleList roleList;
750 try {
751 roleList = (RoleList)(myMBeanServer.invoke(relationObjectName,
752 "retrieveAllRoles",
753 null,
754 null));
755 } catch (MBeanException exc1) {
756 throw new RuntimeException(
757 (exc1.getTargetException()).getMessage());
758 } catch (ReflectionException exc2) {
759 throw new RuntimeException(exc2.getMessage());
760 }
761
762 // Can throw RoleNotFoundException, InvalidRelationIdException,
763 // RelationTypeNotFoundException, InvalidRoleValueException
764 addRelationInt(false,
765 null,
766 relationObjectName,
767 relId,
768 relTypeName,
769 roleList);
770 // Adds relation MBean ObjectName in map
771 synchronized(myRelMBeanObjName2RelIdMap) {
772 myRelMBeanObjName2RelIdMap.put(relationObjectName, relId);
773 }
774
775 // Updates flag to specify that the relation is managed by the Relation
776 // Service
777 // This flag and setter are inherited from RelationSupport and not parts
778 // of the Relation interface, so may be not supported.
779 try {
780 myMBeanServer.setAttribute(relationObjectName,
781 new Attribute(
782 "RelationServiceManagementFlag",
783 Boolean.TRUE));
784 } catch (Exception exc) {
785 // OK : The flag is not supported.
786 }
787
788 // Updates listener information to received notification for
789 // unregistration of this MBean
790 List<ObjectName> newRefList = new ArrayList<ObjectName>();
791 newRefList.add(relationObjectName);
792 updateUnregistrationListener(newRefList, null);
793
794 RELATION_LOGGER.exiting(RelationService.class.getName(),
795 "addRelation");
796 return;
797 }
798
799 /**
800 * If the relation is represented by an MBean (created by the user and
801 * added as a relation in the Relation Service), returns the ObjectName of
802 * the MBean.
803 *
804 * @param relationId relation id identifying the relation
805 *
806 * @return ObjectName of the corresponding relation MBean, or null if
807 * the relation is not an MBean.
808 *
809 * @exception IllegalArgumentException if null parameter
810 * @exception RelationNotFoundException there is no relation associated
811 * to that id
812 */
813 public ObjectName isRelationMBean(String relationId)
814 throws IllegalArgumentException,
815 RelationNotFoundException{
816
817 if (relationId == null) {
818 String excMsg = "Invalid parameter.";
819 throw new IllegalArgumentException(excMsg);
820 }
821
822 RELATION_LOGGER.entering(RelationService.class.getName(),
823 "isRelationMBean", relationId);
824
825 // Can throw RelationNotFoundException
826 Object result = getRelation(relationId);
827 if (result instanceof ObjectName) {
828 return ((ObjectName)result);
829 } else {
830 return null;
831 }
832 }
833
834 /**
835 * Returns the relation id associated to the given ObjectName if the
836 * MBean has been added as a relation in the Relation Service.
837 *
838 * @param objectName ObjectName of supposed relation
839 *
840 * @return relation id (String) or null (if the ObjectName is not a
841 * relation handled by the Relation Service)
842 *
843 * @exception IllegalArgumentException if null parameter
844 */
845 public String isRelation(ObjectName objectName)
846 throws IllegalArgumentException {
847
848 if (objectName == null) {
849 String excMsg = "Invalid parameter.";
850 throw new IllegalArgumentException(excMsg);
851 }
852
853 RELATION_LOGGER.entering(RelationService.class.getName(),
854 "isRelation", objectName);
855
856 String result = null;
857 synchronized(myRelMBeanObjName2RelIdMap) {
858 String relId = myRelMBeanObjName2RelIdMap.get(objectName);
859 if (relId != null) {
860 result = relId;
861 }
862 }
863 return result;
864 }
865
866 /**
867 * Checks if there is a relation identified in Relation Service with given
868 * relation id.
869 *
870 * @param relationId relation id identifying the relation
871 *
872 * @return boolean: true if there is a relation, false else
873 *
874 * @exception IllegalArgumentException if null parameter
875 */
876 public Boolean hasRelation(String relationId)
877 throws IllegalArgumentException {
878
879 if (relationId == null) {
880 String excMsg = "Invalid parameter.";
881 throw new IllegalArgumentException(excMsg);
882 }
883
884 RELATION_LOGGER.entering(RelationService.class.getName(),
885 "hasRelation", relationId);
886
887 try {
888 // Can throw RelationNotFoundException
889 Object result = getRelation(relationId);
890 return true;
891 } catch (RelationNotFoundException exc) {
892 return false;
893 }
894 }
895
896 /**
897 * Returns all the relation ids for all the relations handled by the
898 * Relation Service.
899 *
900 * @return ArrayList of String
901 */
902 public List<String> getAllRelationIds() {
903 List<String> result;
904 synchronized(myRelId2ObjMap) {
905 result = new ArrayList<String>(myRelId2ObjMap.keySet());
906 }
907 return result;
908 }
909
910 /**
911 * Checks if given Role can be read in a relation of the given type.
912 *
913 * @param roleName name of role to be checked
914 * @param relationTypeName name of the relation type
915 *
916 * @return an Integer wrapping an integer corresponding to possible
917 * problems represented as constants in RoleUnresolved:
918 * <P>- 0 if role can be read
919 * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME
920 * <P>- integer corresponding to RoleStatus.ROLE_NOT_READABLE
921 *
922 * @exception IllegalArgumentException if null parameter
923 * @exception RelationTypeNotFoundException if the relation type is not
924 * known in the Relation Service
925 */
926 public Integer checkRoleReading(String roleName,
927 String relationTypeName)
928 throws IllegalArgumentException,
929 RelationTypeNotFoundException {
930
931 if (roleName == null || relationTypeName == null) {
932 String excMsg = "Invalid parameter.";
933 throw new IllegalArgumentException(excMsg);
934 }
935
936 RELATION_LOGGER.entering(RelationService.class.getName(),
937 "checkRoleReading", new Object[] {roleName, relationTypeName});
938
939 Integer result;
940
941 // Can throw a RelationTypeNotFoundException
942 RelationType relType = getRelationType(relationTypeName);
943
944 try {
945 // Can throw a RoleInfoNotFoundException to be transformed into
946 // returned value RoleStatus.NO_ROLE_WITH_NAME
947 RoleInfo roleInfo = relType.getRoleInfo(roleName);
948
949 result = checkRoleInt(1,
950 roleName,
951 null,
952 roleInfo,
953 false);
954
955 } catch (RoleInfoNotFoundException exc) {
956 result = Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME);
957 }
958
959 RELATION_LOGGER.exiting(RelationService.class.getName(),
960 "checkRoleReading");
961 return result;
962 }
963
964 /**
965 * Checks if given Role can be set in a relation of given type.
966 *
967 * @param role role to be checked
968 * @param relationTypeName name of relation type
969 * @param initFlag flag to specify that the checking is done for the
970 * initialization of a role, write access shall not be verified.
971 *
972 * @return an Integer wrapping an integer corresponding to possible
973 * problems represented as constants in RoleUnresolved:
974 * <P>- 0 if role can be set
975 * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME
976 * <P>- integer for RoleStatus.ROLE_NOT_WRITABLE
977 * <P>- integer for RoleStatus.LESS_THAN_MIN_ROLE_DEGREE
978 * <P>- integer for RoleStatus.MORE_THAN_MAX_ROLE_DEGREE
979 * <P>- integer for RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS
980 * <P>- integer for RoleStatus.REF_MBEAN_NOT_REGISTERED
981 *
982 * @exception IllegalArgumentException if null parameter
983 * @exception RelationTypeNotFoundException if unknown relation type
984 */
985 public Integer checkRoleWriting(Role role,
986 String relationTypeName,
987 Boolean initFlag)
988 throws IllegalArgumentException,
989 RelationTypeNotFoundException {
990
991 if (role == null ||
992 relationTypeName == null ||
993 initFlag == null) {
994 String excMsg = "Invalid parameter.";
995 throw new IllegalArgumentException(excMsg);
996 }
997
998 RELATION_LOGGER.entering(RelationService.class.getName(),
999 "checkRoleWriting",
1000 new Object[] {role, relationTypeName, initFlag});
1001
1002 // Can throw a RelationTypeNotFoundException
1003 RelationType relType = getRelationType(relationTypeName);
1004
1005 String roleName = role.getRoleName();
1006 List<ObjectName> roleValue = role.getRoleValue();
1007 boolean writeChkFlag = true;
1008 if (initFlag.booleanValue()) {
1009 writeChkFlag = false;
1010 }
1011
1012 RoleInfo roleInfo;
1013 try {
1014 roleInfo = relType.getRoleInfo(roleName);
1015 } catch (RoleInfoNotFoundException exc) {
1016 RELATION_LOGGER.exiting(RelationService.class.getName(),
1017 "checkRoleWriting");
1018 return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME);
1019 }
1020
1021 Integer result = checkRoleInt(2,
1022 roleName,
1023 roleValue,
1024 roleInfo,
1025 writeChkFlag);
1026
1027 RELATION_LOGGER.exiting(RelationService.class.getName(),
1028 "checkRoleWriting");
1029 return result;
1030 }
1031
1032 /**
1033 * Sends a notification (RelationNotification) for a relation creation.
1034 * The notification type is:
1035 * <P>- RelationNotification.RELATION_BASIC_CREATION if the relation is an
1036 * object internal to the Relation Service
1037 * <P>- RelationNotification.RELATION_MBEAN_CREATION if the relation is a
1038 * MBean added as a relation.
1039 * <P>The source object is the Relation Service itself.
1040 * <P>It is called in Relation Service createRelation() and
1041 * addRelation() methods.
1042 *
1043 * @param relationId relation identifier of the updated relation
1044 *
1045 * @exception IllegalArgumentException if null parameter
1046 * @exception RelationNotFoundException if there is no relation for given
1047 * relation id
1048 */
1049 public void sendRelationCreationNotification(String relationId)
1050 throws IllegalArgumentException,
1051 RelationNotFoundException {
1052
1053 if (relationId == null) {
1054 String excMsg = "Invalid parameter.";
1055 throw new IllegalArgumentException(excMsg);
1056 }
1057
1058 RELATION_LOGGER.entering(RelationService.class.getName(),
1059 "sendRelationCreationNotification", relationId);
1060
1061 // Message
1062 StringBuilder ntfMsg = new StringBuilder("Creation of relation ");
1063 ntfMsg.append(relationId);
1064
1065 // Can throw RelationNotFoundException
1066 sendNotificationInt(1,
1067 ntfMsg.toString(),
1068 relationId,
1069 null,
1070 null,
1071 null,
1072 null);
1073
1074 RELATION_LOGGER.exiting(RelationService.class.getName(),
1075 "sendRelationCreationNotification");
1076 return;
1077 }
1078
1079 /**
1080 * Sends a notification (RelationNotification) for a role update in the
1081 * given relation. The notification type is:
1082 * <P>- RelationNotification.RELATION_BASIC_UPDATE if the relation is an
1083 * object internal to the Relation Service
1084 * <P>- RelationNotification.RELATION_MBEAN_UPDATE if the relation is a
1085 * MBean added as a relation.
1086 * <P>The source object is the Relation Service itself.
1087 * <P>It is called in relation MBean setRole() (for given role) and
1088 * setRoles() (for each role) methods (implementation provided in
1089 * RelationSupport class).
1090 * <P>It is also called in Relation Service setRole() (for given role) and
1091 * setRoles() (for each role) methods.
1092 *
1093 * @param relationId relation identifier of the updated relation
1094 * @param newRole new role (name and new value)
1095 * @param oldValue old role value (List of ObjectName objects)
1096 *
1097 * @exception IllegalArgumentException if null parameter
1098 * @exception RelationNotFoundException if there is no relation for given
1099 * relation id
1100 */
1101 public void sendRoleUpdateNotification(String relationId,
1102 Role newRole,
1103 List<ObjectName> oldValue)
1104 throws IllegalArgumentException,
1105 RelationNotFoundException {
1106
1107 if (relationId == null ||
1108 newRole == null ||
1109 oldValue == null) {
1110 String excMsg = "Invalid parameter.";
1111 throw new IllegalArgumentException(excMsg);
1112 }
1113
1114 if (!(oldValue instanceof ArrayList))
1115 oldValue = new ArrayList<ObjectName>(oldValue);
1116
1117 RELATION_LOGGER.entering(RelationService.class.getName(),
1118 "sendRoleUpdateNotification",
1119 new Object[] {relationId, newRole, oldValue});
1120
1121 String roleName = newRole.getRoleName();
1122 List<ObjectName> newRoleVal = newRole.getRoleValue();
1123
1124 // Message
1125 String newRoleValString = Role.roleValueToString(newRoleVal);
1126 String oldRoleValString = Role.roleValueToString(oldValue);
1127 StringBuilder ntfMsg = new StringBuilder("Value of role ");
1128 ntfMsg.append(roleName);
1129 ntfMsg.append(" has changed\nOld value:\n");
1130 ntfMsg.append(oldRoleValString);
1131 ntfMsg.append("\nNew value:\n");
1132 ntfMsg.append(newRoleValString);
1133
1134 // Can throw a RelationNotFoundException
1135 sendNotificationInt(2,
1136 ntfMsg.toString(),
1137 relationId,
1138 null,
1139 roleName,
1140 newRoleVal,
1141 oldValue);
1142
1143 RELATION_LOGGER.exiting(RelationService.class.getName(),
1144 "sendRoleUpdateNotification");
1145 }
1146
1147 /**
1148 * Sends a notification (RelationNotification) for a relation removal.
1149 * The notification type is:
1150 * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation is an
1151 * object internal to the Relation Service
1152 * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is a
1153 * MBean added as a relation.
1154 * <P>The source object is the Relation Service itself.
1155 * <P>It is called in Relation Service removeRelation() method.
1156 *
1157 * @param relationId relation identifier of the updated relation
1158 * @param unregMBeanList List of ObjectNames of MBeans expected
1159 * to be unregistered due to relation removal (can be null)
1160 *
1161 * @exception IllegalArgumentException if null parameter
1162 * @exception RelationNotFoundException if there is no relation for given
1163 * relation id
1164 */
1165 public void sendRelationRemovalNotification(String relationId,
1166 List<ObjectName> unregMBeanList)
1167 throws IllegalArgumentException,
1168 RelationNotFoundException {
1169
1170 if (relationId == null) {
1171 String excMsg = "Invalid parameter";
1172 throw new IllegalArgumentException(excMsg);
1173 }
1174
1175 RELATION_LOGGER.entering(RelationService.class.getName(),
1176 "sendRelationRemovalNotification",
1177 new Object[] {relationId, unregMBeanList});
1178
1179 // Can throw RelationNotFoundException
1180 sendNotificationInt(3,
1181 "Removal of relation " + relationId,
1182 relationId,
1183 unregMBeanList,
1184 null,
1185 null,
1186 null);
1187
1188
1189 RELATION_LOGGER.exiting(RelationService.class.getName(),
1190 "sendRelationRemovalNotification");
1191 return;
1192 }
1193
1194 /**
1195 * Handles update of the Relation Service role map for the update of given
1196 * role in given relation.
1197 * <P>It is called in relation MBean setRole() (for given role) and
1198 * setRoles() (for each role) methods (implementation provided in
1199 * RelationSupport class).
1200 * <P>It is also called in Relation Service setRole() (for given role) and
1201 * setRoles() (for each role) methods.
1202 * <P>To allow the Relation Service to maintain the consistency (in case
1203 * of MBean unregistration) and to be able to perform queries, this method
1204 * must be called when a role is updated.
1205 *
1206 * @param relationId relation identifier of the updated relation
1207 * @param newRole new role (name and new value)
1208 * @param oldValue old role value (List of ObjectName objects)
1209 *
1210 * @exception IllegalArgumentException if null parameter
1211 * @exception RelationServiceNotRegisteredException if the Relation
1212 * Service is not registered in the MBean Server
1213 * @exception RelationNotFoundException if no relation for given id.
1214 */
1215 public void updateRoleMap(String relationId,
1216 Role newRole,
1217 List<ObjectName> oldValue)
1218 throws IllegalArgumentException,
1219 RelationServiceNotRegisteredException,
1220 RelationNotFoundException {
1221
1222 if (relationId == null ||
1223 newRole == null ||
1224 oldValue == null) {
1225 String excMsg = "Invalid parameter.";
1226 throw new IllegalArgumentException(excMsg);
1227 }
1228
1229 RELATION_LOGGER.entering(RelationService.class.getName(),
1230 "updateRoleMap", new Object[] {relationId, newRole, oldValue});
1231
1232 // Can throw RelationServiceNotRegisteredException
1233 isActive();
1234
1235 // Verifies the relation has been added in the Relation Service
1236 // Can throw a RelationNotFoundException
1237 Object result = getRelation(relationId);
1238
1239 String roleName = newRole.getRoleName();
1240 List<ObjectName> newRoleValue = newRole.getRoleValue();
1241 // Note: no need to test if oldValue not null before cloning,
1242 // tested above.
1243 List<ObjectName> oldRoleValue =
1244 new ArrayList<ObjectName>(oldValue);
1245
1246 // List of ObjectNames of new referenced MBeans
1247 List<ObjectName> newRefList = new ArrayList<ObjectName>();
1248
1249 for (ObjectName currObjName : newRoleValue) {
1250
1251 // Checks if this ObjectName was already present in old value
1252 // Note: use copy (oldRoleValue) instead of original
1253 // oldValue to speed up, as oldRoleValue is decreased
1254 // by removing unchanged references :)
1255 int currObjNamePos = oldRoleValue.indexOf(currObjName);
1256
1257 if (currObjNamePos == -1) {
1258 // New reference to an ObjectName
1259
1260 // Stores this reference into map
1261 // Returns true if new reference, false if MBean already
1262 // referenced
1263 boolean isNewFlag = addNewMBeanReference(currObjName,
1264 relationId,
1265 roleName);
1266
1267 if (isNewFlag) {
1268 // Adds it into list of new reference
1269 newRefList.add(currObjName);
1270 }
1271
1272 } else {
1273 // MBean was already referenced in old value
1274
1275 // Removes it from old value (local list) to ignore it when
1276 // looking for remove MBean references
1277 oldRoleValue.remove(currObjNamePos);
1278 }
1279 }
1280
1281 // List of ObjectNames of MBeans no longer referenced
1282 List<ObjectName> obsRefList = new ArrayList<ObjectName>();
1283
1284 // Each ObjectName remaining in oldRoleValue is an ObjectName no longer
1285 // referenced in new value
1286 for (ObjectName currObjName : oldRoleValue) {
1287 // Removes MBean reference from map
1288 // Returns true if the MBean is no longer referenced in any
1289 // relation
1290 boolean noLongerRefFlag = removeMBeanReference(currObjName,
1291 relationId,
1292 roleName,
1293 false);
1294
1295 if (noLongerRefFlag) {
1296 // Adds it into list of references to be removed
1297 obsRefList.add(currObjName);
1298 }
1299 }
1300
1301 // To avoid having one listener per ObjectName of referenced MBean,
1302 // and to increase performances, there is only one listener recording
1303 // all ObjectNames of interest
1304 updateUnregistrationListener(newRefList, obsRefList);
1305
1306 RELATION_LOGGER.exiting(RelationService.class.getName(),
1307 "updateRoleMap");
1308 return;
1309 }
1310
1311 /**
1312 * Removes given relation from the Relation Service.
1313 * <P>A RelationNotification notification is sent, its type being:
1314 * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation was
1315 * only internal to the Relation Service
1316 * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is
1317 * registered as an MBean.
1318 * <P>For MBeans referenced in such relation, nothing will be done,
1319 *
1320 * @param relationId relation id of the relation to be removed
1321 *
1322 * @exception RelationServiceNotRegisteredException if the Relation
1323 * Service is not registered in the MBean Server
1324 * @exception IllegalArgumentException if null parameter
1325 * @exception RelationNotFoundException if no relation corresponding to
1326 * given relation id
1327 */
1328 public void removeRelation(String relationId)
1329 throws RelationServiceNotRegisteredException,
1330 IllegalArgumentException,
1331 RelationNotFoundException {
1332
1333 // Can throw RelationServiceNotRegisteredException
1334 isActive();
1335
1336 if (relationId == null) {
1337 String excMsg = "Invalid parameter.";
1338 throw new IllegalArgumentException(excMsg);
1339 }
1340
1341 RELATION_LOGGER.entering(RelationService.class.getName(),
1342 "removeRelation", relationId);
1343
1344 // Checks there is a relation with this id
1345 // Can throw RelationNotFoundException
1346 Object result = getRelation(relationId);
1347
1348 // Removes it from listener filter
1349 if (result instanceof ObjectName) {
1350 List<ObjectName> obsRefList = new ArrayList<ObjectName>();
1351 obsRefList.add((ObjectName)result);
1352 // Can throw a RelationServiceNotRegisteredException
1353 updateUnregistrationListener(null, obsRefList);
1354 }
1355
1356 // Sends a notification
1357 // Note: has to be done FIRST as needs the relation to be still in the
1358 // Relation Service
1359 // No RelationNotFoundException as checked above
1360
1361 // Revisit [cebro] Handle CIM "Delete" and "IfDeleted" qualifiers:
1362 // deleting the relation can mean to delete referenced MBeans. In
1363 // that case, MBeans to be unregistered are put in a list sent along
1364 // with the notification below
1365
1366 // Can throw a RelationNotFoundException (but detected above)
1367 sendRelationRemovalNotification(relationId, null);
1368
1369 // Removes the relation from various internal maps
1370
1371 // - MBean reference map
1372 // Retrieves the MBeans referenced in this relation
1373 // Note: here we cannot use removeMBeanReference() because it would
1374 // require to know the MBeans referenced in the relation. For
1375 // that it would be necessary to call 'getReferencedMBeans()'
1376 // on the relation itself. Ok if it is an internal one, but if
1377 // it is an MBean, it is possible it is already unregistered, so
1378 // not available through the MBean Server.
1379 List<ObjectName> refMBeanList = new ArrayList<ObjectName>();
1380 // List of MBeans no longer referenced in any relation, to be
1381 // removed fom the map
1382 List<ObjectName> nonRefObjNameList = new ArrayList<ObjectName>();
1383
1384 synchronized(myRefedMBeanObjName2RelIdsMap) {
1385
1386 for (ObjectName currRefObjName :
1387 myRefedMBeanObjName2RelIdsMap.keySet()) {
1388
1389 // Retrieves relations where the MBean is referenced
1390 Map<String,List<String>> relIdMap =
1391 myRefedMBeanObjName2RelIdsMap.get(currRefObjName);
1392
1393 if (relIdMap.containsKey(relationId)) {
1394 relIdMap.remove(relationId);
1395 refMBeanList.add(currRefObjName);
1396 }
1397
1398 if (relIdMap.isEmpty()) {
1399 // MBean no longer referenced
1400 // Note: do not remove it here because pointed by the
1401 // iterator!
1402 nonRefObjNameList.add(currRefObjName);
1403 }
1404 }
1405
1406 // Cleans MBean reference map by removing MBeans no longer
1407 // referenced
1408 for (ObjectName currRefObjName : nonRefObjNameList) {
1409 myRefedMBeanObjName2RelIdsMap.remove(currRefObjName);
1410 }
1411 }
1412
1413 // - Relation id to object map
1414 synchronized(myRelId2ObjMap) {
1415 myRelId2ObjMap.remove(relationId);
1416 }
1417
1418 if (result instanceof ObjectName) {
1419 // - ObjectName to relation id map
1420 synchronized(myRelMBeanObjName2RelIdMap) {
1421 myRelMBeanObjName2RelIdMap.remove((ObjectName)result);
1422 }
1423 }
1424
1425 // Relation id to relation type name map
1426 // First retrieves the relation type name
1427 String relTypeName;
1428 synchronized(myRelId2RelTypeMap) {
1429 relTypeName = myRelId2RelTypeMap.get(relationId);
1430 myRelId2RelTypeMap.remove(relationId);
1431 }
1432 // - Relation type name to relation id map
1433 synchronized(myRelType2RelIdsMap) {
1434 List<String> relIdList = myRelType2RelIdsMap.get(relTypeName);
1435 if (relIdList != null) {
1436 // Can be null if called from removeRelationType()
1437 relIdList.remove(relationId);
1438 if (relIdList.isEmpty()) {
1439 // No other relation of that type
1440 myRelType2RelIdsMap.remove(relTypeName);
1441 }
1442 }
1443 }
1444
1445 RELATION_LOGGER.exiting(RelationService.class.getName(),
1446 "removeRelation");
1447 return;
1448 }
1449
1450 /**
1451 * Purges the relations.
1452 *
1453 * <P>Depending on the purgeFlag value, this method is either called
1454 * automatically when a notification is received for the unregistration of
1455 * an MBean referenced in a relation (if the flag is set to true), or not
1456 * (if the flag is set to false).
1457 * <P>In that case it is up to the user to call it to maintain the
1458 * consistency of the relations. To be kept in mind that if an MBean is
1459 * unregistered and the purge not done immediately, if the ObjectName is
1460 * reused and assigned to another MBean referenced in a relation, calling
1461 * manually this purgeRelations() method will cause trouble, as will
1462 * consider the ObjectName as corresponding to the unregistered MBean, not
1463 * seeing the new one.
1464 *
1465 * <P>The behavior depends on the cardinality of the role where the
1466 * unregistered MBean is referenced:
1467 * <P>- if removing one MBean reference in the role makes its number of
1468 * references less than the minimum degree, the relation has to be removed.
1469 * <P>- if the remaining number of references after removing the MBean
1470 * reference is still in the cardinality range, keep the relation and
1471 * update it calling its handleMBeanUnregistration() callback.
1472 *
1473 * @exception RelationServiceNotRegisteredException if the Relation
1474 * Service is not registered in the MBean Server.
1475 */
1476 public void purgeRelations()
1477 throws RelationServiceNotRegisteredException {
1478
1479 RELATION_LOGGER.entering(RelationService.class.getName(),
1480 "purgeRelations");
1481
1482 // Can throw RelationServiceNotRegisteredException
1483 isActive();
1484
1485 // Revisit [cebro] Handle the CIM "Delete" and "IfDeleted" qualifier:
1486 // if the unregistered MBean has the "IfDeleted" qualifier,
1487 // possible that the relation itself or other referenced MBeans
1488 // have to be removed (then a notification would have to be sent
1489 // to inform that they should be unregistered.
1490
1491
1492 // Clones the list of notifications to be able to still receive new
1493 // notifications while proceeding those ones
1494 List<MBeanServerNotification> localUnregNtfList;
1495 synchronized(myUnregNtfList) {
1496 localUnregNtfList =
1497 new ArrayList<MBeanServerNotification>(myUnregNtfList);
1498 // Resets list
1499 myUnregNtfList = new ArrayList<MBeanServerNotification>();
1500 }
1501
1502
1503 // Updates the listener filter to avoid receiving notifications for
1504 // those MBeans again
1505 // Makes also a local "myRefedMBeanObjName2RelIdsMap" map, mapping
1506 // ObjectName -> relId -> roles, to remove the MBean from the global
1507 // map
1508 // List of references to be removed from the listener filter
1509 List<ObjectName> obsRefList = new ArrayList<ObjectName>();
1510 // Map including ObjectNames for unregistered MBeans, with
1511 // referencing relation ids and roles
1512 Map<ObjectName,Map<String,List<String>>> localMBean2RelIdMap =
1513 new HashMap<ObjectName,Map<String,List<String>>>();
1514
1515 synchronized(myRefedMBeanObjName2RelIdsMap) {
1516 for (MBeanServerNotification currNtf : localUnregNtfList) {
1517
1518 ObjectName unregMBeanName = currNtf.getMBeanName();
1519
1520 // Adds the unregsitered MBean in the list of references to
1521 // remove from the listener filter
1522 obsRefList.add(unregMBeanName);
1523
1524 // Retrieves the associated map of relation ids and roles
1525 Map<String,List<String>> relIdMap =
1526 myRefedMBeanObjName2RelIdsMap.get(unregMBeanName);
1527 localMBean2RelIdMap.put(unregMBeanName, relIdMap);
1528
1529 myRefedMBeanObjName2RelIdsMap.remove(unregMBeanName);
1530 }
1531 }
1532
1533 // Updates the listener
1534 // Can throw RelationServiceNotRegisteredException
1535 updateUnregistrationListener(null, obsRefList);
1536
1537 for (MBeanServerNotification currNtf : localUnregNtfList) {
1538
1539 ObjectName unregMBeanName = currNtf.getMBeanName();
1540
1541 // Retrieves the relations where the MBean is referenced
1542 Map<String,List<String>> localRelIdMap =
1543 localMBean2RelIdMap.get(unregMBeanName);
1544
1545 // List of relation ids where the unregistered MBean is
1546 // referenced
1547 for (Map.Entry<String,List<String>> currRel :
1548 localRelIdMap.entrySet()) {
1549 final String currRelId = currRel.getKey();
1550 // List of roles of the relation where the MBean is
1551 // referenced
1552 List<String> localRoleNameList = currRel.getValue();
1553
1554 // Checks if the relation has to be removed or not,
1555 // regarding expected minimum role cardinality and current
1556 // number of references after removal of the current one
1557 // If the relation is kept, calls
1558 // handleMBeanUnregistration() callback of the relation to
1559 // update it
1560 //
1561 // Can throw RelationServiceNotRegisteredException
1562 //
1563 // Shall not throw RelationNotFoundException,
1564 // RoleNotFoundException, MBeanException
1565 try {
1566 handleReferenceUnregistration(currRelId,
1567 unregMBeanName,
1568 localRoleNameList);
1569 } catch (RelationNotFoundException exc1) {
1570 throw new RuntimeException(exc1.getMessage());
1571 } catch (RoleNotFoundException exc2) {
1572 throw new RuntimeException(exc2.getMessage());
1573 }
1574 }
1575 }
1576
1577 RELATION_LOGGER.exiting(RelationService.class.getName(),
1578 "purgeRelations");
1579 return;
1580 }
1581
1582 /**
1583 * Retrieves the relations where a given MBean is referenced.
1584 * <P>This corresponds to the CIM "References" and "ReferenceNames"
1585 * operations.
1586 *
1587 * @param mbeanName ObjectName of MBean
1588 * @param relationTypeName can be null; if specified, only the relations
1589 * of that type will be considered in the search. Else all relation types
1590 * are considered.
1591 * @param roleName can be null; if specified, only the relations
1592 * where the MBean is referenced in that role will be returned. Else all
1593 * roles are considered.
1594 *
1595 * @return an HashMap, where the keys are the relation ids of the relations
1596 * where the MBean is referenced, and the value is, for each key,
1597 * an ArrayList of role names (as an MBean can be referenced in several
1598 * roles in the same relation).
1599 *
1600 * @exception IllegalArgumentException if null parameter
1601 */
1602 public Map<String,List<String>>
1603 findReferencingRelations(ObjectName mbeanName,
1604 String relationTypeName,
1605 String roleName)
1606 throws IllegalArgumentException {
1607
1608 if (mbeanName == null) {
1609 String excMsg = "Invalid parameter.";
1610 throw new IllegalArgumentException(excMsg);
1611 }
1612
1613 RELATION_LOGGER.entering(RelationService.class.getName(),
1614 "findReferencingRelations",
1615 new Object[] {mbeanName, relationTypeName, roleName});
1616
1617 Map<String,List<String>> result = new HashMap<String,List<String>>();
1618
1619 synchronized(myRefedMBeanObjName2RelIdsMap) {
1620
1621 // Retrieves the relations referencing the MBean
1622 Map<String,List<String>> relId2RoleNamesMap =
1623 myRefedMBeanObjName2RelIdsMap.get(mbeanName);
1624
1625 if (relId2RoleNamesMap != null) {
1626
1627 // Relation Ids where the MBean is referenced
1628 Set<String> allRelIdSet = relId2RoleNamesMap.keySet();
1629
1630 // List of relation ids of interest regarding the selected
1631 // relation type
1632 List<String> relIdList;
1633 if (relationTypeName == null) {
1634 // Considers all relations
1635 relIdList = new ArrayList<String>(allRelIdSet);
1636
1637 } else {
1638
1639 relIdList = new ArrayList<String>();
1640
1641 // Considers only the relation ids for relations of given
1642 // type
1643 for (String currRelId : allRelIdSet) {
1644
1645 // Retrieves its relation type
1646 String currRelTypeName;
1647 synchronized(myRelId2RelTypeMap) {
1648 currRelTypeName =
1649 myRelId2RelTypeMap.get(currRelId);
1650 }
1651
1652 if (currRelTypeName.equals(relationTypeName)) {
1653
1654 relIdList.add(currRelId);
1655
1656 }
1657 }
1658 }
1659
1660 // Now looks at the roles where the MBean is expected to be
1661 // referenced
1662
1663 for (String currRelId : relIdList) {
1664 // Retrieves list of role names where the MBean is
1665 // referenced
1666 List<String> currRoleNameList =
1667 relId2RoleNamesMap.get(currRelId);
1668
1669 if (roleName == null) {
1670 // All roles to be considered
1671 // Note: no need to test if list not null before
1672 // cloning, MUST be not null else bug :(
1673 result.put(currRelId,
1674 new ArrayList<String>(currRoleNameList));
1675
1676 } else if (currRoleNameList.contains(roleName)) {
1677 // Filters only the relations where the MBean is
1678 // referenced in // given role
1679 List<String> dummyList = new ArrayList<String>();
1680 dummyList.add(roleName);
1681 result.put(currRelId, dummyList);
1682 }
1683 }
1684 }
1685 }
1686
1687 RELATION_LOGGER.exiting(RelationService.class.getName(),
1688 "findReferencingRelations");
1689 return result;
1690 }
1691
1692 /**
1693 * Retrieves the MBeans associated to given one in a relation.
1694 * <P>This corresponds to CIM Associators and AssociatorNames operations.
1695 *
1696 * @param mbeanName ObjectName of MBean
1697 * @param relationTypeName can be null; if specified, only the relations
1698 * of that type will be considered in the search. Else all
1699 * relation types are considered.
1700 * @param roleName can be null; if specified, only the relations
1701 * where the MBean is referenced in that role will be considered. Else all
1702 * roles are considered.
1703 *
1704 * @return an HashMap, where the keys are the ObjectNames of the MBeans
1705 * associated to given MBean, and the value is, for each key, an ArrayList
1706 * of the relation ids of the relations where the key MBean is
1707 * associated to given one (as they can be associated in several different
1708 * relations).
1709 *
1710 * @exception IllegalArgumentException if null parameter
1711 */
1712 public Map<ObjectName,List<String>>
1713 findAssociatedMBeans(ObjectName mbeanName,
1714 String relationTypeName,
1715 String roleName)
1716 throws IllegalArgumentException {
1717
1718 if (mbeanName == null) {
1719 String excMsg = "Invalid parameter.";
1720 throw new IllegalArgumentException(excMsg);
1721 }
1722
1723 RELATION_LOGGER.entering(RelationService.class.getName(),
1724 "findAssociatedMBeans",
1725 new Object[] {mbeanName, relationTypeName, roleName});
1726
1727 // Retrieves the map <relation id> -> <role names> for those
1728 // criterias
1729 Map<String,List<String>> relId2RoleNamesMap =
1730 findReferencingRelations(mbeanName,
1731 relationTypeName,
1732 roleName);
1733
1734 Map<ObjectName,List<String>> result =
1735 new HashMap<ObjectName,List<String>>();
1736
1737 for (String currRelId : relId2RoleNamesMap.keySet()) {
1738
1739 // Retrieves ObjectNames of MBeans referenced in this relation
1740 //
1741 // Shall not throw a RelationNotFoundException if incorrect status
1742 // of maps :(
1743 Map<ObjectName,List<String>> objName2RoleNamesMap;
1744 try {
1745 objName2RoleNamesMap = getReferencedMBeans(currRelId);
1746 } catch (RelationNotFoundException exc) {
1747 throw new RuntimeException(exc.getMessage());
1748 }
1749
1750 // For each MBean associated to given one in a relation, adds the
1751 // association <ObjectName> -> <relation id> into result map
1752 for (ObjectName currObjName : objName2RoleNamesMap.keySet()) {
1753
1754 if (!(currObjName.equals(mbeanName))) {
1755
1756 // Sees if this MBean is already associated to the given
1757 // one in another relation
1758 List<String> currRelIdList = result.get(currObjName);
1759 if (currRelIdList == null) {
1760
1761 currRelIdList = new ArrayList<String>();
1762 currRelIdList.add(currRelId);
1763 result.put(currObjName, currRelIdList);
1764
1765 } else {
1766 currRelIdList.add(currRelId);
1767 }
1768 }
1769 }
1770 }
1771
1772 RELATION_LOGGER.exiting(RelationService.class.getName(),
1773 "findAssociatedMBeans");
1774 return result;
1775 }
1776
1777 /**
1778 * Returns the relation ids for relations of the given type.
1779 *
1780 * @param relationTypeName relation type name
1781 *
1782 * @return an ArrayList of relation ids.
1783 *
1784 * @exception IllegalArgumentException if null parameter
1785 * @exception RelationTypeNotFoundException if there is no relation type
1786 * with that name.
1787 */
1788 public List<String> findRelationsOfType(String relationTypeName)
1789 throws IllegalArgumentException,
1790 RelationTypeNotFoundException {
1791
1792 if (relationTypeName == null) {
1793 String excMsg = "Invalid parameter.";
1794 throw new IllegalArgumentException(excMsg);
1795 }
1796
1797 RELATION_LOGGER.entering(RelationService.class.getName(),
1798 "findRelationsOfType");
1799
1800 // Can throw RelationTypeNotFoundException
1801 RelationType relType = getRelationType(relationTypeName);
1802
1803 List<String> result;
1804 synchronized(myRelType2RelIdsMap) {
1805 List<String> result1 = myRelType2RelIdsMap.get(relationTypeName);
1806 if (result1 == null)
1807 result = new ArrayList<String>();
1808 else
1809 result = new ArrayList<String>(result1);
1810 }
1811
1812 RELATION_LOGGER.exiting(RelationService.class.getName(),
1813 "findRelationsOfType");
1814 return result;
1815 }
1816
1817 /**
1818 * Retrieves role value for given role name in given relation.
1819 *
1820 * @param relationId relation id
1821 * @param roleName name of role
1822 *
1823 * @return the ArrayList of ObjectName objects being the role value
1824 *
1825 * @exception RelationServiceNotRegisteredException if the Relation
1826 * Service is not registered
1827 * @exception IllegalArgumentException if null parameter
1828 * @exception RelationNotFoundException if no relation with given id
1829 * @exception RoleNotFoundException if:
1830 * <P>- there is no role with given name
1831 * <P>or
1832 * <P>- the role is not readable.
1833 *
1834 * @see #setRole
1835 */
1836 public List<ObjectName> getRole(String relationId,
1837 String roleName)
1838 throws RelationServiceNotRegisteredException,
1839 IllegalArgumentException,
1840 RelationNotFoundException,
1841 RoleNotFoundException {
1842
1843 if (relationId == null || roleName == null) {
1844 String excMsg = "Invalid parameter.";
1845 throw new IllegalArgumentException(excMsg);
1846 }
1847
1848 RELATION_LOGGER.entering(RelationService.class.getName(),
1849 "getRole", new Object[] {relationId, roleName});
1850
1851 // Can throw RelationServiceNotRegisteredException
1852 isActive();
1853
1854 // Can throw a RelationNotFoundException
1855 Object relObj = getRelation(relationId);
1856
1857 List<ObjectName> result;
1858
1859 if (relObj instanceof RelationSupport) {
1860 // Internal relation
1861 // Can throw RoleNotFoundException
1862 result = cast(
1863 ((RelationSupport)relObj).getRoleInt(roleName,
1864 true,
1865 this,
1866 false));
1867
1868 } else {
1869 // Relation MBean
1870 Object[] params = new Object[1];
1871 params[0] = roleName;
1872 String[] signature = new String[1];
1873 signature[0] = "java.lang.String";
1874 // Can throw MBeanException wrapping a RoleNotFoundException:
1875 // throw wrapped exception
1876 //
1877 // Shall not throw InstanceNotFoundException or ReflectionException
1878 try {
1879 List<ObjectName> invokeResult = cast(
1880 myMBeanServer.invoke(((ObjectName)relObj),
1881 "getRole",
1882 params,
1883 signature));
1884 if (invokeResult == null || invokeResult instanceof ArrayList)
1885 result = invokeResult;
1886 else
1887 result = new ArrayList<ObjectName>(invokeResult);
1888 } catch (InstanceNotFoundException exc1) {
1889 throw new RuntimeException(exc1.getMessage());
1890 } catch (ReflectionException exc2) {
1891 throw new RuntimeException(exc2.getMessage());
1892 } catch (MBeanException exc3) {
1893 Exception wrappedExc = exc3.getTargetException();
1894 if (wrappedExc instanceof RoleNotFoundException) {
1895 throw ((RoleNotFoundException)wrappedExc);
1896 } else {
1897 throw new RuntimeException(wrappedExc.getMessage());
1898 }
1899 }
1900 }
1901
1902 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRole");
1903 return result;
1904 }
1905
1906 /**
1907 * Retrieves values of roles with given names in given relation.
1908 *
1909 * @param relationId relation id
1910 * @param roleNameArray array of names of roles to be retrieved
1911 *
1912 * @return a RoleResult object, including a RoleList (for roles
1913 * successfully retrieved) and a RoleUnresolvedList (for roles not
1914 * retrieved).
1915 *
1916 * @exception RelationServiceNotRegisteredException if the Relation
1917 * Service is not registered in the MBean Server
1918 * @exception IllegalArgumentException if null parameter
1919 * @exception RelationNotFoundException if no relation with given id
1920 *
1921 * @see #setRoles
1922 */
1923 public RoleResult getRoles(String relationId,
1924 String[] roleNameArray)
1925 throws RelationServiceNotRegisteredException,
1926 IllegalArgumentException,
1927 RelationNotFoundException {
1928
1929 if (relationId == null || roleNameArray == null) {
1930 String excMsg = "Invalid parameter.";
1931 throw new IllegalArgumentException(excMsg);
1932 }
1933
1934 RELATION_LOGGER.entering(RelationService.class.getName(),
1935 "getRoles", relationId);
1936
1937 // Can throw RelationServiceNotRegisteredException
1938 isActive();
1939
1940 // Can throw a RelationNotFoundException
1941 Object relObj = getRelation(relationId);
1942
1943 RoleResult result;
1944
1945 if (relObj instanceof RelationSupport) {
1946 // Internal relation
1947 result = ((RelationSupport)relObj).getRolesInt(roleNameArray,
1948 true,
1949 this);
1950 } else {
1951 // Relation MBean
1952 Object[] params = new Object[1];
1953 params[0] = roleNameArray;
1954 String[] signature = new String[1];
1955 try {
1956 signature[0] = (roleNameArray.getClass()).getName();
1957 } catch (Exception exc) {
1958 // OK : This is an array of java.lang.String
1959 // so this should never happen...
1960 }
1961 // Shall not throw InstanceNotFoundException, ReflectionException
1962 // or MBeanException
1963 try {
1964 result = (RoleResult)
1965 (myMBeanServer.invoke(((ObjectName)relObj),
1966 "getRoles",
1967 params,
1968 signature));
1969 } catch (InstanceNotFoundException exc1) {
1970 throw new RuntimeException(exc1.getMessage());
1971 } catch (ReflectionException exc2) {
1972 throw new RuntimeException(exc2.getMessage());
1973 } catch (MBeanException exc3) {
1974 throw new
1975 RuntimeException((exc3.getTargetException()).getMessage());
1976 }
1977 }
1978
1979 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles");
1980 return result;
1981 }
1982
1983 /**
1984 * Returns all roles present in the relation.
1985 *
1986 * @param relationId relation id
1987 *
1988 * @return a RoleResult object, including a RoleList (for roles
1989 * successfully retrieved) and a RoleUnresolvedList (for roles not
1990 * readable).
1991 *
1992 * @exception IllegalArgumentException if null parameter
1993 * @exception RelationNotFoundException if no relation for given id
1994 * @exception RelationServiceNotRegisteredException if the Relation
1995 * Service is not registered in the MBean Server
1996 */
1997 public RoleResult getAllRoles(String relationId)
1998 throws IllegalArgumentException,
1999 RelationNotFoundException,
2000 RelationServiceNotRegisteredException {
2001
2002 if (relationId == null) {
2003 String excMsg = "Invalid parameter.";
2004 throw new IllegalArgumentException(excMsg);
2005 }
2006
2007 RELATION_LOGGER.entering(RelationService.class.getName(),
2008 "getRoles", relationId);
2009
2010 // Can throw a RelationNotFoundException
2011 Object relObj = getRelation(relationId);
2012
2013 RoleResult result;
2014
2015 if (relObj instanceof RelationSupport) {
2016 // Internal relation
2017 result = ((RelationSupport)relObj).getAllRolesInt(true, this);
2018
2019 } else {
2020 // Relation MBean
2021 // Shall not throw any Exception
2022 try {
2023 result = (RoleResult)
2024 (myMBeanServer.getAttribute(((ObjectName)relObj),
2025 "AllRoles"));
2026 } catch (Exception exc) {
2027 throw new RuntimeException(exc.getMessage());
2028 }
2029 }
2030
2031 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles");
2032 return result;
2033 }
2034
2035 /**
2036 * Retrieves the number of MBeans currently referenced in the given role.
2037 *
2038 * @param relationId relation id
2039 * @param roleName name of role
2040 *
2041 * @return the number of currently referenced MBeans in that role
2042 *
2043 * @exception IllegalArgumentException if null parameter
2044 * @exception RelationNotFoundException if no relation with given id
2045 * @exception RoleNotFoundException if there is no role with given name
2046 */
2047 public Integer getRoleCardinality(String relationId,
2048 String roleName)
2049 throws IllegalArgumentException,
2050 RelationNotFoundException,
2051 RoleNotFoundException {
2052
2053 if (relationId == null || roleName == null) {
2054 String excMsg = "Invalid parameter.";
2055 throw new IllegalArgumentException(excMsg);
2056 }
2057
2058 RELATION_LOGGER.entering(RelationService.class.getName(),
2059 "getRoleCardinality", new Object[] {relationId, roleName});
2060
2061 // Can throw a RelationNotFoundException
2062 Object relObj = getRelation(relationId);
2063
2064 Integer result;
2065
2066 if (relObj instanceof RelationSupport) {
2067 // Internal relation
2068 // Can throw RoleNotFoundException
2069 result = ((RelationSupport)relObj).getRoleCardinality(roleName);
2070
2071 } else {
2072 // Relation MBean
2073 Object[] params = new Object[1];
2074 params[0] = roleName;
2075 String[] signature = new String[1];
2076 signature[0] = "java.lang.String";
2077 // Can throw MBeanException wrapping RoleNotFoundException:
2078 // throw wrapped exception
2079 //
2080 // Shall not throw InstanceNotFoundException or ReflectionException
2081 try {
2082 result = (Integer)
2083 (myMBeanServer.invoke(((ObjectName)relObj),
2084 "getRoleCardinality",
2085 params,
2086 signature));
2087 } catch (InstanceNotFoundException exc1) {
2088 throw new RuntimeException(exc1.getMessage());
2089 } catch (ReflectionException exc2) {
2090 throw new RuntimeException(exc2.getMessage());
2091 } catch (MBeanException exc3) {
2092 Exception wrappedExc = exc3.getTargetException();
2093 if (wrappedExc instanceof RoleNotFoundException) {
2094 throw ((RoleNotFoundException)wrappedExc);
2095 } else {
2096 throw new RuntimeException(wrappedExc.getMessage());
2097 }
2098 }
2099 }
2100
2101 RELATION_LOGGER.exiting(RelationService.class.getName(),
2102 "getRoleCardinality");
2103 return result;
2104 }
2105
2106 /**
2107 * Sets the given role in given relation.
2108 * <P>Will check the role according to its corresponding role definition
2109 * provided in relation's relation type
2110 * <P>The Relation Service will keep track of the change to keep the
2111 * consistency of relations by handling referenced MBean unregistrations.
2112 *
2113 * @param relationId relation id
2114 * @param role role to be set (name and new value)
2115 *
2116 * @exception RelationServiceNotRegisteredException if the Relation
2117 * Service is not registered in the MBean Server
2118 * @exception IllegalArgumentException if null parameter
2119 * @exception RelationNotFoundException if no relation with given id
2120 * @exception RoleNotFoundException if the role does not exist or is not
2121 * writable
2122 * @exception InvalidRoleValueException if value provided for role is not
2123 * valid:
2124 * <P>- the number of referenced MBeans in given value is less than
2125 * expected minimum degree
2126 * <P>or
2127 * <P>- the number of referenced MBeans in provided value exceeds expected
2128 * maximum degree
2129 * <P>or
2130 * <P>- one referenced MBean in the value is not an Object of the MBean
2131 * class expected for that role
2132 * <P>or
2133 * <P>- an MBean provided for that role does not exist
2134 *
2135 * @see #getRole
2136 */
2137 public void setRole(String relationId,
2138 Role role)
2139 throws RelationServiceNotRegisteredException,
2140 IllegalArgumentException,
2141 RelationNotFoundException,
2142 RoleNotFoundException,
2143 InvalidRoleValueException {
2144
2145 if (relationId == null || role == null) {
2146 String excMsg = "Invalid parameter.";
2147 throw new IllegalArgumentException(excMsg);
2148 }
2149
2150 RELATION_LOGGER.entering(RelationService.class.getName(),
2151 "setRole", new Object[] {relationId, role});
2152
2153 // Can throw RelationServiceNotRegisteredException
2154 isActive();
2155
2156 // Can throw a RelationNotFoundException
2157 Object relObj = getRelation(relationId);
2158
2159 if (relObj instanceof RelationSupport) {
2160 // Internal relation
2161 // Can throw RoleNotFoundException,
2162 // InvalidRoleValueException and
2163 // RelationServiceNotRegisteredException
2164 //
2165 // Shall not throw RelationTypeNotFoundException
2166 // (as relation exists in the RS, its relation type is known)
2167 try {
2168 ((RelationSupport)relObj).setRoleInt(role,
2169 true,
2170 this,
2171 false);
2172
2173 } catch (RelationTypeNotFoundException exc) {
2174 throw new RuntimeException(exc.getMessage());
2175 }
2176
2177 } else {
2178 // Relation MBean
2179 Object[] params = new Object[1];
2180 params[0] = role;
2181 String[] signature = new String[1];
2182 signature[0] = "javax.management.relation.Role";
2183 // Can throw MBeanException wrapping RoleNotFoundException,
2184 // InvalidRoleValueException
2185 //
2186 // Shall not MBeanException wrapping an MBeanException wrapping
2187 // RelationTypeNotFoundException, or ReflectionException, or
2188 // InstanceNotFoundException
2189 try {
2190 myMBeanServer.setAttribute(((ObjectName)relObj),
2191 new Attribute("Role", role));
2192
2193 } catch (InstanceNotFoundException exc1) {
2194 throw new RuntimeException(exc1.getMessage());
2195 } catch (ReflectionException exc3) {
2196 throw new RuntimeException(exc3.getMessage());
2197 } catch (MBeanException exc2) {
2198 Exception wrappedExc = exc2.getTargetException();
2199 if (wrappedExc instanceof RoleNotFoundException) {
2200 throw ((RoleNotFoundException)wrappedExc);
2201 } else if (wrappedExc instanceof InvalidRoleValueException) {
2202 throw ((InvalidRoleValueException)wrappedExc);
2203 } else {
2204 throw new RuntimeException(wrappedExc.getMessage());
2205
2206 }
2207 } catch (AttributeNotFoundException exc4) {
2208 throw new RuntimeException(exc4.getMessage());
2209 } catch (InvalidAttributeValueException exc5) {
2210 throw new RuntimeException(exc5.getMessage());
2211 }
2212 }
2213
2214 RELATION_LOGGER.exiting(RelationService.class.getName(), "setRole");
2215 return;
2216 }
2217
2218 /**
2219 * Sets the given roles in given relation.
2220 * <P>Will check the role according to its corresponding role definition
2221 * provided in relation's relation type
2222 * <P>The Relation Service keeps track of the changes to keep the
2223 * consistency of relations by handling referenced MBean unregistrations.
2224 *
2225 * @param relationId relation id
2226 * @param roleList list of roles to be set
2227 *
2228 * @return a RoleResult object, including a RoleList (for roles
2229 * successfully set) and a RoleUnresolvedList (for roles not
2230 * set).
2231 *
2232 * @exception RelationServiceNotRegisteredException if the Relation
2233 * Service is not registered in the MBean Server
2234 * @exception IllegalArgumentException if null parameter
2235 * @exception RelationNotFoundException if no relation with given id
2236 *
2237 * @see #getRoles
2238 */
2239 public RoleResult setRoles(String relationId,
2240 RoleList roleList)
2241 throws RelationServiceNotRegisteredException,
2242 IllegalArgumentException,
2243 RelationNotFoundException {
2244
2245 if (relationId == null || roleList == null) {
2246 String excMsg = "Invalid parameter.";
2247 throw new IllegalArgumentException(excMsg);
2248 }
2249
2250 RELATION_LOGGER.entering(RelationService.class.getName(),
2251 "setRoles", new Object[] {relationId, roleList});
2252
2253 // Can throw RelationServiceNotRegisteredException
2254 isActive();
2255
2256 // Can throw a RelationNotFoundException
2257 Object relObj = getRelation(relationId);
2258
2259 RoleResult result;
2260
2261 if (relObj instanceof RelationSupport) {
2262 // Internal relation
2263 // Can throw RelationServiceNotRegisteredException
2264 //
2265 // Shall not throw RelationTypeNotFoundException (as relation is
2266 // known, its relation type exists)
2267 try {
2268 result = ((RelationSupport)relObj).setRolesInt(roleList,
2269 true,
2270 this);
2271 } catch (RelationTypeNotFoundException exc) {
2272 throw new RuntimeException(exc.getMessage());
2273 }
2274
2275 } else {
2276 // Relation MBean
2277 Object[] params = new Object[1];
2278 params[0] = roleList;
2279 String[] signature = new String[1];
2280 signature[0] = "javax.management.relation.RoleList";
2281 // Shall not throw InstanceNotFoundException or an MBeanException
2282 // or ReflectionException
2283 try {
2284 result = (RoleResult)
2285 (myMBeanServer.invoke(((ObjectName)relObj),
2286 "setRoles",
2287 params,
2288 signature));
2289 } catch (InstanceNotFoundException exc1) {
2290 throw new RuntimeException(exc1.getMessage());
2291 } catch (ReflectionException exc3) {
2292 throw new RuntimeException(exc3.get