blob: 7ef98aa7a6f6727f15a6f64d478cbd9ab72f2361 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
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
26package javax.management.relation;
27
28import static com.sun.jmx.defaults.JmxProperties.RELATION_LOGGER;
29import static com.sun.jmx.mbeanserver.Util.cast;
30
31import java.util.ArrayList;
32import java.util.Date;
33import java.util.HashMap;
34import java.util.Iterator;
35import java.util.List;
36import java.util.Map;
37import java.util.Set;
38import java.util.logging.Level;
39
40import javax.management.Attribute;
41import javax.management.AttributeNotFoundException;
42import javax.management.InstanceNotFoundException;
43import javax.management.InvalidAttributeValueException;
44import javax.management.MBeanException;
45import javax.management.MBeanNotificationInfo;
46import javax.management.MBeanRegistration;
47import javax.management.MBeanServer;
48import javax.management.MBeanServerDelegate;
49import javax.management.MBeanServerNotification;
50import javax.management.Notification;
51import javax.management.NotificationBroadcasterSupport;
52import javax.management.NotificationListener;
53import javax.management.ObjectName;
54import javax.management.ReflectionException;
55
56/**
57 * The Relation Service is in charge of creating and deleting relation types
58 * and relations, of handling the consistency and of providing query
59 * mechanisms.
60 * <P>It implements the NotificationBroadcaster by extending
61 * NotificationBroadcasterSupport to send notifications when a relation is
62 * removed from it.
63 * <P>It implements the NotificationListener interface to be able to receive
64 * notifications concerning unregistration of MBeans referenced in relation
65 * roles and of relation MBeans.
66 * <P>It implements the MBeanRegistration interface to be able to retrieve
67 * its ObjectName and MBean Server.
68 *
69 * @since 1.5
70 */
71public class RelationService extends NotificationBroadcasterSupport
72 implements RelationServiceMBean, MBeanRegistration, NotificationListener {
73
74 //
75 // Private members
76 //
77
78 // Map associating:
79 // <relation id> -> <RelationSupport object/ObjectName>
80 // depending if the relation has been created using createRelation()
81 // method (so internally handled) or is an MBean added as a relation by the
82 // user
83 private Map<String,Object> myRelId2ObjMap = new HashMap<String,Object>();
84
85 // Map associating:
86 // <relation id> -> <relation type name>
87 private Map<String,String> myRelId2RelTypeMap = new HashMap<String,String>();
88
89 // Map associating:
90 // <relation MBean Object Name> -> <relation id>
91 private Map<ObjectName,String> myRelMBeanObjName2RelIdMap =
92 new HashMap<ObjectName,String>();
93
94 // Map associating:
95 // <relation type name> -> <RelationType object>
96 private Map<String,RelationType> myRelType2ObjMap =
97 new HashMap<String,RelationType>();
98
99 // Map associating:
100 // <relation type name> -> ArrayList of <relation id>
101 // to list all the relations of a given type
102 private Map<String,List<String>> myRelType2RelIdsMap =
103 new HashMap<String,List<String>>();
104
105 // Map associating:
106 // <ObjectName> -> HashMap
107 // the value HashMap mapping:
108 // <relation id> -> ArrayList of <role name>
109 // to track where a given MBean is referenced.
110 private Map<ObjectName,Map<String,List<String>>>
111 myRefedMBeanObjName2RelIdsMap =
112 new HashMap<ObjectName,Map<String,List<String>>>();
113
114 // Flag to indicate if, when a notification is received for the
115 // unregistration of an MBean referenced in a relation, if an immediate
116 // "purge" of the relations (look for the relations no
117 // longer valid) has to be performed , or if that will be performed only
118 // when the purgeRelations method will be explicitly called.
119 // true is immediate purge.
120 private boolean myPurgeFlag = true;
121
122 // Internal counter to provide sequence numbers for notifications sent by:
123 // - the Relation Service
124 // - a relation handled by the Relation Service
125 private Long myNtfSeqNbrCounter = new Long(0);
126
127 // ObjectName used to register the Relation Service in the MBean Server
128 private ObjectName myObjName = null;
129
130 // MBean Server where the Relation Service is registered
131 private MBeanServer myMBeanServer = null;
132
133 // Filter registered in the MBean Server with the Relation Service to be
134 // informed of referenced MBean unregistrations
135 private MBeanServerNotificationFilter myUnregNtfFilter = null;
136
137 // List of unregistration notifications received (storage used if purge
138 // of relations when unregistering a referenced MBean is not immediate but
139 // on user request)
140 private List<MBeanServerNotification> myUnregNtfList =
141 new ArrayList<MBeanServerNotification>();
142
143 //
144 // Constructor
145 //
146
147 /**
148 * Constructor.
149 *
150 * @param immediatePurgeFlag flag to indicate when a notification is
151 * received for the unregistration of an MBean referenced in a relation, if
152 * an immediate "purge" of the relations (look for the relations no
153 * longer valid) has to be performed , or if that will be performed only
154 * when the purgeRelations method will be explicitly called.
155 * <P>true is immediate purge.
156 */
157 public RelationService(boolean immediatePurgeFlag) {
158
159 RELATION_LOGGER.entering(RelationService.class.getName(),
160 "RelationService");
161
162 setPurgeFlag(immediatePurgeFlag);
163
164 RELATION_LOGGER.exiting(RelationService.class.getName(),
165 "RelationService");
166 return;
167 }
168
169 /**
170 * Checks if the Relation Service is active.
171 * Current condition is that the Relation Service must be registered in the
172 * MBean Server
173 *
174 * @exception RelationServiceNotRegisteredException if it is not
175 * registered
176 */
177 public void isActive()
178 throws RelationServiceNotRegisteredException {
179 if (myMBeanServer == null) {
180 // MBean Server not set by preRegister(): relation service not
181 // registered
182 String excMsg =
183 "Relation Service not registered in the MBean Server.";
184 throw new RelationServiceNotRegisteredException(excMsg);
185 }
186 return;
187 }
188
189 //
190 // MBeanRegistration interface
191 //
192
193 // Pre-registration: retrieves its ObjectName and MBean Server
194 //
195 // No exception thrown.
196 public ObjectName preRegister(MBeanServer server,
197 ObjectName name)
198 throws Exception {
199
200 myMBeanServer = server;
201 myObjName = name;
202 return name;
203 }
204
205 // Post-registration: does nothing
206 public void postRegister(Boolean registrationDone) {
207 return;
208 }
209
210 // Pre-unregistration: does nothing
211 public void preDeregister()
212 throws Exception {
213 return;
214 }
215
216 // Post-unregistration: does nothing
217 public void postDeregister() {
218 return;
219 }
220
221 //
222 // Accessors
223 //
224
225 /**
226 * Returns the flag to indicate if when a notification is received for the
227 * unregistration of an MBean referenced in a relation, if an immediate
228 * "purge" of the relations (look for the relations no longer valid)
229 * has to be performed , or if that will be performed only when the
230 * purgeRelations method will be explicitly called.
231 * <P>true is immediate purge.
232 *
233 * @return true if purges are automatic.
234 *
235 * @see #setPurgeFlag
236 */
237 public boolean getPurgeFlag() {
238 return myPurgeFlag;
239 }
240
241 /**
242 * Sets the flag to indicate if when a notification is received for the
243 * unregistration of an MBean referenced in a relation, if an immediate
244 * "purge" of the relations (look for the relations no longer valid)
245 * has to be performed , or if that will be performed only when the
246 * purgeRelations method will be explicitly called.
247 * <P>true is immediate purge.
248 *
249 * @param purgeFlag flag
250 *
251 * @see #getPurgeFlag
252 */
253 public void setPurgeFlag(boolean purgeFlag) {
254
255 myPurgeFlag = purgeFlag;
256 return;
257 }
258
259 // Returns internal counter to be used for Sequence Numbers of
260 // notifications to be raised by:
261 // - a relation handled by this Relation Service (when updated)
262 // - the Relation Service
263 private Long getNotificationSequenceNumber() {
264 Long result = null;
265 synchronized(myNtfSeqNbrCounter) {
266 result = new Long(myNtfSeqNbrCounter.longValue() + 1);
267 myNtfSeqNbrCounter = new Long(result.longValue());
268 }
269 return result;
270 }
271
272 //
273 // Relation type handling
274 //
275
276 /**
277 * Creates a relation type (a RelationTypeSupport object) with given
278 * role infos (provided by the RoleInfo objects), and adds it in the
279 * Relation Service.
280 *
281 * @param relationTypeName name of the relation type
282 * @param roleInfoArray array of role infos
283 *
284 * @exception IllegalArgumentException if null parameter
285 * @exception InvalidRelationTypeException If:
286 * <P>- there is already a relation type with that name
287 * <P>- the same name has been used for two different role infos
288 * <P>- no role info provided
289 * <P>- one null role info provided
290 */
291 public void createRelationType(String relationTypeName,
292 RoleInfo[] roleInfoArray)
293 throws IllegalArgumentException,
294 InvalidRelationTypeException {
295
296 if (relationTypeName == null || roleInfoArray == null) {
297 String excMsg = "Invalid parameter.";
298 throw new IllegalArgumentException(excMsg);
299 }
300
301 RELATION_LOGGER.entering(RelationService.class.getName(),
302 "createRelationType", relationTypeName);
303
304 // Can throw an InvalidRelationTypeException
305 RelationType relType =
306 new RelationTypeSupport(relationTypeName, roleInfoArray);
307
308 addRelationTypeInt(relType);
309
310 RELATION_LOGGER.exiting(RelationService.class.getName(),
311 "createRelationType");
312 return;
313 }
314
315 /**
316 * Adds given object as a relation type. The object is expected to
317 * implement the RelationType interface.
318 *
319 * @param relationTypeObj relation type object (implementing the
320 * RelationType interface)
321 *
322 * @exception IllegalArgumentException if null parameter or if
323 * {@link RelationType#getRelationTypeName
324 * relationTypeObj.getRelationTypeName()} returns null.
325 * @exception InvalidRelationTypeException if:
326 * <P>- the same name has been used for two different roles
327 * <P>- no role info provided
328 * <P>- one null role info provided
329 * <P>- there is already a relation type with that name
330 */
331 public void addRelationType(RelationType relationTypeObj)
332 throws IllegalArgumentException,
333 InvalidRelationTypeException {
334
335 if (relationTypeObj == null) {
336 String excMsg = "Invalid parameter.";
337 throw new IllegalArgumentException(excMsg);
338 }
339
340 RELATION_LOGGER.entering(RelationService.class.getName(),
341 "addRelationType");
342
343 // Checks the role infos
344 List<RoleInfo> roleInfoList = relationTypeObj.getRoleInfos();
345 if (roleInfoList == null) {
346 String excMsg = "No role info provided.";
347 throw new InvalidRelationTypeException(excMsg);
348 }
349
350 RoleInfo[] roleInfoArray = new RoleInfo[roleInfoList.size()];
351 int i = 0;
352 for (RoleInfo currRoleInfo : roleInfoList) {
353 roleInfoArray[i] = currRoleInfo;
354 i++;
355 }
356 // Can throw InvalidRelationTypeException
357 RelationTypeSupport.checkRoleInfos(roleInfoArray);
358
359 addRelationTypeInt(relationTypeObj);
360
361 RELATION_LOGGER.exiting(RelationService.class.getName(),
362 "addRelationType");
363 return;
364 }
365
366 /**
367 * Retrieves names of all known relation types.
368 *
369 * @return ArrayList of relation type names (Strings)
370 */
371 public List<String> getAllRelationTypeNames() {
372 ArrayList<String> result = null;
373 synchronized(myRelType2ObjMap) {
374 result = new ArrayList<String>(myRelType2ObjMap.keySet());
375 }
376 return result;
377 }
378
379 /**
380 * Retrieves list of role infos (RoleInfo objects) of a given relation
381 * type.
382 *
383 * @param relationTypeName name of relation type
384 *
385 * @return ArrayList of RoleInfo.
386 *
387 * @exception IllegalArgumentException if null parameter
388 * @exception RelationTypeNotFoundException if there is no relation type
389 * with that name.
390 */
391 public List<RoleInfo> getRoleInfos(String relationTypeName)
392 throws IllegalArgumentException,
393 RelationTypeNotFoundException {
394
395 if (relationTypeName == null) {
396 String excMsg = "Invalid parameter.";
397 throw new IllegalArgumentException(excMsg);
398 }
399
400 RELATION_LOGGER.entering(RelationService.class.getName(),
401 "getRoleInfos", relationTypeName);
402
403 // Can throw a RelationTypeNotFoundException
404 RelationType relType = getRelationType(relationTypeName);
405
406 RELATION_LOGGER.exiting(RelationService.class.getName(),
407 "getRoleInfos");
408 return relType.getRoleInfos();
409 }
410
411 /**
412 * Retrieves role info for given role name of a given relation type.
413 *
414 * @param relationTypeName name of relation type
415 * @param roleInfoName name of role
416 *
417 * @return RoleInfo object.
418 *
419 * @exception IllegalArgumentException if null parameter
420 * @exception RelationTypeNotFoundException if the relation type is not
421 * known in the Relation Service
422 * @exception RoleInfoNotFoundException if the role is not part of the
423 * relation type.
424 */
425 public RoleInfo getRoleInfo(String relationTypeName,
426 String roleInfoName)
427 throws IllegalArgumentException,
428 RelationTypeNotFoundException,
429 RoleInfoNotFoundException {
430
431 if (relationTypeName == null || roleInfoName == null) {
432 String excMsg = "Invalid parameter.";
433 throw new IllegalArgumentException(excMsg);
434 }
435
436 RELATION_LOGGER.entering(RelationService.class.getName(),
437 "getRoleInfo", new Object[] {relationTypeName, roleInfoName});
438
439 // Can throw a RelationTypeNotFoundException
440 RelationType relType = getRelationType(relationTypeName);
441
442 // Can throw a RoleInfoNotFoundException
443 RoleInfo roleInfo = relType.getRoleInfo(roleInfoName);
444
445 RELATION_LOGGER.exiting(RelationService.class.getName(),
446 "getRoleInfo");
447 return roleInfo;
448 }
449
450 /**
451 * Removes given relation type from Relation Service.
452 * <P>The relation objects of that type will be removed from the
453 * Relation Service.
454 *
455 * @param relationTypeName name of the relation type to be removed
456 *
457 * @exception RelationServiceNotRegisteredException if the Relation
458 * Service is not registered in the MBean Server
459 * @exception IllegalArgumentException if null parameter
460 * @exception RelationTypeNotFoundException If there is no relation type
461 * with that name
462 */
463 public void removeRelationType(String relationTypeName)
464 throws RelationServiceNotRegisteredException,
465 IllegalArgumentException,
466 RelationTypeNotFoundException {
467
468 // Can throw RelationServiceNotRegisteredException
469 isActive();
470
471 if (relationTypeName == null) {
472 String excMsg = "Invalid parameter.";
473 throw new IllegalArgumentException(excMsg);
474 }
475
476 RELATION_LOGGER.entering(RelationService.class.getName(),
477 "removeRelationType", relationTypeName);
478
479 // Checks if the relation type to be removed exists
480 // Can throw a RelationTypeNotFoundException
481 RelationType relType = getRelationType(relationTypeName);
482
483 // Retrieves the relation ids for relations of that type
484 List<String> relIdList = null;
485 synchronized(myRelType2RelIdsMap) {
486 // Note: take a copy of the list as it is a part of a map that
487 // will be updated by removeRelation() below.
488 List<String> relIdList1 =
489 myRelType2RelIdsMap.get(relationTypeName);
490 if (relIdList1 != null) {
491 relIdList = new ArrayList<String>(relIdList1);
492 }
493 }
494
495 // Removes the relation type from all maps
496 synchronized(myRelType2ObjMap) {
497 myRelType2ObjMap.remove(relationTypeName);
498 }
499 synchronized(myRelType2RelIdsMap) {
500 myRelType2RelIdsMap.remove(relationTypeName);
501 }
502
503 // Removes all relations of that type
504 if (relIdList != null) {
505 for (String currRelId : relIdList) {
506 // Note: will remove it from myRelId2RelTypeMap :)
507 //
508 // Can throw RelationServiceNotRegisteredException (detected
509 // above)
510 // Shall not throw a RelationNotFoundException
511 try {
512 removeRelation(currRelId);
513 } catch (RelationNotFoundException exc1) {
514 throw new RuntimeException(exc1.getMessage());
515 }
516 }
517 }
518
519 RELATION_LOGGER.exiting(RelationService.class.getName(),
520 "removeRelationType");
521 return;
522 }
523
524 //
525 // Relation handling
526 //
527
528 /**
529 * Creates a simple relation (represented by a RelationSupport object) of
530 * given relation type, and adds it in the Relation Service.
531 * <P>Roles are initialized according to the role list provided in
532 * parameter. The ones not initialized in this way are set to an empty
533 * ArrayList of ObjectNames.
534 * <P>A RelationNotification, with type RELATION_BASIC_CREATION, is sent.
535 *
536 * @param relationId relation identifier, to identify uniquely the relation
537 * inside the Relation Service
538 * @param relationTypeName name of the relation type (has to be created
539 * in the Relation Service)
540 * @param roleList role list to initialize roles of the relation (can
541 * be null).
542 *
543 * @exception RelationServiceNotRegisteredException if the Relation
544 * Service is not registered in the MBean Server
545 * @exception IllegalArgumentException if null parameter, except the role
546 * list which can be null if no role initialization
547 * @exception RoleNotFoundException if a value is provided for a role
548 * that does not exist in the relation type
549 * @exception InvalidRelationIdException if relation id already used
550 * @exception RelationTypeNotFoundException if relation type not known in
551 * Relation Service
552 * @exception InvalidRoleValueException if:
553 * <P>- the same role name is used for two different roles
554 * <P>- the number of referenced MBeans in given value is less than
555 * expected minimum degree
556 * <P>- the number of referenced MBeans in provided value exceeds expected
557 * maximum degree
558 * <P>- one referenced MBean in the value is not an Object of the MBean
559 * class expected for that role
560 * <P>- an MBean provided for that role does not exist
561 */
562 public void createRelation(String relationId,
563 String relationTypeName,
564 RoleList roleList)
565 throws RelationServiceNotRegisteredException,
566 IllegalArgumentException,
567 RoleNotFoundException,
568 InvalidRelationIdException,
569 RelationTypeNotFoundException,
570 InvalidRoleValueException {
571
572 // Can throw RelationServiceNotRegisteredException
573 isActive();
574
575 if (relationId == null ||
576 relationTypeName == null) {
577 String excMsg = "Invalid parameter.";
578 throw new IllegalArgumentException(excMsg);
579 }
580
581 RELATION_LOGGER.entering(RelationService.class.getName(),
582 "createRelation",
583 new Object[] {relationId, relationTypeName, roleList});
584
585 // Creates RelationSupport object
586 // Can throw InvalidRoleValueException
587 RelationSupport relObj = new RelationSupport(relationId,
588 myObjName,
589 relationTypeName,
590 roleList);
591
592 // Adds relation object as a relation into the Relation Service
593 // Can throw RoleNotFoundException, InvalidRelationId,
594 // RelationTypeNotFoundException, InvalidRoleValueException
595 //
596 // Cannot throw MBeanException
597 addRelationInt(true,
598 relObj,
599 null,
600 relationId,
601 relationTypeName,
602 roleList);
603 RELATION_LOGGER.exiting(RelationService.class.getName(),
604 "createRelation");
605 return;
606 }
607
608 /**
609 * Adds an MBean created by the user (and registered by him in the MBean
610 * Server) as a relation in the Relation Service.
611 * <P>To be added as a relation, the MBean must conform to the
612 * following:
613 * <P>- implement the Relation interface
614 * <P>- have for RelationService ObjectName the ObjectName of current
615 * Relation Service
616 * <P>- have a relation id unique and unused in current Relation Service
617 * <P>- have for relation type a relation type created in the Relation
618 * Service
619 * <P>- have roles conforming to the role info provided in the relation
620 * type.
621 *
622 * @param relationObjectName ObjectName of the relation MBean to be added.
623 *
624 * @exception IllegalArgumentException if null parameter
625 * @exception RelationServiceNotRegisteredException if the Relation
626 * Service is not registered in the MBean Server
627 * @exception NoSuchMethodException If the MBean does not implement the
628 * Relation interface
629 * @exception InvalidRelationIdException if:
630 * <P>- no relation identifier in MBean
631 * <P>- the relation identifier is already used in the Relation Service
632 * @exception InstanceNotFoundException if the MBean for given ObjectName
633 * has not been registered
634 * @exception InvalidRelationServiceException if:
635 * <P>- no Relation Service name in MBean
636 * <P>- the Relation Service name in the MBean is not the one of the
637 * current Relation Service
638 * @exception RelationTypeNotFoundException if:
639 * <P>- no relation type name in MBean
640 * <P>- the relation type name in MBean does not correspond to a relation
641 * type created in the Relation Service
642 * @exception InvalidRoleValueException if:
643 * <P>- the number of referenced MBeans in a role is less than
644 * expected minimum degree
645 * <P>- the number of referenced MBeans in a role exceeds expected
646 * maximum degree
647 * <P>- one referenced MBean in the value is not an Object of the MBean
648 * class expected for that role
649 * <P>- an MBean provided for a role does not exist
650 * @exception RoleNotFoundException if a value is provided for a role
651 * that does not exist in the relation type
652 */
653 public void addRelation(ObjectName relationObjectName)
654 throws IllegalArgumentException,
655 RelationServiceNotRegisteredException,
656 NoSuchMethodException,
657 InvalidRelationIdException,
658 InstanceNotFoundException,
659 InvalidRelationServiceException,
660 RelationTypeNotFoundException,
661 RoleNotFoundException,
662 InvalidRoleValueException {
663
664 if (relationObjectName == null) {
665 String excMsg = "Invalid parameter.";
666 throw new IllegalArgumentException(excMsg);
667 }
668
669 RELATION_LOGGER.entering(RelationService.class.getName(),
670 "addRelation", relationObjectName);
671
672 // Can throw RelationServiceNotRegisteredException
673 isActive();
674
675 // Checks that the relation MBean implements the Relation interface.
676 // It will also check that the provided ObjectName corresponds to a
677 // registered MBean (else will throw an InstanceNotFoundException)
678 if ((!(myMBeanServer.isInstanceOf(relationObjectName, "javax.management.relation.Relation")))) {
679 String excMsg = "This MBean does not implement the Relation interface.";
680 throw new NoSuchMethodException(excMsg);
681 }
682 // Checks there is a relation id in the relation MBean (its uniqueness
683 // is checked in addRelationInt())
684 // Can throw InstanceNotFoundException (but detected above)
685 // No MBeanException as no exception raised by this method, and no
686 // ReflectionException
687 String relId = null;
688 try {
689 relId = (String)(myMBeanServer.getAttribute(relationObjectName,
690 "RelationId"));
691
692 } catch (MBeanException exc1) {
693 throw new RuntimeException(
694 (exc1.getTargetException()).getMessage());
695 } catch (ReflectionException exc2) {
696 throw new RuntimeException(exc2.getMessage());
697 } catch (AttributeNotFoundException exc3) {
698 throw new RuntimeException(exc3.getMessage());
699 }
700
701 if (relId == null) {
702 String excMsg = "This MBean does not provide a relation id.";
703 throw new InvalidRelationIdException(excMsg);
704 }
705 // Checks that the Relation Service where the relation MBean is
706 // expected to be added is the current one
707 // Can throw InstanceNotFoundException (but detected above)
708 // No MBeanException as no exception raised by this method, no
709 // ReflectionException
710 ObjectName relServObjName = null;
711 try {
712 relServObjName = (ObjectName)
713 (myMBeanServer.getAttribute(relationObjectName,
714 "RelationServiceName"));
715
716 } catch (MBeanException exc1) {
717 throw new RuntimeException(
718 (exc1.getTargetException()).getMessage());
719 } catch (ReflectionException exc2) {
720 throw new RuntimeException(exc2.getMessage());
721 } catch (AttributeNotFoundException exc3) {
722 throw new RuntimeException(exc3.getMessage());
723 }
724
725 boolean badRelServFlag = false;
726 if (relServObjName == null) {
727 badRelServFlag = true;
728
729 } else if (!(relServObjName.equals(myObjName))) {
730 badRelServFlag = true;
731 }
732 if (badRelServFlag) {
733 String excMsg = "The Relation Service referenced in the MBean is not the current one.";
734 throw new InvalidRelationServiceException(excMsg);
735 }
736 // Checks that a relation type has been specified for the relation
737 // Can throw InstanceNotFoundException (but detected above)
738 // No MBeanException as no exception raised by this method, no
739 // ReflectionException
740 String relTypeName = null;
741 try {
742 relTypeName = (String)(myMBeanServer.getAttribute(relationObjectName,
743 "RelationTypeName"));
744
745 } catch (MBeanException exc1) {
746 throw new RuntimeException(
747 (exc1.getTargetException()).getMessage());
748 }catch (ReflectionException exc2) {
749 throw new RuntimeException(exc2.getMessage());
750 } catch (AttributeNotFoundException exc3) {
751 throw new RuntimeException(exc3.getMessage());
752 }
753 if (relTypeName == null) {
754 String excMsg = "No relation type provided.";
755 throw new RelationTypeNotFoundException(excMsg);
756 }
757 // Retrieves all roles without considering read mode
758 // Can throw InstanceNotFoundException (but detected above)
759 // No MBeanException as no exception raised by this method, no
760 // ReflectionException
761 RoleList roleList = null;
762 try {
763 roleList = (RoleList)(myMBeanServer.invoke(relationObjectName,
764 "retrieveAllRoles",
765 null,
766 null));
767 } catch (MBeanException exc1) {
768 throw new RuntimeException(
769 (exc1.getTargetException()).getMessage());
770 } catch (ReflectionException exc2) {
771 throw new RuntimeException(exc2.getMessage());
772 }
773
774 // Can throw RoleNotFoundException, InvalidRelationIdException,
775 // RelationTypeNotFoundException, InvalidRoleValueException
776 addRelationInt(false,
777 null,
778 relationObjectName,
779 relId,
780 relTypeName,
781 roleList);
782 // Adds relation MBean ObjectName in map
783 synchronized(myRelMBeanObjName2RelIdMap) {
784 myRelMBeanObjName2RelIdMap.put(relationObjectName, relId);
785 }
786
787 // Updates flag to specify that the relation is managed by the Relation
788 // Service
789 // This flag and setter are inherited from RelationSupport and not parts
790 // of the Relation interface, so may be not supported.
791 try {
792 myMBeanServer.setAttribute(relationObjectName,
793 new Attribute(
794 "RelationServiceManagementFlag",
795 Boolean.TRUE));
796 } catch (Exception exc) {
797 // OK : The flag is not supported.
798 }
799
800 // Updates listener information to received notification for
801 // unregistration of this MBean
802 List<ObjectName> newRefList = new ArrayList<ObjectName>();
803 newRefList.add(relationObjectName);
804 updateUnregistrationListener(newRefList, null);
805
806 RELATION_LOGGER.exiting(RelationService.class.getName(),
807 "addRelation");
808 return;
809 }
810
811 /**
812 * If the relation is represented by an MBean (created by the user and
813 * added as a relation in the Relation Service), returns the ObjectName of
814 * the MBean.
815 *
816 * @param relationId relation id identifying the relation
817 *
818 * @return ObjectName of the corresponding relation MBean, or null if
819 * the relation is not an MBean.
820 *
821 * @exception IllegalArgumentException if null parameter
822 * @exception RelationNotFoundException there is no relation associated
823 * to that id
824 */
825 public ObjectName isRelationMBean(String relationId)
826 throws IllegalArgumentException,
827 RelationNotFoundException{
828
829 if (relationId == null) {
830 String excMsg = "Invalid parameter.";
831 throw new IllegalArgumentException(excMsg);
832 }
833
834 RELATION_LOGGER.entering(RelationService.class.getName(),
835 "isRelationMBean", relationId);
836
837 // Can throw RelationNotFoundException
838 Object result = getRelation(relationId);
839 if (result instanceof ObjectName) {
840 return ((ObjectName)result);
841 } else {
842 return null;
843 }
844 }
845
846 /**
847 * Returns the relation id associated to the given ObjectName if the
848 * MBean has been added as a relation in the Relation Service.
849 *
850 * @param objectName ObjectName of supposed relation
851 *
852 * @return relation id (String) or null (if the ObjectName is not a
853 * relation handled by the Relation Service)
854 *
855 * @exception IllegalArgumentException if null parameter
856 */
857 public String isRelation(ObjectName objectName)
858 throws IllegalArgumentException {
859
860 if (objectName == null) {
861 String excMsg = "Invalid parameter.";
862 throw new IllegalArgumentException(excMsg);
863 }
864
865 RELATION_LOGGER.entering(RelationService.class.getName(),
866 "isRelation", objectName);
867
868 String result = null;
869 synchronized(myRelMBeanObjName2RelIdMap) {
870 String relId = myRelMBeanObjName2RelIdMap.get(objectName);
871 if (relId != null) {
872 result = relId;
873 }
874 }
875 return result;
876 }
877
878 /**
879 * Checks if there is a relation identified in Relation Service with given
880 * relation id.
881 *
882 * @param relationId relation id identifying the relation
883 *
884 * @return boolean: true if there is a relation, false else
885 *
886 * @exception IllegalArgumentException if null parameter
887 */
888 public Boolean hasRelation(String relationId)
889 throws IllegalArgumentException {
890
891 if (relationId == null) {
892 String excMsg = "Invalid parameter.";
893 throw new IllegalArgumentException(excMsg);
894 }
895
896 RELATION_LOGGER.entering(RelationService.class.getName(),
897 "hasRelation", relationId);
898
899 try {
900 // Can throw RelationNotFoundException
901 Object result = getRelation(relationId);
902 return true;
903 } catch (RelationNotFoundException exc) {
904 return false;
905 }
906 }
907
908 /**
909 * Returns all the relation ids for all the relations handled by the
910 * Relation Service.
911 *
912 * @return ArrayList of String
913 */
914 public List<String> getAllRelationIds() {
915 List<String> result = null;
916 synchronized(myRelId2ObjMap) {
917 result = new ArrayList<String>(myRelId2ObjMap.keySet());
918 }
919 return result;
920 }
921
922 /**
923 * Checks if given Role can be read in a relation of the given type.
924 *
925 * @param roleName name of role to be checked
926 * @param relationTypeName name of the relation type
927 *
928 * @return an Integer wrapping an integer corresponding to possible
929 * problems represented as constants in RoleUnresolved:
930 * <P>- 0 if role can be read
931 * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME
932 * <P>- integer corresponding to RoleStatus.ROLE_NOT_READABLE
933 *
934 * @exception IllegalArgumentException if null parameter
935 * @exception RelationTypeNotFoundException if the relation type is not
936 * known in the Relation Service
937 */
938 public Integer checkRoleReading(String roleName,
939 String relationTypeName)
940 throws IllegalArgumentException,
941 RelationTypeNotFoundException {
942
943 if (roleName == null || relationTypeName == null) {
944 String excMsg = "Invalid parameter.";
945 throw new IllegalArgumentException(excMsg);
946 }
947
948 RELATION_LOGGER.entering(RelationService.class.getName(),
949 "checkRoleReading", new Object[] {roleName, relationTypeName});
950
951 Integer result = null;
952
953 // Can throw a RelationTypeNotFoundException
954 RelationType relType = getRelationType(relationTypeName);
955
956 try {
957 // Can throw a RoleInfoNotFoundException to be transformed into
958 // returned value RoleStatus.NO_ROLE_WITH_NAME
959 RoleInfo roleInfo = relType.getRoleInfo(roleName);
960
961 result = checkRoleInt(1,
962 roleName,
963 null,
964 roleInfo,
965 false);
966
967 } catch (RoleInfoNotFoundException exc) {
968 result = new Integer(RoleStatus.NO_ROLE_WITH_NAME);
969 }
970
971 RELATION_LOGGER.exiting(RelationService.class.getName(),
972 "checkRoleReading");
973 return result;
974 }
975
976 /**
977 * Checks if given Role can be set in a relation of given type.
978 *
979 * @param role role to be checked
980 * @param relationTypeName name of relation type
981 * @param initFlag flag to specify that the checking is done for the
982 * initialization of a role, write access shall not be verified.
983 *
984 * @return an Integer wrapping an integer corresponding to possible
985 * problems represented as constants in RoleUnresolved:
986 * <P>- 0 if role can be set
987 * <P>- integer corresponding to RoleStatus.NO_ROLE_WITH_NAME
988 * <P>- integer for RoleStatus.ROLE_NOT_WRITABLE
989 * <P>- integer for RoleStatus.LESS_THAN_MIN_ROLE_DEGREE
990 * <P>- integer for RoleStatus.MORE_THAN_MAX_ROLE_DEGREE
991 * <P>- integer for RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS
992 * <P>- integer for RoleStatus.REF_MBEAN_NOT_REGISTERED
993 *
994 * @exception IllegalArgumentException if null parameter
995 * @exception RelationTypeNotFoundException if unknown relation type
996 */
997 public Integer checkRoleWriting(Role role,
998 String relationTypeName,
999 Boolean initFlag)
1000 throws IllegalArgumentException,
1001 RelationTypeNotFoundException {
1002
1003 if (role == null ||
1004 relationTypeName == null ||
1005 initFlag == null) {
1006 String excMsg = "Invalid parameter.";
1007 throw new IllegalArgumentException(excMsg);
1008 }
1009
1010 RELATION_LOGGER.entering(RelationService.class.getName(),
1011 "checkRoleWriting",
1012 new Object[] {role, relationTypeName, initFlag});
1013
1014 // Can throw a RelationTypeNotFoundException
1015 RelationType relType = getRelationType(relationTypeName);
1016
1017 String roleName = role.getRoleName();
1018 List<ObjectName> roleValue = role.getRoleValue();
1019 boolean writeChkFlag = true;
1020 if (initFlag.booleanValue()) {
1021 writeChkFlag = false;
1022 }
1023
1024 RoleInfo roleInfo = null;
1025 try {
1026 roleInfo = relType.getRoleInfo(roleName);
1027 } catch (RoleInfoNotFoundException exc) {
1028 RELATION_LOGGER.exiting(RelationService.class.getName(),
1029 "checkRoleWriting");
1030 return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
1031 }
1032
1033 Integer result = checkRoleInt(2,
1034 roleName,
1035 roleValue,
1036 roleInfo,
1037 writeChkFlag);
1038
1039 RELATION_LOGGER.exiting(RelationService.class.getName(),
1040 "checkRoleWriting");
1041 return result;
1042 }
1043
1044 /**
1045 * Sends a notification (RelationNotification) for a relation creation.
1046 * The notification type is:
1047 * <P>- RelationNotification.RELATION_BASIC_CREATION if the relation is an
1048 * object internal to the Relation Service
1049 * <P>- RelationNotification.RELATION_MBEAN_CREATION if the relation is a
1050 * MBean added as a relation.
1051 * <P>The source object is the Relation Service itself.
1052 * <P>It is called in Relation Service createRelation() and
1053 * addRelation() methods.
1054 *
1055 * @param relationId relation identifier of the updated relation
1056 *
1057 * @exception IllegalArgumentException if null parameter
1058 * @exception RelationNotFoundException if there is no relation for given
1059 * relation id
1060 */
1061 public void sendRelationCreationNotification(String relationId)
1062 throws IllegalArgumentException,
1063 RelationNotFoundException {
1064
1065 if (relationId == null) {
1066 String excMsg = "Invalid parameter.";
1067 throw new IllegalArgumentException(excMsg);
1068 }
1069
1070 RELATION_LOGGER.entering(RelationService.class.getName(),
1071 "sendRelationCreationNotification", relationId);
1072
1073 // Message
1074 StringBuilder ntfMsg = new StringBuilder("Creation of relation ");
1075 ntfMsg.append(relationId);
1076
1077 // Can throw RelationNotFoundException
1078 sendNotificationInt(1,
1079 ntfMsg.toString(),
1080 relationId,
1081 null,
1082 null,
1083 null,
1084 null);
1085
1086 RELATION_LOGGER.exiting(RelationService.class.getName(),
1087 "sendRelationCreationNotification");
1088 return;
1089 }
1090
1091 /**
1092 * Sends a notification (RelationNotification) for a role update in the
1093 * given relation. The notification type is:
1094 * <P>- RelationNotification.RELATION_BASIC_UPDATE if the relation is an
1095 * object internal to the Relation Service
1096 * <P>- RelationNotification.RELATION_MBEAN_UPDATE if the relation is a
1097 * MBean added as a relation.
1098 * <P>The source object is the Relation Service itself.
1099 * <P>It is called in relation MBean setRole() (for given role) and
1100 * setRoles() (for each role) methods (implementation provided in
1101 * RelationSupport class).
1102 * <P>It is also called in Relation Service setRole() (for given role) and
1103 * setRoles() (for each role) methods.
1104 *
1105 * @param relationId relation identifier of the updated relation
1106 * @param newRole new role (name and new value)
1107 * @param oldValue old role value (List of ObjectName objects)
1108 *
1109 * @exception IllegalArgumentException if null parameter
1110 * @exception RelationNotFoundException if there is no relation for given
1111 * relation id
1112 */
1113 public void sendRoleUpdateNotification(String relationId,
1114 Role newRole,
1115 List<ObjectName> oldValue)
1116 throws IllegalArgumentException,
1117 RelationNotFoundException {
1118
1119 if (relationId == null ||
1120 newRole == null ||
1121 oldValue == null) {
1122 String excMsg = "Invalid parameter.";
1123 throw new IllegalArgumentException(excMsg);
1124 }
1125
1126 if (!(oldValue instanceof ArrayList))
1127 oldValue = new ArrayList<ObjectName>(oldValue);
1128
1129 RELATION_LOGGER.entering(RelationService.class.getName(),
1130 "sendRoleUpdateNotification",
1131 new Object[] {relationId, newRole, oldValue});
1132
1133 String roleName = newRole.getRoleName();
1134 List<ObjectName> newRoleVal = newRole.getRoleValue();
1135
1136 // Message
1137 String newRoleValString = Role.roleValueToString(newRoleVal);
1138 String oldRoleValString = Role.roleValueToString(oldValue);
1139 StringBuilder ntfMsg = new StringBuilder("Value of role ");
1140 ntfMsg.append(roleName);
1141 ntfMsg.append(" has changed\nOld value:\n");
1142 ntfMsg.append(oldRoleValString);
1143 ntfMsg.append("\nNew value:\n");
1144 ntfMsg.append(newRoleValString);
1145
1146 // Can throw a RelationNotFoundException
1147 sendNotificationInt(2,
1148 ntfMsg.toString(),
1149 relationId,
1150 null,
1151 roleName,
1152 newRoleVal,
1153 oldValue);
1154
1155 RELATION_LOGGER.exiting(RelationService.class.getName(),
1156 "sendRoleUpdateNotification");
1157 }
1158
1159 /**
1160 * Sends a notification (RelationNotification) for a relation removal.
1161 * The notification type is:
1162 * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation is an
1163 * object internal to the Relation Service
1164 * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is a
1165 * MBean added as a relation.
1166 * <P>The source object is the Relation Service itself.
1167 * <P>It is called in Relation Service removeRelation() method.
1168 *
1169 * @param relationId relation identifier of the updated relation
1170 * @param unregMBeanList List of ObjectNames of MBeans expected
1171 * to be unregistered due to relation removal (can be null)
1172 *
1173 * @exception IllegalArgumentException if null parameter
1174 * @exception RelationNotFoundException if there is no relation for given
1175 * relation id
1176 */
1177 public void sendRelationRemovalNotification(String relationId,
1178 List<ObjectName> unregMBeanList)
1179 throws IllegalArgumentException,
1180 RelationNotFoundException {
1181
1182 if (relationId == null) {
1183 String excMsg = "Invalid parameter";
1184 throw new IllegalArgumentException(excMsg);
1185 }
1186
1187 RELATION_LOGGER.entering(RelationService.class.getName(),
1188 "sendRelationRemovalNotification",
1189 new Object[] {relationId, unregMBeanList});
1190
1191 // Can throw RelationNotFoundException
1192 sendNotificationInt(3,
1193 "Removal of relation " + relationId,
1194 relationId,
1195 unregMBeanList,
1196 null,
1197 null,
1198 null);
1199
1200
1201 RELATION_LOGGER.exiting(RelationService.class.getName(),
1202 "sendRelationRemovalNotification");
1203 return;
1204 }
1205
1206 /**
1207 * Handles update of the Relation Service role map for the update of given
1208 * role in given relation.
1209 * <P>It is called in relation MBean setRole() (for given role) and
1210 * setRoles() (for each role) methods (implementation provided in
1211 * RelationSupport class).
1212 * <P>It is also called in Relation Service setRole() (for given role) and
1213 * setRoles() (for each role) methods.
1214 * <P>To allow the Relation Service to maintain the consistency (in case
1215 * of MBean unregistration) and to be able to perform queries, this method
1216 * must be called when a role is updated.
1217 *
1218 * @param relationId relation identifier of the updated relation
1219 * @param newRole new role (name and new value)
1220 * @param oldValue old role value (List of ObjectName objects)
1221 *
1222 * @exception IllegalArgumentException if null parameter
1223 * @exception RelationServiceNotRegisteredException if the Relation
1224 * Service is not registered in the MBean Server
1225 * @exception RelationNotFoundException if no relation for given id.
1226 */
1227 public void updateRoleMap(String relationId,
1228 Role newRole,
1229 List<ObjectName> oldValue)
1230 throws IllegalArgumentException,
1231 RelationServiceNotRegisteredException,
1232 RelationNotFoundException {
1233
1234 if (relationId == null ||
1235 newRole == null ||
1236 oldValue == null) {
1237 String excMsg = "Invalid parameter.";
1238 throw new IllegalArgumentException(excMsg);
1239 }
1240
1241 RELATION_LOGGER.entering(RelationService.class.getName(),
1242 "updateRoleMap", new Object[] {relationId, newRole, oldValue});
1243
1244 // Can throw RelationServiceNotRegisteredException
1245 isActive();
1246
1247 // Verifies the relation has been added in the Relation Service
1248 // Can throw a RelationNotFoundException
1249 Object result = getRelation(relationId);
1250
1251 String roleName = newRole.getRoleName();
1252 List<ObjectName> newRoleValue = newRole.getRoleValue();
1253 // Note: no need to test if oldValue not null before cloning,
1254 // tested above.
1255 List<ObjectName> oldRoleValue =
1256 new ArrayList<ObjectName>(oldValue);
1257
1258 // List of ObjectNames of new referenced MBeans
1259 List<ObjectName> newRefList = new ArrayList<ObjectName>();
1260
1261 for (ObjectName currObjName : newRoleValue) {
1262
1263 // Checks if this ObjectName was already present in old value
1264 // Note: use copy (oldRoleValue) instead of original
1265 // oldValue to speed up, as oldRoleValue is decreased
1266 // by removing unchanged references :)
1267 int currObjNamePos = oldRoleValue.indexOf(currObjName);
1268
1269 if (currObjNamePos == -1) {
1270 // New reference to an ObjectName
1271
1272 // Stores this reference into map
1273 // Returns true if new reference, false if MBean already
1274 // referenced
1275 boolean isNewFlag = addNewMBeanReference(currObjName,
1276 relationId,
1277 roleName);
1278
1279 if (isNewFlag) {
1280 // Adds it into list of new reference
1281 newRefList.add(currObjName);
1282 }
1283
1284 } else {
1285 // MBean was already referenced in old value
1286
1287 // Removes it from old value (local list) to ignore it when
1288 // looking for remove MBean references
1289 oldRoleValue.remove(currObjNamePos);
1290 }
1291 }
1292
1293 // List of ObjectNames of MBeans no longer referenced
1294 List<ObjectName> obsRefList = new ArrayList<ObjectName>();
1295
1296 // Each ObjectName remaining in oldRoleValue is an ObjectName no longer
1297 // referenced in new value
1298 for (ObjectName currObjName : oldRoleValue) {
1299 // Removes MBean reference from map
1300 // Returns true if the MBean is no longer referenced in any
1301 // relation
1302 boolean noLongerRefFlag = removeMBeanReference(currObjName,
1303 relationId,
1304 roleName,
1305 false);
1306
1307 if (noLongerRefFlag) {
1308 // Adds it into list of references to be removed
1309 obsRefList.add(currObjName);
1310 }
1311 }
1312
1313 // To avoid having one listener per ObjectName of referenced MBean,
1314 // and to increase performances, there is only one listener recording
1315 // all ObjectNames of interest
1316 updateUnregistrationListener(newRefList, obsRefList);
1317
1318 RELATION_LOGGER.exiting(RelationService.class.getName(),
1319 "updateRoleMap");
1320 return;
1321 }
1322
1323 /**
1324 * Removes given relation from the Relation Service.
1325 * <P>A RelationNotification notification is sent, its type being:
1326 * <P>- RelationNotification.RELATION_BASIC_REMOVAL if the relation was
1327 * only internal to the Relation Service
1328 * <P>- RelationNotification.RELATION_MBEAN_REMOVAL if the relation is
1329 * registered as an MBean.
1330 * <P>For MBeans referenced in such relation, nothing will be done,
1331 *
1332 * @param relationId relation id of the relation to be removed
1333 *
1334 * @exception RelationServiceNotRegisteredException if the Relation
1335 * Service is not registered in the MBean Server
1336 * @exception IllegalArgumentException if null parameter
1337 * @exception RelationNotFoundException if no relation corresponding to
1338 * given relation id
1339 */
1340 public void removeRelation(String relationId)
1341 throws RelationServiceNotRegisteredException,
1342 IllegalArgumentException,
1343 RelationNotFoundException {
1344
1345 // Can throw RelationServiceNotRegisteredException
1346 isActive();
1347
1348 if (relationId == null) {
1349 String excMsg = "Invalid parameter.";
1350 throw new IllegalArgumentException(excMsg);
1351 }
1352
1353 RELATION_LOGGER.entering(RelationService.class.getName(),
1354 "removeRelation", relationId);
1355
1356 // Checks there is a relation with this id
1357 // Can throw RelationNotFoundException
1358 Object result = getRelation(relationId);
1359
1360 // Removes it from listener filter
1361 if (result instanceof ObjectName) {
1362 List<ObjectName> obsRefList = new ArrayList<ObjectName>();
1363 obsRefList.add((ObjectName)result);
1364 // Can throw a RelationServiceNotRegisteredException
1365 updateUnregistrationListener(null, obsRefList);
1366 }
1367
1368 // Sends a notification
1369 // Note: has to be done FIRST as needs the relation to be still in the
1370 // Relation Service
1371 // No RelationNotFoundException as checked above
1372
1373 // Revisit [cebro] Handle CIM "Delete" and "IfDeleted" qualifiers:
1374 // deleting the relation can mean to delete referenced MBeans. In
1375 // that case, MBeans to be unregistered are put in a list sent along
1376 // with the notification below
1377
1378 // Can throw a RelationNotFoundException (but detected above)
1379 sendRelationRemovalNotification(relationId, null);
1380
1381 // Removes the relation from various internal maps
1382
1383 // - MBean reference map
1384 // Retrieves the MBeans referenced in this relation
1385 // Note: here we cannot use removeMBeanReference() because it would
1386 // require to know the MBeans referenced in the relation. For
1387 // that it would be necessary to call 'getReferencedMBeans()'
1388 // on the relation itself. Ok if it is an internal one, but if
1389 // it is an MBean, it is possible it is already unregistered, so
1390 // not available through the MBean Server.
1391 List<ObjectName> refMBeanList = new ArrayList<ObjectName>();
1392 // List of MBeans no longer referenced in any relation, to be
1393 // removed fom the map
1394 List<ObjectName> nonRefObjNameList = new ArrayList<ObjectName>();
1395
1396 synchronized(myRefedMBeanObjName2RelIdsMap) {
1397
1398 for (ObjectName currRefObjName :
1399 myRefedMBeanObjName2RelIdsMap.keySet()) {
1400
1401 // Retrieves relations where the MBean is referenced
1402 Map<String,List<String>> relIdMap =
1403 myRefedMBeanObjName2RelIdsMap.get(currRefObjName);
1404
1405 if (relIdMap.containsKey(relationId)) {
1406 relIdMap.remove(relationId);
1407 refMBeanList.add(currRefObjName);
1408 }
1409
1410 if (relIdMap.isEmpty()) {
1411 // MBean no longer referenced
1412 // Note: do not remove it here because pointed by the
1413 // iterator!
1414 nonRefObjNameList.add(currRefObjName);
1415 }
1416 }
1417
1418 // Cleans MBean reference map by removing MBeans no longer
1419 // referenced
1420 for (ObjectName currRefObjName : nonRefObjNameList) {
1421 myRefedMBeanObjName2RelIdsMap.remove(currRefObjName);
1422 }
1423 }
1424
1425 // - Relation id to object map
1426 synchronized(myRelId2ObjMap) {
1427 myRelId2ObjMap.remove(relationId);
1428 }
1429
1430 if (result instanceof ObjectName) {
1431 // - ObjectName to relation id map
1432 synchronized(myRelMBeanObjName2RelIdMap) {
1433 myRelMBeanObjName2RelIdMap.remove((ObjectName)result);
1434 }
1435 }
1436
1437 // Relation id to relation type name map
1438 // First retrieves the relation type name
1439 String relTypeName = null;
1440 synchronized(myRelId2RelTypeMap) {
1441 relTypeName = myRelId2RelTypeMap.get(relationId);
1442 myRelId2RelTypeMap.remove(relationId);
1443 }
1444 // - Relation type name to relation id map
1445 synchronized(myRelType2RelIdsMap) {
1446 List<String> relIdList = myRelType2RelIdsMap.get(relTypeName);
1447 if (relIdList != null) {
1448 // Can be null if called from removeRelationType()
1449 relIdList.remove(relationId);
1450 if (relIdList.isEmpty()) {
1451 // No other relation of that type
1452 myRelType2RelIdsMap.remove(relTypeName);
1453 }
1454 }
1455 }
1456
1457 RELATION_LOGGER.exiting(RelationService.class.getName(),
1458 "removeRelation");
1459 return;
1460 }
1461
1462 /**
1463 * Purges the relations.
1464 *
1465 * <P>Depending on the purgeFlag value, this method is either called
1466 * automatically when a notification is received for the unregistration of
1467 * an MBean referenced in a relation (if the flag is set to true), or not
1468 * (if the flag is set to false).
1469 * <P>In that case it is up to the user to call it to maintain the
1470 * consistency of the relations. To be kept in mind that if an MBean is
1471 * unregistered and the purge not done immediately, if the ObjectName is
1472 * reused and assigned to another MBean referenced in a relation, calling
1473 * manually this purgeRelations() method will cause trouble, as will
1474 * consider the ObjectName as corresponding to the unregistered MBean, not
1475 * seeing the new one.
1476 *
1477 * <P>The behavior depends on the cardinality of the role where the
1478 * unregistered MBean is referenced:
1479 * <P>- if removing one MBean reference in the role makes its number of
1480 * references less than the minimum degree, the relation has to be removed.
1481 * <P>- if the remaining number of references after removing the MBean
1482 * reference is still in the cardinality range, keep the relation and
1483 * update it calling its handleMBeanUnregistration() callback.
1484 *
1485 * @exception RelationServiceNotRegisteredException if the Relation
1486 * Service is not registered in the MBean Server.
1487 */
1488 public void purgeRelations()
1489 throws RelationServiceNotRegisteredException {
1490
1491 RELATION_LOGGER.entering(RelationService.class.getName(),
1492 "purgeRelations");
1493
1494 // Can throw RelationServiceNotRegisteredException
1495 isActive();
1496
1497 // Revisit [cebro] Handle the CIM "Delete" and "IfDeleted" qualifier:
1498 // if the unregistered MBean has the "IfDeleted" qualifier,
1499 // possible that the relation itself or other referenced MBeans
1500 // have to be removed (then a notification would have to be sent
1501 // to inform that they should be unregistered.
1502
1503
1504 // Clones the list of notifications to be able to still receive new
1505 // notifications while proceeding those ones
1506 List<MBeanServerNotification> localUnregNtfList;
1507 synchronized(myUnregNtfList) {
1508 localUnregNtfList =
1509 new ArrayList<MBeanServerNotification>(myUnregNtfList);
1510 // Resets list
1511 myUnregNtfList = new ArrayList<MBeanServerNotification>();
1512 }
1513
1514
1515 // Updates the listener filter to avoid receiving notifications for
1516 // those MBeans again
1517 // Makes also a local "myRefedMBeanObjName2RelIdsMap" map, mapping
1518 // ObjectName -> relId -> roles, to remove the MBean from the global
1519 // map
1520 // List of references to be removed from the listener filter
1521 List<ObjectName> obsRefList = new ArrayList<ObjectName>();
1522 // Map including ObjectNames for unregistered MBeans, with
1523 // referencing relation ids and roles
1524 Map<ObjectName,Map<String,List<String>>> localMBean2RelIdMap =
1525 new HashMap<ObjectName,Map<String,List<String>>>();
1526
1527 synchronized(myRefedMBeanObjName2RelIdsMap) {
1528 for (MBeanServerNotification currNtf : localUnregNtfList) {
1529
1530 ObjectName unregMBeanName = currNtf.getMBeanName();
1531
1532 // Adds the unregsitered MBean in the list of references to
1533 // remove from the listener filter
1534 obsRefList.add(unregMBeanName);
1535
1536 // Retrieves the associated map of relation ids and roles
1537 Map<String,List<String>> relIdMap =
1538 myRefedMBeanObjName2RelIdsMap.get(unregMBeanName);
1539 localMBean2RelIdMap.put(unregMBeanName, relIdMap);
1540
1541 myRefedMBeanObjName2RelIdsMap.remove(unregMBeanName);
1542 }
1543 }
1544
1545 // Updates the listener
1546 // Can throw RelationServiceNotRegisteredException
1547 updateUnregistrationListener(null, obsRefList);
1548
1549 for (MBeanServerNotification currNtf : localUnregNtfList) {
1550
1551 ObjectName unregMBeanName = currNtf.getMBeanName();
1552
1553 // Retrieves the relations where the MBean is referenced
1554 Map<String,List<String>> localRelIdMap =
1555 localMBean2RelIdMap.get(unregMBeanName);
1556
1557 // List of relation ids where the unregistered MBean is
1558 // referenced
1559 for (Map.Entry<String,List<String>> currRel :
1560 localRelIdMap.entrySet()) {
1561 final String currRelId = currRel.getKey();
1562 // List of roles of the relation where the MBean is
1563 // referenced
1564 List<String> localRoleNameList = currRel.getValue();
1565
1566 // Checks if the relation has to be removed or not,
1567 // regarding expected minimum role cardinality and current
1568 // number of references after removal of the current one
1569 // If the relation is kept, calls
1570 // handleMBeanUnregistration() callback of the relation to
1571 // update it
1572 //
1573 // Can throw RelationServiceNotRegisteredException
1574 //
1575 // Shall not throw RelationNotFoundException,
1576 // RoleNotFoundException, MBeanException
1577 try {
1578 handleReferenceUnregistration(currRelId,
1579 unregMBeanName,
1580 localRoleNameList);
1581 } catch (RelationNotFoundException exc1) {
1582 throw new RuntimeException(exc1.getMessage());
1583 } catch (RoleNotFoundException exc2) {
1584 throw new RuntimeException(exc2.getMessage());
1585 }
1586 }
1587 }
1588
1589 RELATION_LOGGER.exiting(RelationService.class.getName(),
1590 "purgeRelations");
1591 return;
1592 }
1593
1594 /**
1595 * Retrieves the relations where a given MBean is referenced.
1596 * <P>This corresponds to the CIM "References" and "ReferenceNames"
1597 * operations.
1598 *
1599 * @param mbeanName ObjectName of MBean
1600 * @param relationTypeName can be null; if specified, only the relations
1601 * of that type will be considered in the search. Else all relation types
1602 * are considered.
1603 * @param roleName can be null; if specified, only the relations
1604 * where the MBean is referenced in that role will be returned. Else all
1605 * roles are considered.
1606 *
1607 * @return an HashMap, where the keys are the relation ids of the relations
1608 * where the MBean is referenced, and the value is, for each key,
1609 * an ArrayList of role names (as an MBean can be referenced in several
1610 * roles in the same relation).
1611 *
1612 * @exception IllegalArgumentException if null parameter
1613 */
1614 public Map<String,List<String>>
1615 findReferencingRelations(ObjectName mbeanName,
1616 String relationTypeName,
1617 String roleName)
1618 throws IllegalArgumentException {
1619
1620 if (mbeanName == null) {
1621 String excMsg = "Invalid parameter.";
1622 throw new IllegalArgumentException(excMsg);
1623 }
1624
1625 RELATION_LOGGER.entering(RelationService.class.getName(),
1626 "findReferencingRelations",
1627 new Object[] {mbeanName, relationTypeName, roleName});
1628
1629 Map<String,List<String>> result = new HashMap<String,List<String>>();
1630
1631 synchronized(myRefedMBeanObjName2RelIdsMap) {
1632
1633 // Retrieves the relations referencing the MBean
1634 Map<String,List<String>> relId2RoleNamesMap =
1635 myRefedMBeanObjName2RelIdsMap.get(mbeanName);
1636
1637 if (relId2RoleNamesMap != null) {
1638
1639 // Relation Ids where the MBean is referenced
1640 Set<String> allRelIdSet = relId2RoleNamesMap.keySet();
1641
1642 // List of relation ids of interest regarding the selected
1643 // relation type
1644 List<String> relIdList = null;
1645 if (relationTypeName == null) {
1646 // Considers all relations
1647 relIdList = new ArrayList<String>(allRelIdSet);
1648
1649 } else {
1650
1651 relIdList = new ArrayList<String>();
1652
1653 // Considers only the relation ids for relations of given
1654 // type
1655 for (String currRelId : allRelIdSet) {
1656
1657 // Retrieves its relation type
1658 String currRelTypeName = null;
1659 synchronized(myRelId2RelTypeMap) {
1660 currRelTypeName =
1661 myRelId2RelTypeMap.get(currRelId);
1662 }
1663
1664 if (currRelTypeName.equals(relationTypeName)) {
1665
1666 relIdList.add(currRelId);
1667
1668 }
1669 }
1670 }
1671
1672 // Now looks at the roles where the MBean is expected to be
1673 // referenced
1674
1675 for (String currRelId : relIdList) {
1676 // Retrieves list of role names where the MBean is
1677 // referenced
1678 List<String> currRoleNameList =
1679 relId2RoleNamesMap.get(currRelId);
1680
1681 if (roleName == null) {
1682 // All roles to be considered
1683 // Note: no need to test if list not null before
1684 // cloning, MUST be not null else bug :(
1685 result.put(currRelId,
1686 new ArrayList<String>(currRoleNameList));
1687
1688 } else if (currRoleNameList.contains(roleName)) {
1689 // Filters only the relations where the MBean is
1690 // referenced in // given role
1691 List<String> dummyList = new ArrayList<String>();
1692 dummyList.add(roleName);
1693 result.put(currRelId, dummyList);
1694 }
1695 }
1696 }
1697 }
1698
1699 RELATION_LOGGER.exiting(RelationService.class.getName(),
1700 "findReferencingRelations");
1701 return result;
1702 }
1703
1704 /**
1705 * Retrieves the MBeans associated to given one in a relation.
1706 * <P>This corresponds to CIM Associators and AssociatorNames operations.
1707 *
1708 * @param mbeanName ObjectName of MBean
1709 * @param relationTypeName can be null; if specified, only the relations
1710 * of that type will be considered in the search. Else all
1711 * relation types are considered.
1712 * @param roleName can be null; if specified, only the relations
1713 * where the MBean is referenced in that role will be considered. Else all
1714 * roles are considered.
1715 *
1716 * @return an HashMap, where the keys are the ObjectNames of the MBeans
1717 * associated to given MBean, and the value is, for each key, an ArrayList
1718 * of the relation ids of the relations where the key MBean is
1719 * associated to given one (as they can be associated in several different
1720 * relations).
1721 *
1722 * @exception IllegalArgumentException if null parameter
1723 */
1724 public Map<ObjectName,List<String>>
1725 findAssociatedMBeans(ObjectName mbeanName,
1726 String relationTypeName,
1727 String roleName)
1728 throws IllegalArgumentException {
1729
1730 if (mbeanName == null) {
1731 String excMsg = "Invalid parameter.";
1732 throw new IllegalArgumentException(excMsg);
1733 }
1734
1735 RELATION_LOGGER.entering(RelationService.class.getName(),
1736 "findAssociatedMBeans",
1737 new Object[] {mbeanName, relationTypeName, roleName});
1738
1739 // Retrieves the map <relation id> -> <role names> for those
1740 // criterias
1741 Map<String,List<String>> relId2RoleNamesMap =
1742 findReferencingRelations(mbeanName,
1743 relationTypeName,
1744 roleName);
1745
1746 Map<ObjectName,List<String>> result =
1747 new HashMap<ObjectName,List<String>>();
1748
1749 for (String currRelId : relId2RoleNamesMap.keySet()) {
1750
1751 // Retrieves ObjectNames of MBeans referenced in this relation
1752 //
1753 // Shall not throw a RelationNotFoundException if incorrect status
1754 // of maps :(
1755 Map<ObjectName,List<String>> objName2RoleNamesMap;
1756 try {
1757 objName2RoleNamesMap = getReferencedMBeans(currRelId);
1758 } catch (RelationNotFoundException exc) {
1759 throw new RuntimeException(exc.getMessage());
1760 }
1761
1762 // For each MBean associated to given one in a relation, adds the
1763 // association <ObjectName> -> <relation id> into result map
1764 for (ObjectName currObjName : objName2RoleNamesMap.keySet()) {
1765
1766 if (!(currObjName.equals(mbeanName))) {
1767
1768 // Sees if this MBean is already associated to the given
1769 // one in another relation
1770 List<String> currRelIdList = result.get(currObjName);
1771 if (currRelIdList == null) {
1772
1773 currRelIdList = new ArrayList<String>();
1774 currRelIdList.add(currRelId);
1775 result.put(currObjName, currRelIdList);
1776
1777 } else {
1778 currRelIdList.add(currRelId);
1779 }
1780 }
1781 }
1782 }
1783
1784 RELATION_LOGGER.exiting(RelationService.class.getName(),
1785 "findAssociatedMBeans");
1786 return result;
1787 }
1788
1789 /**
1790 * Returns the relation ids for relations of the given type.
1791 *
1792 * @param relationTypeName relation type name
1793 *
1794 * @return an ArrayList of relation ids.
1795 *
1796 * @exception IllegalArgumentException if null parameter
1797 * @exception RelationTypeNotFoundException if there is no relation type
1798 * with that name.
1799 */
1800 public List<String> findRelationsOfType(String relationTypeName)
1801 throws IllegalArgumentException,
1802 RelationTypeNotFoundException {
1803
1804 if (relationTypeName == null) {
1805 String excMsg = "Invalid parameter.";
1806 throw new IllegalArgumentException(excMsg);
1807 }
1808
1809 RELATION_LOGGER.entering(RelationService.class.getName(),
1810 "findRelationsOfType");
1811
1812 // Can throw RelationTypeNotFoundException
1813 RelationType relType = getRelationType(relationTypeName);
1814
1815 List<String> result;
1816 synchronized(myRelType2RelIdsMap) {
1817 List<String> result1 = myRelType2RelIdsMap.get(relationTypeName);
1818 if (result1 == null)
1819 result = new ArrayList<String>();
1820 else
1821 result = new ArrayList<String>(result1);
1822 }
1823
1824 RELATION_LOGGER.exiting(RelationService.class.getName(),
1825 "findRelationsOfType");
1826 return result;
1827 }
1828
1829 /**
1830 * Retrieves role value for given role name in given relation.
1831 *
1832 * @param relationId relation id
1833 * @param roleName name of role
1834 *
1835 * @return the ArrayList of ObjectName objects being the role value
1836 *
1837 * @exception RelationServiceNotRegisteredException if the Relation
1838 * Service is not registered
1839 * @exception IllegalArgumentException if null parameter
1840 * @exception RelationNotFoundException if no relation with given id
1841 * @exception RoleNotFoundException if:
1842 * <P>- there is no role with given name
1843 * <P>or
1844 * <P>- the role is not readable.
1845 *
1846 * @see #setRole
1847 */
1848 public List<ObjectName> getRole(String relationId,
1849 String roleName)
1850 throws RelationServiceNotRegisteredException,
1851 IllegalArgumentException,
1852 RelationNotFoundException,
1853 RoleNotFoundException {
1854
1855 if (relationId == null || roleName == null) {
1856 String excMsg = "Invalid parameter.";
1857 throw new IllegalArgumentException(excMsg);
1858 }
1859
1860 RELATION_LOGGER.entering(RelationService.class.getName(),
1861 "getRole", new Object[] {relationId, roleName});
1862
1863 // Can throw RelationServiceNotRegisteredException
1864 isActive();
1865
1866 // Can throw a RelationNotFoundException
1867 Object relObj = getRelation(relationId);
1868
1869 List<ObjectName> result;
1870
1871 if (relObj instanceof RelationSupport) {
1872 // Internal relation
1873 // Can throw RoleNotFoundException
1874 result = cast(
1875 ((RelationSupport)relObj).getRoleInt(roleName,
1876 true,
1877 this,
1878 false));
1879
1880 } else {
1881 // Relation MBean
1882 Object[] params = new Object[1];
1883 params[0] = roleName;
1884 String[] signature = new String[1];
1885 signature[0] = "java.lang.String";
1886 // Can throw MBeanException wrapping a RoleNotFoundException:
1887 // throw wrapped exception
1888 //
1889 // Shall not throw InstanceNotFoundException or ReflectionException
1890 try {
1891 List<ObjectName> invokeResult = cast(
1892 myMBeanServer.invoke(((ObjectName)relObj),
1893 "getRole",
1894 params,
1895 signature));
1896 if (invokeResult == null || invokeResult instanceof ArrayList)
1897 result = invokeResult;
1898 else
1899 result = new ArrayList<ObjectName>(invokeResult);
1900 } catch (InstanceNotFoundException exc1) {
1901 throw new RuntimeException(exc1.getMessage());
1902 } catch (ReflectionException exc2) {
1903 throw new RuntimeException(exc2.getMessage());
1904 } catch (MBeanException exc3) {
1905 Exception wrappedExc = exc3.getTargetException();
1906 if (wrappedExc instanceof RoleNotFoundException) {
1907 throw ((RoleNotFoundException)wrappedExc);
1908 } else {
1909 throw new RuntimeException(wrappedExc.getMessage());
1910 }
1911 }
1912 }
1913
1914 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRole");
1915 return result;
1916 }
1917
1918 /**
1919 * Retrieves values of roles with given names in given relation.
1920 *
1921 * @param relationId relation id
1922 * @param roleNameArray array of names of roles to be retrieved
1923 *
1924 * @return a RoleResult object, including a RoleList (for roles
1925 * successfully retrieved) and a RoleUnresolvedList (for roles not
1926 * retrieved).
1927 *
1928 * @exception RelationServiceNotRegisteredException if the Relation
1929 * Service is not registered in the MBean Server
1930 * @exception IllegalArgumentException if null parameter
1931 * @exception RelationNotFoundException if no relation with given id
1932 *
1933 * @see #setRoles
1934 */
1935 public RoleResult getRoles(String relationId,
1936 String[] roleNameArray)
1937 throws RelationServiceNotRegisteredException,
1938 IllegalArgumentException,
1939 RelationNotFoundException {
1940
1941 if (relationId == null || roleNameArray == null) {
1942 String excMsg = "Invalid parameter.";
1943 throw new IllegalArgumentException(excMsg);
1944 }
1945
1946 RELATION_LOGGER.entering(RelationService.class.getName(),
1947 "getRoles", relationId);
1948
1949 // Can throw RelationServiceNotRegisteredException
1950 isActive();
1951
1952 // Can throw a RelationNotFoundException
1953 Object relObj = getRelation(relationId);
1954
1955 RoleResult result = null;
1956
1957 if (relObj instanceof RelationSupport) {
1958 // Internal relation
1959 result = ((RelationSupport)relObj).getRolesInt(roleNameArray,
1960 true,
1961 this);
1962 } else {
1963 // Relation MBean
1964 Object[] params = new Object[1];
1965 params[0] = roleNameArray;
1966 String[] signature = new String[1];
1967 try {
1968 signature[0] = (roleNameArray.getClass()).getName();
1969 } catch (Exception exc) {
1970 // OK : This is an array of java.lang.String
1971 // so this should never happen...
1972 }
1973 // Shall not throw InstanceNotFoundException, ReflectionException
1974 // or MBeanException
1975 try {
1976 result = (RoleResult)
1977 (myMBeanServer.invoke(((ObjectName)relObj),
1978 "getRoles",
1979 params,
1980 signature));
1981 } catch (InstanceNotFoundException exc1) {
1982 throw new RuntimeException(exc1.getMessage());
1983 } catch (ReflectionException exc2) {
1984 throw new RuntimeException(exc2.getMessage());
1985 } catch (MBeanException exc3) {
1986 throw new
1987 RuntimeException((exc3.getTargetException()).getMessage());
1988 }
1989 }
1990
1991 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles");
1992 return result;
1993 }
1994
1995 /**
1996 * Returns all roles present in the relation.
1997 *
1998 * @param relationId relation id
1999 *
2000 * @return a RoleResult object, including a RoleList (for roles
2001 * successfully retrieved) and a RoleUnresolvedList (for roles not
2002 * readable).
2003 *
2004 * @exception IllegalArgumentException if null parameter
2005 * @exception RelationNotFoundException if no relation for given id
2006 * @exception RelationServiceNotRegisteredException if the Relation
2007 * Service is not registered in the MBean Server
2008 */
2009 public RoleResult getAllRoles(String relationId)
2010 throws IllegalArgumentException,
2011 RelationNotFoundException,
2012 RelationServiceNotRegisteredException {
2013
2014 if (relationId == null) {
2015 String excMsg = "Invalid parameter.";
2016 throw new IllegalArgumentException(excMsg);
2017 }
2018
2019 RELATION_LOGGER.entering(RelationService.class.getName(),
2020 "getRoles", relationId);
2021
2022 // Can throw a RelationNotFoundException
2023 Object relObj = getRelation(relationId);
2024
2025 RoleResult result = null;
2026
2027 if (relObj instanceof RelationSupport) {
2028 // Internal relation
2029 result = ((RelationSupport)relObj).getAllRolesInt(true, this);
2030
2031 } else {
2032 // Relation MBean
2033 // Shall not throw any Exception
2034 try {
2035 result = (RoleResult)
2036 (myMBeanServer.getAttribute(((ObjectName)relObj),
2037 "AllRoles"));
2038 } catch (Exception exc) {
2039 throw new RuntimeException(exc.getMessage());
2040 }
2041 }
2042
2043 RELATION_LOGGER.exiting(RelationService.class.getName(), "getRoles");
2044 return result;
2045 }
2046
2047 /**
2048 * Retrieves the number of MBeans currently referenced in the given role.
2049 *
2050 * @param relationId relation id
2051 * @param roleName name of role
2052 *
2053 * @return the number of currently referenced MBeans in that role
2054 *
2055 * @exception IllegalArgumentException if null parameter
2056 * @exception RelationNotFoundException if no relation with given id
2057 * @exception RoleNotFoundException if there is no role with given name
2058 */
2059 public Integer getRoleCardinality(String relationId,
2060 String roleName)
2061 throws IllegalArgumentException,
2062 RelationNotFoundException,
2063 RoleNotFoundException {
2064
2065 if (relationId == null || roleName == null) {
2066 String excMsg = "Invalid parameter.";
2067 throw new IllegalArgumentException(excMsg);
2068 }
2069
2070 RELATION_LOGGER.entering(RelationService.class.getName(),
2071 "getRoleCardinality", new Object[] {relationId, roleName});
2072
2073 // Can throw a RelationNotFoundException
2074 Object relObj = getRelation(relationId);
2075
2076 Integer result = null;
2077
2078 if (relObj instanceof RelationSupport) {
2079 // Internal relation
2080 // Can throw RoleNotFoundException
2081 result = ((RelationSupport)relObj).getRoleCardinality(roleName);
2082
2083 } else {
2084 // Relation MBean
2085 Object[] params = new Object[1];
2086 params[0] = roleName;
2087 String[] signature = new String[1];
2088 signature[0] = "java.lang.String";
2089 // Can throw MBeanException wrapping RoleNotFoundException:
2090 // throw wrapped exception
2091 //
2092 // Shall not throw InstanceNotFoundException or ReflectionException
2093 try {
2094 result = (Integer)
2095 (myMBeanServer.invoke(((ObjectName)relObj),
2096 "getRoleCardinality",
2097 params,
2098 signature));
2099 } catch (InstanceNotFoundException exc1) {
2100 throw new RuntimeException(exc1.getMessage());
2101 } catch (ReflectionException exc2) {
2102 throw new RuntimeException(exc2.getMessage());
2103 } catch (MBeanException exc3) {
2104 Exception wrappedExc = exc3.getTargetException();
2105 if (wrappedExc instanceof RoleNotFoundException) {
2106 throw ((RoleNotFoundException)wrappedExc);
2107 } else {
2108 throw new RuntimeException(wrappedExc.getMessage());
2109 }
2110 }
2111 }
2112
2113 RELATION_LOGGER.exiting(RelationService.class.getName(),
2114 "getRoleCardinality");
2115 return result;
2116 }
2117
2118 /**
2119 * Sets the given role in given relation.
2120 * <P>Will check the role according to its corresponding role definition
2121 * provided in relation's relation type
2122 * <P>The Relation Service will keep track of the change to keep the
2123 * consistency of relations by handling referenced MBean unregistrations.
2124 *
2125 * @param relationId relation id
2126 * @param role role to be set (name and new value)
2127 *
2128 * @exception RelationServiceNotRegisteredException if the Relation
2129 * Service is not registered in the MBean Server
2130 * @exception IllegalArgumentException if null parameter
2131 * @exception RelationNotFoundException if no relation with given id
2132 * @exception RoleNotFoundException if the role does not exist or is not
2133 * writable
2134 * @exception InvalidRoleValueException if value provided for role is not
2135 * valid:
2136 * <P>- the number of referenced MBeans in given value is less than
2137 * expected minimum degree
2138 * <P>or
2139 * <P>- the number of referenced MBeans in provided value exceeds expected
2140 * maximum degree
2141 * <P>or
2142 * <P>- one referenced MBean in the value is not an Object of the MBean
2143 * class expected for that role
2144 * <P>or
2145 * <P>- an MBean provided for that role does not exist
2146 *
2147 * @see #getRole
2148 */
2149 public void setRole(String relationId,
2150 Role role)
2151 throws RelationServiceNotRegisteredException,
2152 IllegalArgumentException,
2153 RelationNotFoundException,
2154 RoleNotFoundException,
2155 InvalidRoleValueException {
2156
2157 if (relationId == null || role == null) {
2158 String excMsg = "Invalid parameter.";
2159 throw new IllegalArgumentException(excMsg);
2160 }
2161
2162 RELATION_LOGGER.entering(RelationService.class.getName(),
2163 "setRole", new Object[] {relationId, role});
2164
2165 // Can throw RelationServiceNotRegisteredException
2166 isActive();
2167
2168 // Can throw a RelationNotFoundException
2169 Object relObj = getRelation(relationId);
2170
2171 if (relObj instanceof RelationSupport) {
2172 // Internal relation
2173 // Can throw RoleNotFoundException,
2174 // InvalidRoleValueException and
2175 // RelationServiceNotRegisteredException
2176 //
2177 // Shall not throw RelationTypeNotFoundException
2178 // (as relation exists in the RS, its relation type is known)
2179 try {
2180 ((RelationSupport)relObj).setRoleInt(role,
2181 true,
2182 this,
2183 false);
2184
2185 } catch (RelationTypeNotFoundException exc) {
2186 throw new RuntimeException(exc.getMessage());
2187 }
2188
2189 } else {
2190 // Relation MBean
2191 Object[] params = new Object[1];
2192 params[0] = role;
2193 String[] signature = new String[1];
2194 signature[0] = "javax.management.relation.Role";
2195 // Can throw MBeanException wrapping RoleNotFoundException,
2196 // InvalidRoleValueException
2197 //
2198 // Shall not MBeanException wrapping an MBeanException wrapping
2199 // RelationTypeNotFoundException, or ReflectionException, or
2200 // InstanceNotFoundException
2201 try {
2202 myMBeanServer.setAttribute(((ObjectName)relObj),
2203 new Attribute("Role", role));
2204
2205 } catch (InstanceNotFoundException exc1) {
2206 throw new RuntimeException(exc1.getMessage());
2207 } catch (ReflectionException exc3) {
2208 throw new RuntimeException(exc3.getMessage());
2209 } catch (MBeanException exc2) {
2210 Exception wrappedExc = exc2.getTargetException();
2211 if (wrappedExc instanceof RoleNotFoundException) {
2212 throw ((RoleNotFoundException)wrappedExc);
2213 } else if (wrappedExc instanceof InvalidRoleValueException) {
2214 throw ((InvalidRoleValueException)wrappedExc);
2215 } else {
2216 throw new RuntimeException(wrappedExc.getMessage());
2217
2218 }
2219 } catch (AttributeNotFoundException exc4) {
2220 throw new RuntimeException(exc4.getMessage());
2221 } catch (InvalidAttributeValueException exc5) {
2222 throw new RuntimeException(exc5.getMessage());
2223 }
2224 }
2225
2226 RELATION_LOGGER.exiting(RelationService.class.getName(), "setRole");
2227 return;
2228 }
2229
2230 /**
2231 * Sets the given roles in given relation.
2232 * <P>Will check the role according to its corresponding role definition
2233 * provided in relation's relation type
2234 * <P>The Relation Service keeps track of the changes to keep the
2235 * consistency of relations by handling referenced MBean unregistrations.
2236 *
2237 * @param relationId relation id
2238 * @param roleList list of roles to be set
2239 *
2240 * @return a RoleResult object, including a RoleList (for roles
2241 * successfully set) and a RoleUnresolvedList (for roles not
2242 * set).
2243 *
2244 * @exception RelationServiceNotRegisteredException if the Relation
2245 * Service is not registered in the MBean Server
2246 * @exception IllegalArgumentException if null parameter
2247 * @exception RelationNotFoundException if no relation with given id
2248 *
2249 * @see #getRoles
2250 */
2251 public RoleResult setRoles(String relationId,
2252 RoleList roleList)
2253 throws RelationServiceNotRegisteredException,
2254 IllegalArgumentException,
2255 RelationNotFoundException {
2256
2257 if (relationId == null || roleList == null) {
2258 String excMsg = "Invalid parameter.";
2259 throw new IllegalArgumentException(excMsg);
2260 }
2261
2262 RELATION_LOGGER.entering(RelationService.class.getName(),
2263 "setRoles", new Object[] {relationId, roleList});
2264
2265 // Can throw RelationServiceNotRegisteredException
2266 isActive();
2267
2268 // Can throw a RelationNotFoundException
2269 Object relObj = getRelation(relationId);
2270
2271 RoleResult result = null;
2272
2273 if (relObj instanceof RelationSupport) {
2274 // Internal relation
2275 // Can throw RelationServiceNotRegisteredException
2276 //
2277 // Shall not throw RelationTypeNotFoundException (as relation is
2278 // known, its relation type exists)
2279 try {
2280 result = ((RelationSupport)relObj).setRolesInt(roleList,
2281 true,
2282 this);
2283 } catch (RelationTypeNotFoundException exc) {
2284 throw new RuntimeException(exc.getMessage());
2285 }
2286
2287 } else {
2288 // Relation MBean
2289 Object[] params = new Object[1];
2290 params[0] = roleList;
2291 String[] signature = new String[1];
2292 signature[0] = "javax.management.relation.RoleList";
2293 // Shall not throw InstanceNotFoundException or an MBeanException
2294 // or ReflectionException
2295 try {
2296 result = (RoleResult)
2297 (myMBeanServer.invoke(((ObjectName)relObj),
2298 "setRoles",
2299 params,
2300 signature));
2301 } catch (InstanceNotFoundException exc1) {
2302 throw new RuntimeException(exc1.getMessage());
2303 } catch (ReflectionException exc3) {
2304 throw new RuntimeException(exc3.getMessage());
2305 } catch (MBeanException exc2) {
2306 throw new
2307 RuntimeException((exc2.getTargetException()).getMessage());
2308 }
2309 }
2310
2311 RELATION_LOGGER.exiting(RelationService.class.getName(), "setRoles");
2312 return result;
2313 }
2314
2315 /**
2316 * Retrieves MBeans referenced in the various roles of the relation.
2317 *
2318 * @param relationId relation id
2319 *
2320 * @return a HashMap mapping:
2321 * <P> ObjectName -> ArrayList of String (role
2322 * names)
2323 *
2324 * @exception IllegalArgumentException if null parameter
2325 * @exception RelationNotFoundException if no relation for given
2326 * relation id
2327 */
2328 public Map<ObjectName,List<String>>
2329 getReferencedMBeans(String relationId)
2330 throws IllegalArgumentException,
2331 RelationNotFoundException {
2332
2333 if (relationId == null) {
2334 String excMsg = "Invalid parameter.";
2335 throw new IllegalArgumentException(excMsg);
2336 }
2337
2338 RELATION_LOGGER.entering(RelationService.class.getName(),
2339 "getReferencedMBeans", relationId);
2340
2341 // Can throw a RelationNotFoundException
2342 Object relObj = getRelation(relationId);
2343
2344 Map<ObjectName,List<String>> result;
2345
2346 if (relObj instanceof RelationSupport) {
2347 // Internal relation
2348 result = ((RelationSupport)relObj).getReferencedMBeans();
2349
2350 } else {
2351 // Relation MBean
2352 // No Exception
2353 try {
2354 result = cast(
2355 myMBeanServer.getAttribute(((ObjectName)relObj),
2356 "ReferencedMBeans"));
2357 } catch (Exception exc) {
2358 throw new RuntimeException(exc.getMessage());
2359 }
2360 }
2361
2362 RELATION_LOGGER.exiting(RelationService.class.getName(),
2363 "getReferencedMBeans");
2364 return result;
2365 }
2366
2367 /**
2368 * Returns name of associated relation type for given relation.
2369 *
2370 * @param relationId relation id
2371 *
2372 * @return the name of the associated relation type.
2373 *
2374 * @exception IllegalArgumentException if null parameter
2375 * @exception RelationNotFoundException if no relation for given
2376 * relation id
2377 */
2378 public String getRelationTypeName(String relationId)
2379 throws IllegalArgumentException,
2380 RelationNotFoundException {
2381
2382 if (relationId == null) {
2383 String excMsg = "Invalid parameter.";
2384 throw new IllegalArgumentException(excMsg);
2385 }
2386
2387 RELATION_LOGGER.entering(RelationService.class.getName(),
2388 "getRelationTypeName", relationId);
2389
2390 // Can throw a RelationNotFoundException
2391 Object relObj = getRelation(relationId);
2392
2393 String result = null;
2394
2395 if (relObj instanceof RelationSupport) {
2396 // Internal relation
2397 result = ((RelationSupport)relObj).getRelationTypeName();
2398
2399 } else {
2400 // Relation MBean
2401 // No Exception
2402 try {
2403 result = (String)
2404 (myMBeanServer.getAttribute(((ObjectName)relObj),
2405 "RelationTypeName"));
2406 } catch (Exception exc) {
2407 throw new RuntimeException(exc.getMessage());
2408 }
2409 }
2410
2411 RELATION_LOGGER.exiting(RelationService.class.getName(),
2412 "getRelationTypeName");
2413 return result;
2414 }
2415
2416 //
2417 // NotificationListener Interface
2418 //
2419
2420 /**
2421 * Invoked when a JMX notification occurs.
2422 * Currently handles notifications for unregistration of MBeans, either
2423 * referenced in a relation role or being a relation itself.
2424 *
2425 * @param notif The notification.
2426 * @param handback An opaque object which helps the listener to
2427 * associate information regarding the MBean emitter (can be null).
2428 */
2429 public void handleNotification(Notification notif,
2430 Object handback) {
2431
2432 if (notif == null) {
2433 String excMsg = "Invalid parameter.";
2434 throw new IllegalArgumentException(excMsg);
2435 }
2436
2437 RELATION_LOGGER.entering(RelationService.class.getName(),
2438 "handleNotification", notif);
2439
2440 if (notif instanceof MBeanServerNotification) {
2441
2442 MBeanServerNotification mbsNtf = (MBeanServerNotification) notif;
2443 String ntfType = notif.getType();
2444
2445 if (ntfType.equals(
2446 MBeanServerNotification.UNREGISTRATION_NOTIFICATION )) {
2447 ObjectName mbeanName =
2448 ((MBeanServerNotification)notif).getMBeanName();
2449
2450 // Note: use a flag to block access to
2451 // myRefedMBeanObjName2RelIdsMap only for a quick access
2452 boolean isRefedMBeanFlag = false;
2453 synchronized(myRefedMBeanObjName2RelIdsMap) {
2454
2455 if (myRefedMBeanObjName2RelIdsMap.containsKey(mbeanName)) {
2456 // Unregistration of a referenced MBean
2457 synchronized(myUnregNtfList) {
2458 myUnregNtfList.add(mbsNtf);
2459 }
2460 isRefedMBeanFlag = true;
2461 }
2462 if (isRefedMBeanFlag && myPurgeFlag) {
2463 // Immediate purge
2464 // Can throw RelationServiceNotRegisteredException
2465 // but assume that will be fine :)
2466 try {
2467 purgeRelations();
2468 } catch (Exception exc) {
2469 throw new RuntimeException(exc.getMessage());
2470 }
2471 }
2472 }
2473
2474 // Note: do both tests as a relation can be an MBean and be
2475 // itself referenced in another relation :)
2476 String relId = null;
2477 synchronized(myRelMBeanObjName2RelIdMap){
2478 relId = myRelMBeanObjName2RelIdMap.get(mbeanName);
2479 }
2480 if (relId != null) {
2481 // Unregistration of a relation MBean
2482 // Can throw RelationTypeNotFoundException,
2483 // RelationServiceNotRegisteredException
2484 //
2485 // Shall not throw RelationTypeNotFoundException or
2486 // InstanceNotFoundException
2487 try {
2488 removeRelation(relId);
2489 } catch (Exception exc) {
2490 throw new RuntimeException(exc.getMessage());
2491 }
2492 }
2493 }
2494 }
2495
2496 RELATION_LOGGER.exiting(RelationService.class.getName(),
2497 "handleNotification");
2498 return;
2499 }
2500
2501 //
2502 // NotificationBroadcaster interface
2503 //
2504
2505 /**
2506 * Returns a NotificationInfo object containing the name of the Java class
2507 * of the notification and the notification types sent.
2508 */
2509 public MBeanNotificationInfo[] getNotificationInfo() {
2510
2511 RELATION_LOGGER.entering(RelationService.class.getName(),
2512 "getNotificationInfo");
2513
2514 MBeanNotificationInfo[] ntfInfoArray =
2515 new MBeanNotificationInfo[1];
2516
2517 String ntfClass = "javax.management.relation.RelationNotification";
2518
2519 String[] ntfTypes = new String[] {
2520 RelationNotification.RELATION_BASIC_CREATION,
2521 RelationNotification.RELATION_MBEAN_CREATION,
2522 RelationNotification.RELATION_BASIC_UPDATE,
2523 RelationNotification.RELATION_MBEAN_UPDATE,
2524 RelationNotification.RELATION_BASIC_REMOVAL,
2525 RelationNotification.RELATION_MBEAN_REMOVAL,
2526 };
2527
2528 String ntfDesc = "Sent when a relation is created, updated or deleted.";
2529
2530 MBeanNotificationInfo ntfInfo =
2531 new MBeanNotificationInfo(ntfTypes, ntfClass, ntfDesc);
2532
2533 RELATION_LOGGER.exiting(RelationService.class.getName(),
2534 "getNotificationInfo");
2535 return new MBeanNotificationInfo[] {ntfInfo};
2536 }
2537
2538 //
2539 // Misc
2540 //
2541
2542 // Adds given object as a relation type.
2543 //
2544 // -param relationTypeObj relation type object
2545 //
2546 // -exception IllegalArgumentException if null parameter
2547 // -exception InvalidRelationTypeException if there is already a relation
2548 // type with that name
2549 private void addRelationTypeInt(RelationType relationTypeObj)
2550 throws IllegalArgumentException,
2551 InvalidRelationTypeException {
2552
2553 if (relationTypeObj == null) {
2554 String excMsg = "Invalid parameter.";
2555 throw new IllegalArgumentException(excMsg);
2556 }
2557
2558 RELATION_LOGGER.entering(RelationService.class.getName(),
2559 "addRelationTypeInt");
2560
2561 String relTypeName = relationTypeObj.getRelationTypeName();
2562
2563 // Checks that there is not already a relation type with that name
2564 // existing in the Relation Service
2565 try {
2566 // Can throw a RelationTypeNotFoundException (in fact should ;)
2567 RelationType relType = getRelationType(relTypeName);
2568
2569 if (relType != null) {
2570 String excMsg = "There is already a relation type in the Relation Service with name ";
2571 StringBuilder excMsgStrB = new StringBuilder(excMsg);
2572 excMsgStrB.append(relTypeName);
2573 throw new InvalidRelationTypeException(excMsgStrB.toString());
2574 }
2575
2576 } catch (RelationTypeNotFoundException exc) {
2577 // OK : The RelationType could not be found.
2578 }
2579
2580 // Adds the relation type
2581 synchronized(myRelType2ObjMap) {
2582 myRelType2ObjMap.put(relTypeName, relationTypeObj);
2583 }
2584
2585 if (relationTypeObj instanceof RelationTypeSupport) {
2586 ((RelationTypeSupport)relationTypeObj).setRelationServiceFlag(true);
2587 }
2588
2589 RELATION_LOGGER.exiting(RelationService.class.getName(),
2590 "addRelationTypeInt");
2591 return;
2592 }
2593
2594 // Retrieves relation type with given name
2595 //
2596 // -param relationTypeName expected name of a relation type created in the
2597 // Relation Service
2598 //
2599 // -return RelationType object corresponding to given name
2600 //
2601 // -exception IllegalArgumentException if null parameter
2602 // -exception RelationTypeNotFoundException if no relation type for that
2603 // name created in Relation Service
2604 //
2605 RelationType getRelationType(String relationTypeName)
2606 throws IllegalArgumentException,
2607 RelationTypeNotFoundException {
2608
2609 if (relationTypeName == null) {
2610 String excMsg = "Invalid parameter.";
2611 throw new IllegalArgumentException(excMsg);
2612 }
2613
2614 RELATION_LOGGER.entering(RelationService.class.getName(),
2615 "getRelationType", relationTypeName);
2616
2617 // No null relation type accepted, so can use get()
2618 RelationType relType = null;
2619 synchronized(myRelType2ObjMap) {
2620 relType = (myRelType2ObjMap.get(relationTypeName));
2621 }
2622
2623 if (relType == null) {
2624 String excMsg = "No relation type created in the Relation Service with the name ";
2625 StringBuilder excMsgStrB = new StringBuilder(excMsg);
2626 excMsgStrB.append(relationTypeName);
2627 throw new RelationTypeNotFoundException(excMsgStrB.toString());
2628 }
2629
2630 RELATION_LOGGER.exiting(RelationService.class.getName(),
2631 "getRelationType");
2632 return relType;
2633 }
2634
2635 // Retrieves relation corresponding to given relation id.
2636 // Returns either:
2637 // - a RelationSupport object if the relation is internal
2638 // or
2639 // - the ObjectName of the corresponding MBean
2640 //
2641 // -param relationId expected relation id
2642 //
2643 // -return RelationSupport object or ObjectName of relation with given id
2644 //
2645 // -exception IllegalArgumentException if null parameter
2646 // -exception RelationNotFoundException if no relation for that
2647 // relation id created in Relation Service
2648 //
2649 Object getRelation(String relationId)
2650 throws IllegalArgumentException,
2651 RelationNotFoundException {
2652
2653 if (relationId == null) {
2654 String excMsg = "Invalid parameter.";
2655 throw new IllegalArgumentException(excMsg);
2656 }
2657
2658 RELATION_LOGGER.entering(RelationService.class.getName(),
2659 "getRelation", relationId);
2660
2661 // No null relation accepted, so can use get()
2662 Object rel = null;
2663 synchronized(myRelId2ObjMap) {
2664 rel = myRelId2ObjMap.get(relationId);
2665 }
2666
2667 if (rel == null) {
2668 String excMsg = "No relation associated to relation id " + relationId;
2669 throw new RelationNotFoundException(excMsg);
2670 }
2671
2672 RELATION_LOGGER.exiting(RelationService.class.getName(),
2673 "getRelation");
2674 return rel;
2675 }
2676
2677 // Adds a new MBean reference (reference to an ObjectName) in the
2678 // referenced MBean map (myRefedMBeanObjName2RelIdsMap).
2679 //
2680 // -param objectName ObjectName of new referenced MBean
2681 // -param relationId relation id of the relation where the MBean is
2682 // referenced
2683 // -param roleName name of the role where the MBean is referenced
2684 //
2685 // -return boolean:
2686 // - true if the MBean was not referenced before, so really a new
2687 // reference
2688 // - false else
2689 //
2690 // -exception IllegalArgumentException if null parameter
2691 private boolean addNewMBeanReference(ObjectName objectName,
2692 String relationId,
2693 String roleName)
2694 throws IllegalArgumentException {
2695
2696 if (objectName == null ||
2697 relationId == null ||
2698 roleName == null) {
2699 String excMsg = "Invalid parameter.";
2700 throw new IllegalArgumentException(excMsg);
2701 }
2702
2703 RELATION_LOGGER.entering(RelationService.class.getName(),
2704 "addNewMBeanReference",
2705 new Object[] {objectName, relationId, roleName});
2706
2707 boolean isNewFlag = false;
2708
2709 synchronized(myRefedMBeanObjName2RelIdsMap) {
2710
2711 // Checks if the MBean was already referenced
2712 // No null value allowed, use get() directly
2713 Map<String,List<String>> mbeanRefMap =
2714 myRefedMBeanObjName2RelIdsMap.get(objectName);
2715
2716 if (mbeanRefMap == null) {
2717 // MBean not referenced in any relation yet
2718
2719 isNewFlag = true;
2720
2721 // List of roles where the MBean is referenced in given
2722 // relation
2723 List<String> roleNames = new ArrayList<String>();
2724 roleNames.add(roleName);
2725
2726 // Map of relations where the MBean is referenced
2727 mbeanRefMap = new HashMap<String,List<String>>();
2728 mbeanRefMap.put(relationId, roleNames);
2729
2730 myRefedMBeanObjName2RelIdsMap.put(objectName, mbeanRefMap);
2731
2732 } else {
2733 // MBean already referenced in at least another relation
2734 // Checks if already referenced in another role in current
2735 // relation
2736 List<String> roleNames = mbeanRefMap.get(relationId);
2737
2738 if (roleNames == null) {
2739 // MBean not referenced in current relation
2740
2741 // List of roles where the MBean is referenced in given
2742 // relation
2743 roleNames = new ArrayList<String>();
2744 roleNames.add(roleName);
2745
2746 // Adds new reference done in current relation
2747 mbeanRefMap.put(relationId, roleNames);
2748
2749 } else {
2750 // MBean already referenced in current relation in another
2751 // role
2752 // Adds new reference done
2753 roleNames.add(roleName);
2754 }
2755 }
2756 }
2757
2758 RELATION_LOGGER.exiting(RelationService.class.getName(),
2759 "addNewMBeanReference");
2760 return isNewFlag;
2761 }
2762
2763 // Removes an obsolete MBean reference (reference to an ObjectName) in
2764 // the referenced MBean map (myRefedMBeanObjName2RelIdsMap).
2765 //
2766 // -param objectName ObjectName of MBean no longer referenced
2767 // -param relationId relation id of the relation where the MBean was
2768 // referenced
2769 // -param roleName name of the role where the MBean was referenced
2770 // -param allRolesFlag flag, if true removes reference to MBean for all
2771 // roles in the relation, not only for the one above
2772 //
2773 // -return boolean:
2774 // - true if the MBean is no longer reference in any relation
2775 // - false else
2776 //
2777 // -exception IllegalArgumentException if null parameter
2778 private boolean removeMBeanReference(ObjectName objectName,
2779 String relationId,
2780 String roleName,
2781 boolean allRolesFlag)
2782 throws IllegalArgumentException {
2783
2784 if (objectName == null ||
2785 relationId == null ||
2786 roleName == null) {
2787 String excMsg = "Invalid parameter.";
2788 throw new IllegalArgumentException(excMsg);
2789 }
2790
2791 RELATION_LOGGER.entering(RelationService.class.getName(),
2792 "removeMBeanReference",
2793 new Object[] {objectName, relationId, roleName, allRolesFlag});
2794
2795 boolean noLongerRefFlag = false;
2796
2797 synchronized(myRefedMBeanObjName2RelIdsMap) {
2798
2799 // Retrieves the set of relations (designed via their relation ids)
2800 // where the MBean is referenced
2801 // Note that it is possible that the MBean has already been removed
2802 // from the internal map: this is the case when the MBean is
2803 // unregistered, the role is updated, then we arrive here.
2804 HashMap mbeanRefMap = (HashMap)
2805 (myRefedMBeanObjName2RelIdsMap.get(objectName));
2806
2807 if (mbeanRefMap == null) {
2808 // The MBean is no longer referenced
2809 RELATION_LOGGER.exiting(RelationService.class.getName(),
2810 "removeMBeanReference");
2811 return true;
2812 }
2813
2814 ArrayList roleNames = new ArrayList();
2815 if (!allRolesFlag) {
2816 // Now retrieves the roles of current relation where the MBean
2817 // was referenced
2818 roleNames = (ArrayList)(mbeanRefMap.get(relationId));
2819
2820 // Removes obsolete reference to role
2821 int obsRefIdx = roleNames.indexOf(roleName);
2822 if (obsRefIdx != -1) {
2823 roleNames.remove(obsRefIdx);
2824 }
2825 }
2826
2827 // Checks if there is still at least one role in current relation
2828 // where the MBean is referenced
2829 if (roleNames.isEmpty() || allRolesFlag) {
2830 // MBean no longer referenced in current relation: removes
2831 // entry
2832 mbeanRefMap.remove(relationId);
2833 }
2834
2835 // Checks if the MBean is still referenced in at least on relation
2836 if (mbeanRefMap.isEmpty()) {
2837 // MBean no longer referenced in any relation: removes entry
2838 myRefedMBeanObjName2RelIdsMap.remove(objectName);
2839 noLongerRefFlag = true;
2840 }
2841 }
2842
2843 RELATION_LOGGER.exiting(RelationService.class.getName(),
2844 "removeMBeanReference");
2845 return noLongerRefFlag;
2846 }
2847
2848 // Updates the listener registered to the MBean Server to be informed of
2849 // referenced MBean unregistrations
2850 //
2851 // -param newRefList ArrayList of ObjectNames for new references done
2852 // to MBeans (can be null)
2853 // -param obsoleteRefList ArrayList of ObjectNames for obsolete references
2854 // to MBeans (can be null)
2855 //
2856 // -exception RelationServiceNotRegisteredException if the Relation
2857 // Service is not registered in the MBean Server.
2858 private void updateUnregistrationListener(List newRefList,
2859 List obsoleteRefList)
2860 throws RelationServiceNotRegisteredException {
2861
2862 if (newRefList != null && obsoleteRefList != null) {
2863 if (newRefList.isEmpty() && obsoleteRefList.isEmpty()) {
2864 // Nothing to do :)
2865 return;
2866 }
2867 }
2868
2869 RELATION_LOGGER.entering(RelationService.class.getName(),
2870 "updateUnregistrationListener",
2871 new Object[] {newRefList, obsoleteRefList});
2872
2873 // Can throw RelationServiceNotRegisteredException
2874 isActive();
2875
2876 if (newRefList != null || obsoleteRefList != null) {
2877
2878 boolean newListenerFlag = false;
2879 if (myUnregNtfFilter == null) {
2880 // Initialize it to be able to synchronise it :)
2881 myUnregNtfFilter = new MBeanServerNotificationFilter();
2882 newListenerFlag = true;
2883 }
2884
2885 synchronized(myUnregNtfFilter) {
2886
2887 // Enables ObjectNames in newRefList
2888 if (newRefList != null) {
2889 for (Iterator newRefIter = newRefList.iterator();
2890 newRefIter.hasNext();) {
2891
2892 ObjectName newObjName = (ObjectName)
2893 (newRefIter.next());
2894 myUnregNtfFilter.enableObjectName(newObjName);
2895 }
2896 }
2897
2898 if (obsoleteRefList != null) {
2899 // Disables ObjectNames in obsoleteRefList
2900 for (Iterator obsRefIter = obsoleteRefList.iterator();
2901 obsRefIter.hasNext();) {
2902
2903 ObjectName obsObjName = (ObjectName)
2904 (obsRefIter.next());
2905 myUnregNtfFilter.disableObjectName(obsObjName);
2906 }
2907 }
2908
2909// Under test
2910 if (newListenerFlag) {
2911 try {
2912 myMBeanServer.addNotificationListener(
2913 MBeanServerDelegate.DELEGATE_NAME,
2914 this,
2915 myUnregNtfFilter,
2916 null);
2917 } catch (InstanceNotFoundException exc) {
2918 throw new
2919 RelationServiceNotRegisteredException(exc.getMessage());
2920 }
2921 }
2922// End test
2923
2924
2925// if (!newListenerFlag) {
2926 // The Relation Service was already registered as a
2927 // listener:
2928 // removes it
2929 // Shall not throw InstanceNotFoundException (as the
2930 // MBean Server Delegate is expected to exist) or
2931 // ListenerNotFoundException (as it has been checked above
2932 // that the Relation Service is registered)
2933// try {
2934// myMBeanServer.removeNotificationListener(
2935// MBeanServerDelegate.DELEGATE_NAME,
2936// this);
2937// } catch (InstanceNotFoundException exc1) {
2938// throw new RuntimeException(exc1.getMessage());
2939// } catch (ListenerNotFoundException exc2) {
2940// throw new
2941// RelationServiceNotRegisteredException(exc2.getMessage());
2942// }
2943// }
2944
2945 // Adds Relation Service with current filter
2946 // Can throw InstanceNotFoundException if the Relation
2947 // Service is not registered, to be transformed into
2948 // RelationServiceNotRegisteredException
2949 //
2950 // Assume that there will not be any InstanceNotFoundException
2951 // for the MBean Server Delegate :)
2952// try {
2953// myMBeanServer.addNotificationListener(
2954// MBeanServerDelegate.DELEGATE_NAME,
2955// this,
2956// myUnregNtfFilter,
2957// null);
2958// } catch (InstanceNotFoundException exc) {
2959// throw new
2960// RelationServiceNotRegisteredException(exc.getMessage());
2961// }
2962 }
2963 }
2964
2965 RELATION_LOGGER.exiting(RelationService.class.getName(),
2966 "updateUnregistrationListener");
2967 return;
2968 }
2969
2970 // Adds a relation (being either a RelationSupport object or an MBean
2971 // referenced using its ObjectName) in the Relation Service.
2972 // Will send a notification RelationNotification with type:
2973 // - RelationNotification.RELATION_BASIC_CREATION for internal relation
2974 // creation
2975 // - RelationNotification.RELATION_MBEAN_CREATION for an MBean being added
2976 // as a relation.
2977 //
2978 // -param relationBaseFlag flag true if the relation is a RelationSupport
2979 // object, false if it is an MBean
2980 // -param relationObj RelationSupport object (if relation is internal)
2981 // -param relationObjName ObjectName of the MBean to be added as a relation
2982 // (only for the relation MBean)
2983 // -param relationId relation identifier, to uniquely identify the relation
2984 // inside the Relation Service
2985 // -param relationTypeName name of the relation type (has to be created
2986 // in the Relation Service)
2987 // -param roleList role list to initialize roles of the relation
2988 // (can be null)
2989 //
2990 // -exception IllegalArgumentException if null paramater
2991 // -exception RelationServiceNotRegisteredException if the Relation
2992 // Service is not registered in the MBean Server
2993 // -exception RoleNotFoundException if a value is provided for a role
2994 // that does not exist in the relation type
2995 // -exception InvalidRelationIdException if relation id already used
2996 // -exception RelationTypeNotFoundException if relation type not known in
2997 // Relation Service
2998 // -exception InvalidRoleValueException if:
2999 // - the same role name is used for two different roles
3000 // - the number of referenced MBeans in given value is less than
3001 // expected minimum degree
3002 // - the number of referenced MBeans in provided value exceeds expected
3003 // maximum degree
3004 // - one referenced MBean in the value is not an Object of the MBean
3005 // class expected for that role
3006 // - an MBean provided for that role does not exist
3007 private void addRelationInt(boolean relationBaseFlag,
3008 RelationSupport relationObj,
3009 ObjectName relationObjName,
3010 String relationId,
3011 String relationTypeName,
3012 RoleList roleList)
3013 throws IllegalArgumentException,
3014 RelationServiceNotRegisteredException,
3015 RoleNotFoundException,
3016 InvalidRelationIdException,
3017 RelationTypeNotFoundException,
3018 InvalidRoleValueException {
3019
3020 if (relationId == null ||
3021 relationTypeName == null ||
3022 (relationBaseFlag &&
3023 (relationObj == null ||
3024 relationObjName != null)) ||
3025 (!relationBaseFlag &&
3026 (relationObjName == null ||
3027 relationObj != null))) {
3028 String excMsg = "Invalid parameter.";
3029 throw new IllegalArgumentException(excMsg);
3030 }
3031
3032 RELATION_LOGGER.entering(RelationService.class.getName(),
3033 "addRelationInt", new Object[] {relationBaseFlag, relationObj,
3034 relationObjName, relationId, relationTypeName, roleList});
3035
3036 // Can throw RelationServiceNotRegisteredException
3037 isActive();
3038
3039 // Checks if there is already a relation with given id
3040 try {
3041 // Can throw a RelationNotFoundException (in fact should :)
3042 Object rel = getRelation(relationId);
3043
3044 if (rel != null) {
3045 // There is already a relation with that id
3046 String excMsg = "There is already a relation with id ";
3047 StringBuilder excMsgStrB = new StringBuilder(excMsg);
3048 excMsgStrB.append(relationId);
3049 throw new InvalidRelationIdException(excMsgStrB.toString());
3050 }
3051 } catch (RelationNotFoundException exc) {
3052 // OK : The Relation could not be found.
3053 }
3054
3055 // Retrieves the relation type
3056 // Can throw RelationTypeNotFoundException
3057 RelationType relType = getRelationType(relationTypeName);
3058
3059 // Checks that each provided role conforms to its role info provided in
3060 // the relation type
3061 // First retrieves a local list of the role infos of the relation type
3062 // to see which roles have not been initialized
3063 // Note: no need to test if list not null before cloning, not allowed
3064 // to have an empty relation type.
3065 ArrayList roleInfoList = (ArrayList)
3066 (((ArrayList)(relType.getRoleInfos())).clone());
3067
3068 if (roleList != null) {
3069
3070 for (Iterator roleIter = roleList.iterator();
3071 roleIter.hasNext();) {
3072
3073 Role currRole = (Role)(roleIter.next());
3074 String currRoleName = currRole.getRoleName();
3075 ArrayList currRoleValue = (ArrayList)
3076 (currRole.getRoleValue());
3077 // Retrieves corresponding role info
3078 // Can throw a RoleInfoNotFoundException to be converted into a
3079 // RoleNotFoundException
3080 RoleInfo roleInfo = null;
3081 try {
3082 roleInfo = relType.getRoleInfo(currRoleName);
3083 } catch (RoleInfoNotFoundException exc) {
3084 throw new RoleNotFoundException(exc.getMessage());
3085 }
3086
3087 // Checks that role conforms to role info,
3088 Integer status = checkRoleInt(2,
3089 currRoleName,
3090 currRoleValue,
3091 roleInfo,
3092 false);
3093 int pbType = status.intValue();
3094 if (pbType != 0) {
3095 // A problem has occurred: throws appropriate exception
3096 // here InvalidRoleValueException
3097 throwRoleProblemException(pbType, currRoleName);
3098 }
3099
3100 // Removes role info for that list from list of role infos for
3101 // roles to be defaulted
3102 int roleInfoIdx = roleInfoList.indexOf(roleInfo);
3103 // Note: no need to check if != -1, MUST be there :)
3104 roleInfoList.remove(roleInfoIdx);
3105 }
3106 }
3107
3108 // Initializes roles not initialized by roleList
3109 // Can throw InvalidRoleValueException
3110 initializeMissingRoles(relationBaseFlag,
3111 relationObj,
3112 relationObjName,
3113 relationId,
3114 relationTypeName,
3115 roleInfoList);
3116
3117 // Creation of relation successfull!!!!
3118
3119 // Updates internal maps
3120 // Relation id to object map
3121 synchronized(myRelId2ObjMap) {
3122 if (relationBaseFlag) {
3123 // Note: do not clone relation object, created by us :)
3124 myRelId2ObjMap.put(relationId, relationObj);
3125 } else {
3126 myRelId2ObjMap.put(relationId, relationObjName);
3127 }
3128 }
3129
3130 // Relation id to relation type name map
3131 synchronized(myRelId2RelTypeMap) {
3132 myRelId2RelTypeMap.put(relationId,
3133 relationTypeName);
3134 }
3135
3136 // Relation type to relation id map
3137 synchronized(myRelType2RelIdsMap) {
3138 List<String> relIdList =
3139 myRelType2RelIdsMap.get(relationTypeName);
3140 boolean firstRelFlag = false;
3141 if (relIdList == null) {
3142 firstRelFlag = true;
3143 relIdList = new ArrayList<String>();
3144 }
3145 relIdList.add(relationId);
3146 if (firstRelFlag) {
3147 myRelType2RelIdsMap.put(relationTypeName, relIdList);
3148 }
3149 }
3150
3151 // Referenced MBean to relation id map
3152 // Only role list parameter used, as default initialization of roles
3153 // done automatically in initializeMissingRoles() sets each
3154 // uninitialized role to an empty value.
3155 for (Iterator roleIter = roleList.iterator();
3156 roleIter.hasNext();) {
3157 Role currRole = (Role)(roleIter.next());
3158 // Creates a dummy empty ArrayList of ObjectNames to be the old
3159 // role value :)
3160 List<ObjectName> dummyList = new ArrayList<ObjectName>();
3161 // Will not throw a RelationNotFoundException (as the RelId2Obj map
3162 // has been updated above) so catch it :)
3163 try {
3164 updateRoleMap(relationId, currRole, dummyList);
3165
3166 } catch (RelationNotFoundException exc) {
3167 // OK : The Relation could not be found.
3168 }
3169 }
3170
3171 // Sends a notification for relation creation
3172 // Will not throw RelationNotFoundException so catch it :)
3173 try {
3174 sendRelationCreationNotification(relationId);
3175
3176 } catch (RelationNotFoundException exc) {
3177 // OK : The Relation could not be found.
3178 }
3179
3180 RELATION_LOGGER.exiting(RelationService.class.getName(),
3181 "addRelationInt");
3182 return;
3183 }
3184
3185 // Checks that given role conforms to given role info.
3186 //
3187 // -param chkType type of check:
3188 // - 1: read, just check read access
3189 // - 2: write, check value and write access if writeChkFlag
3190 // -param roleName role name
3191 // -param roleValue role value
3192 // -param roleInfo corresponding role info
3193 // -param writeChkFlag boolean to specify a current write access and
3194 // to check it
3195 //
3196 // -return Integer with value:
3197 // - 0: ok
3198 // - RoleStatus.NO_ROLE_WITH_NAME
3199 // - RoleStatus.ROLE_NOT_READABLE
3200 // - RoleStatus.ROLE_NOT_WRITABLE
3201 // - RoleStatus.LESS_THAN_MIN_ROLE_DEGREE
3202 // - RoleStatus.MORE_THAN_MAX_ROLE_DEGREE
3203 // - RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS
3204 // - RoleStatus.REF_MBEAN_NOT_REGISTERED
3205 //
3206 // -exception IllegalArgumentException if null parameter
3207 private Integer checkRoleInt(int chkType,
3208 String roleName,
3209 List roleValue,
3210 RoleInfo roleInfo,
3211 boolean writeChkFlag)
3212 throws IllegalArgumentException {
3213
3214 if (roleName == null ||
3215 roleInfo == null ||
3216 (chkType == 2 && roleValue == null)) {
3217 String excMsg = "Invalid parameter.";
3218 throw new IllegalArgumentException(excMsg);
3219 }
3220
3221 RELATION_LOGGER.entering(RelationService.class.getName(),
3222 "checkRoleInt", new Object[] {chkType, roleName,
3223 roleValue, roleInfo, writeChkFlag});
3224
3225 // Compares names
3226 String expName = roleInfo.getName();
3227 if (!(roleName.equals(expName))) {
3228 RELATION_LOGGER.exiting(RelationService.class.getName(),
3229 "checkRoleInt");
3230 return new Integer(RoleStatus.NO_ROLE_WITH_NAME);
3231 }
3232
3233 // Checks read access if required
3234 if (chkType == 1) {
3235 boolean isReadable = roleInfo.isReadable();
3236 if (!isReadable) {
3237 RELATION_LOGGER.exiting(RelationService.class.getName(),
3238 "checkRoleInt");
3239 return new Integer(RoleStatus.ROLE_NOT_READABLE);
3240 } else {
3241 // End of check :)
3242 RELATION_LOGGER.exiting(RelationService.class.getName(),
3243 "checkRoleInt");
3244 return new Integer(0);
3245 }
3246 }
3247
3248 // Checks write access if required
3249 if (writeChkFlag) {
3250 boolean isWritable = roleInfo.isWritable();
3251 if (!isWritable) {
3252 RELATION_LOGGER.exiting(RelationService.class.getName(),
3253 "checkRoleInt");
3254 return new Integer(RoleStatus.ROLE_NOT_WRITABLE);
3255 }
3256 }
3257
3258 int refNbr = roleValue.size();
3259
3260 // Checks minimum cardinality
3261 boolean chkMinFlag = roleInfo.checkMinDegree(refNbr);
3262 if (!chkMinFlag) {
3263 RELATION_LOGGER.exiting(RelationService.class.getName(),
3264 "checkRoleInt");
3265 return new Integer(RoleStatus.LESS_THAN_MIN_ROLE_DEGREE);
3266 }
3267
3268 // Checks maximum cardinality
3269 boolean chkMaxFlag = roleInfo.checkMaxDegree(refNbr);
3270 if (!chkMaxFlag) {
3271 RELATION_LOGGER.exiting(RelationService.class.getName(),
3272 "checkRoleInt");
3273 return new Integer(RoleStatus.MORE_THAN_MAX_ROLE_DEGREE);
3274 }
3275
3276 // Verifies that each referenced MBean is registered in the MBean
3277 // Server and that it is an instance of the class specified in the
3278 // role info, or of a subclass of it
3279 // Note that here again this is under the assumption that
3280 // referenced MBeans, relation MBeans and the Relation Service are
3281 // registered in the same MBean Server.
3282 String expClassName = roleInfo.getRefMBeanClassName();
3283
3284 for (Iterator refMBeanIter = roleValue.iterator();
3285 refMBeanIter.hasNext();) {
3286 ObjectName currObjName = (ObjectName)(refMBeanIter.next());
3287
3288 // Checks it is registered
3289 if (currObjName == null) {
3290 RELATION_LOGGER.exiting(RelationService.class.getName(),
3291 "checkRoleInt");
3292 return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
3293 }
3294
3295 // Checks if it is of the correct class
3296 // Can throw an InstanceNotFoundException, if MBean not registered
3297 try {
3298 boolean classSts = myMBeanServer.isInstanceOf(currObjName,
3299 expClassName);
3300 if (!classSts) {
3301 RELATION_LOGGER.exiting(RelationService.class.getName(),
3302 "checkRoleInt");
3303 return new Integer(RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS);
3304 }
3305
3306 } catch (InstanceNotFoundException exc) {
3307 RELATION_LOGGER.exiting(RelationService.class.getName(),
3308 "checkRoleInt");
3309 return new Integer(RoleStatus.REF_MBEAN_NOT_REGISTERED);
3310 }
3311 }
3312
3313 RELATION_LOGGER.exiting(RelationService.class.getName(),
3314 "checkRoleInt");
3315 return new Integer(0);
3316 }
3317
3318
3319 // Initializes roles associated to given role infos to default value (empty
3320 // ArrayList of ObjectNames) in given relation.
3321 // It will succeed for every role except if the role info has a minimum
3322 // cardinality greater than 0. In that case, an InvalidRoleValueException
3323 // will be raised.
3324 //
3325 // -param relationBaseFlag flag true if the relation is a RelationSupport
3326 // object, false if it is an MBean
3327 // -param relationObj RelationSupport object (if relation is internal)
3328 // -param relationObjName ObjectName of the MBean to be added as a relation
3329 // (only for the relation MBean)
3330 // -param relationId relation id
3331 // -param relationTypeName name of the relation type (has to be created
3332 // in the Relation Service)
3333 // -param roleInfoList list of role infos for roles to be defaulted
3334 //
3335 // -exception IllegalArgumentException if null paramater
3336 // -exception RelationServiceNotRegisteredException if the Relation
3337 // Service is not registered in the MBean Server
3338 // -exception InvalidRoleValueException if role must have a non-empty
3339 // value
3340
3341 // Revisit [cebro] Handle CIM qualifiers as REQUIRED to detect roles which
3342 // should have been initialized by the user
3343 private void initializeMissingRoles(boolean relationBaseFlag,
3344 RelationSupport relationObj,
3345 ObjectName relationObjName,
3346 String relationId,
3347 String relationTypeName,
3348 List roleInfoList)
3349 throws IllegalArgumentException,
3350 RelationServiceNotRegisteredException,
3351 InvalidRoleValueException {
3352
3353 if ((relationBaseFlag &&
3354 (relationObj == null ||
3355 relationObjName != null)) ||
3356 (!relationBaseFlag &&
3357 (relationObjName == null ||
3358 relationObj != null)) ||
3359 relationId == null ||
3360 relationTypeName == null ||
3361 roleInfoList == null) {
3362 String excMsg = "Invalid parameter.";
3363 throw new IllegalArgumentException(excMsg);
3364 }
3365
3366 RELATION_LOGGER.entering(RelationService.class.getName(),
3367 "initializeMissingRoles", new Object[] {relationBaseFlag,
3368 relationObj, relationObjName, relationId, relationTypeName,
3369 roleInfoList});
3370
3371 // Can throw RelationServiceNotRegisteredException
3372 isActive();
3373
3374 // For each role info (corresponding to a role not initialized by the
3375 // role list provided by the user), try to set in the relation a role
3376 // with an empty list of ObjectNames.
3377 // A check is performed to verify that the role can be set to an
3378 // empty value, according to its minimum cardinality
3379 for (Iterator roleInfoIter = roleInfoList.iterator();
3380 roleInfoIter.hasNext();) {
3381
3382 RoleInfo currRoleInfo = (RoleInfo)(roleInfoIter.next());
3383 String roleName = currRoleInfo.getName();
3384
3385 // Creates an empty value
3386 List<ObjectName> emptyValue = new ArrayList<ObjectName>();
3387 // Creates a role
3388 Role role = new Role(roleName, emptyValue);
3389
3390 if (relationBaseFlag) {
3391
3392 // Internal relation
3393 // Can throw InvalidRoleValueException
3394 //
3395 // Will not throw RoleNotFoundException (role to be
3396 // initialized), or RelationNotFoundException, or
3397 // RelationTypeNotFoundException
3398 try {
3399 relationObj.setRoleInt(role, true, this, false);
3400
3401 } catch (RoleNotFoundException exc1) {
3402 throw new RuntimeException(exc1.getMessage());
3403 } catch (RelationNotFoundException exc2) {
3404 throw new RuntimeException(exc2.getMessage());
3405 } catch (RelationTypeNotFoundException exc3) {
3406 throw new RuntimeException(exc3.getMessage());
3407 }
3408
3409 } else {
3410
3411 // Relation is an MBean
3412 // Use standard setRole()
3413 Object[] params = new Object[1];
3414 params[0] = role;
3415 String[] signature = new String[1];
3416 signature[0] = "javax.management.relation.Role";
3417 // Can throw MBeanException wrapping
3418 // InvalidRoleValueException. Returns the target exception to
3419 // be homogeneous.
3420 //
3421 // Will not throw MBeanException (wrapping
3422 // RoleNotFoundException or MBeanException) or
3423 // InstanceNotFoundException, or ReflectionException
3424 //
3425 // Again here the assumption is that the Relation Service and
3426 // the relation MBeans are registered in the same MBean Server.
3427 try {
3428 myMBeanServer.setAttribute(relationObjName,
3429 new Attribute("Role", role));
3430
3431 } catch (InstanceNotFoundException exc1) {
3432 throw new RuntimeException(exc1.getMessage());
3433 } catch (ReflectionException exc3) {
3434 throw new RuntimeException(exc3.getMessage());
3435 } catch (MBeanException exc2) {
3436 Exception wrappedExc = exc2.getTargetException();
3437 if (wrappedExc instanceof InvalidRoleValueException) {
3438 throw ((InvalidRoleValueException)wrappedExc);
3439 } else {
3440 throw new RuntimeException(wrappedExc.getMessage());
3441 }
3442 } catch (AttributeNotFoundException exc4) {
3443 throw new RuntimeException(exc4.getMessage());
3444 } catch (InvalidAttributeValueException exc5) {
3445 throw new RuntimeException(exc5.getMessage());
3446 }
3447 }
3448 }
3449
3450 RELATION_LOGGER.exiting(RelationService.class.getName(),
3451 "initializeMissingRoles");
3452 return;
3453 }
3454
3455 // Throws an exception corresponding to a given problem type
3456 //
3457 // -param pbType possible problem, defined in RoleUnresolved
3458 // -param roleName role name
3459 //
3460 // -exception IllegalArgumentException if null parameter
3461 // -exception RoleNotFoundException for problems:
3462 // - NO_ROLE_WITH_NAME
3463 // - ROLE_NOT_READABLE
3464 // - ROLE_NOT_WRITABLE
3465 // -exception InvalidRoleValueException for problems:
3466 // - LESS_THAN_MIN_ROLE_DEGREE
3467 // - MORE_THAN_MAX_ROLE_DEGREE
3468 // - REF_MBEAN_OF_INCORRECT_CLASS
3469 // - REF_MBEAN_NOT_REGISTERED
3470 static void throwRoleProblemException(int pbType,
3471 String roleName)
3472 throws IllegalArgumentException,
3473 RoleNotFoundException,
3474 InvalidRoleValueException {
3475
3476 if (roleName == null) {
3477 String excMsg = "Invalid parameter.";
3478 throw new IllegalArgumentException(excMsg);
3479 }
3480
3481 // Exception type: 1 = RoleNotFoundException
3482 // 2 = InvalidRoleValueException
3483 int excType = 0;
3484
3485 String excMsgPart = null;
3486
3487 switch (pbType) {
3488 case RoleStatus.NO_ROLE_WITH_NAME:
3489 excMsgPart = " does not exist in relation.";
3490 excType = 1;
3491 break;
3492 case RoleStatus.ROLE_NOT_READABLE:
3493 excMsgPart = " is not readable.";
3494 excType = 1;
3495 break;
3496 case RoleStatus.ROLE_NOT_WRITABLE:
3497 excMsgPart = " is not writable.";
3498 excType = 1;
3499 break;
3500 case RoleStatus.LESS_THAN_MIN_ROLE_DEGREE:
3501 excMsgPart = " has a number of MBean references less than the expected minimum degree.";
3502 excType = 2;
3503 break;
3504 case RoleStatus.MORE_THAN_MAX_ROLE_DEGREE:
3505 excMsgPart = " has a number of MBean references greater than the expected maximum degree.";
3506 excType = 2;
3507 break;
3508 case RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS:
3509 excMsgPart = " has an MBean reference to an MBean not of the expected class of references for that role.";
3510 excType = 2;
3511 break;
3512 case RoleStatus.REF_MBEAN_NOT_REGISTERED:
3513 excMsgPart = " has a reference to null or to an MBean not registered.";
3514 excType = 2;
3515 break;
3516 }
3517 // No default as we must have been in one of those cases
3518
3519 StringBuilder excMsgStrB = new StringBuilder(roleName);
3520 excMsgStrB.append(excMsgPart);
3521 String excMsg = excMsgStrB.toString();
3522 if (excType == 1) {
3523 throw new RoleNotFoundException(excMsg);
3524
3525 } else if (excType == 2) {
3526 throw new InvalidRoleValueException(excMsg);
3527 }
3528 }
3529
3530 // Sends a notification of given type, with given parameters
3531 //
3532 // -param intNtfType integer to represent notification type:
3533 // - 1 : create
3534 // - 2 : update
3535 // - 3 : delete
3536 // -param message human-readable message
3537 // -param relationId relation id of the created/updated/deleted relation
3538 // -param unregMBeanList list of ObjectNames of referenced MBeans
3539 // expected to be unregistered due to relation removal (only for removal,
3540 // due to CIM qualifiers, can be null)
3541 // -param roleName role name
3542 // -param roleNewValue role new value (ArrayList of ObjectNames)
3543 // -param oldValue old role value (ArrayList of ObjectNames)
3544 //
3545 // -exception IllegalArgument if null parameter
3546 // -exception RelationNotFoundException if no relation for given id
3547 private void sendNotificationInt(int intNtfType,
3548 String message,
3549 String relationId,
3550 List<ObjectName> unregMBeanList,
3551 String roleName,
3552 List<ObjectName> roleNewValue,
3553 List<ObjectName> oldValue)
3554 throws IllegalArgumentException,
3555 RelationNotFoundException {
3556
3557 if (message == null ||
3558 relationId == null ||
3559 (intNtfType != 3 && unregMBeanList != null) ||
3560 (intNtfType == 2 &&
3561 (roleName == null ||
3562 roleNewValue == null ||
3563 oldValue == null))) {
3564 String excMsg = "Invalid parameter.";
3565 throw new IllegalArgumentException(excMsg);
3566 }
3567
3568 RELATION_LOGGER.entering(RelationService.class.getName(),
3569 "sendNotificationInt", new Object[] {intNtfType, message,
3570 relationId, unregMBeanList, roleName, roleNewValue, oldValue});
3571
3572 // Relation type name
3573 // Note: do not use getRelationTypeName() as if it is a relation MBean
3574 // it is already unregistered.
3575 String relTypeName = null;
3576 synchronized(myRelId2RelTypeMap) {
3577 relTypeName = (myRelId2RelTypeMap.get(relationId));
3578 }
3579
3580 // ObjectName (for a relation MBean)
3581 // Can also throw a RelationNotFoundException, but detected above
3582 ObjectName relObjName = isRelationMBean(relationId);
3583
3584 String ntfType = null;
3585 if (relObjName != null) {
3586 switch (intNtfType) {
3587 case 1:
3588 ntfType = RelationNotification.RELATION_MBEAN_CREATION;
3589 break;
3590 case 2:
3591 ntfType = RelationNotification.RELATION_MBEAN_UPDATE;
3592 break;
3593 case 3:
3594 ntfType = RelationNotification.RELATION_MBEAN_REMOVAL;
3595 break;
3596 }
3597 } else {
3598 switch (intNtfType) {
3599 case 1:
3600 ntfType = RelationNotification.RELATION_BASIC_CREATION;
3601 break;
3602 case 2:
3603 ntfType = RelationNotification.RELATION_BASIC_UPDATE;
3604 break;
3605 case 3:
3606 ntfType = RelationNotification.RELATION_BASIC_REMOVAL;
3607 break;
3608 }
3609 }
3610
3611 // Sequence number
3612 Long seqNbr = getNotificationSequenceNumber();
3613
3614 // Timestamp
3615 Date currDate = new Date();
3616 long timeStamp = currDate.getTime();
3617
3618 RelationNotification ntf = null;
3619
3620 if (ntfType.equals(RelationNotification.RELATION_BASIC_CREATION) ||
3621 ntfType.equals(RelationNotification.RELATION_MBEAN_CREATION) ||
3622 ntfType.equals(RelationNotification.RELATION_BASIC_REMOVAL) ||
3623 ntfType.equals(RelationNotification.RELATION_MBEAN_REMOVAL))
3624
3625 // Creation or removal
3626 ntf = new RelationNotification(ntfType,
3627 this,
3628 seqNbr.longValue(),
3629 timeStamp,
3630 message,
3631 relationId,
3632 relTypeName,
3633 relObjName,
3634 unregMBeanList);
3635
3636 else if (ntfType.equals(RelationNotification.RELATION_BASIC_UPDATE)
3637 ||
3638 ntfType.equals(RelationNotification.RELATION_MBEAN_UPDATE))
3639 {
3640 // Update
3641 ntf = new RelationNotification(ntfType,
3642 this,
3643 seqNbr.longValue(),
3644 timeStamp,
3645 message,
3646 relationId,
3647 relTypeName,
3648 relObjName,
3649 roleName,
3650 roleNewValue,
3651 oldValue);
3652 }
3653
3654 sendNotification(ntf);
3655
3656 RELATION_LOGGER.exiting(RelationService.class.getName(),
3657 "sendNotificationInt");
3658 return;
3659 }
3660
3661 // Checks, for the unregistration of an MBean referenced in the roles given
3662 // in parameter, if the relation has to be removed or not, regarding
3663 // expected minimum role cardinality and current number of
3664 // references in each role after removal of the current one.
3665 // If the relation is kept, calls handleMBeanUnregistration() callback of
3666 // the relation to update it.
3667 //
3668 // -param relationId relation id
3669 // -param objectName ObjectName of the unregistered MBean
3670 // -param roleNameList list of names of roles where the unregistered
3671 // MBean is referenced.
3672 //
3673 // -exception IllegalArgumentException if null parameter
3674 // -exception RelationServiceNotRegisteredException if the Relation
3675 // Service is not registered in the MBean Server
3676 // -exception RelationNotFoundException if unknown relation id
3677 // -exception RoleNotFoundException if one role given as parameter does
3678 // not exist in the relation
3679 private void handleReferenceUnregistration(String relationId,
3680 ObjectName objectName,
3681 List roleNameList)
3682 throws IllegalArgumentException,
3683 RelationServiceNotRegisteredException,
3684 RelationNotFoundException,
3685 RoleNotFoundException {
3686
3687 if (relationId == null ||
3688 roleNameList == null ||
3689 objectName == null) {
3690 String excMsg = "Invalid parameter.";
3691 throw new IllegalArgumentException(excMsg);
3692 }
3693
3694 RELATION_LOGGER.entering(RelationService.class.getName(),
3695 "handleReferenceUnregistration",
3696 new Object[] {relationId, objectName, roleNameList});
3697
3698 // Can throw RelationServiceNotRegisteredException
3699 isActive();
3700
3701 // Retrieves the relation type name of the relation
3702 // Can throw RelationNotFoundException
3703 String currRelTypeName = getRelationTypeName(relationId);
3704
3705 // Retrieves the relation
3706 // Can throw RelationNotFoundException, but already detected above
3707 Object relObj = getRelation(relationId);
3708
3709 // Flag to specify if the relation has to be deleted
3710 boolean deleteRelFlag = false;
3711
3712 for (Iterator roleNameIter = roleNameList.iterator();
3713 roleNameIter.hasNext();) {
3714
3715 if (deleteRelFlag) {
3716 break;
3717 }
3718
3719 String currRoleName = (String)(roleNameIter.next());
3720 // Retrieves number of MBeans currently referenced in role
3721 // BEWARE! Do not use getRole() as role may be not readable
3722 //
3723 // Can throw RelationNotFoundException (but already checked),
3724 // RoleNotFoundException
3725 int currRoleRefNbr =
3726 (getRoleCardinality(relationId, currRoleName)).intValue();
3727
3728 // Retrieves new number of element in role
3729 int currRoleNewRefNbr = currRoleRefNbr - 1;
3730
3731 // Retrieves role info for that role
3732 //
3733 // Shall not throw RelationTypeNotFoundException or
3734 // RoleInfoNotFoundException
3735 RoleInfo currRoleInfo = null;
3736 try {
3737 currRoleInfo = getRoleInfo(currRelTypeName,
3738 currRoleName);
3739 } catch (RelationTypeNotFoundException exc1) {
3740 throw new RuntimeException(exc1.getMessage());
3741 } catch (RoleInfoNotFoundException exc2) {
3742 throw new RuntimeException(exc2.getMessage());
3743 }
3744
3745 // Checks with expected minimum number of elements
3746 boolean chkMinFlag = currRoleInfo.checkMinDegree(currRoleNewRefNbr);
3747
3748 if (!chkMinFlag) {
3749 // The relation has to be deleted
3750 deleteRelFlag = true;
3751 }
3752 }
3753
3754 if (deleteRelFlag) {
3755 // Removes the relation
3756 removeRelation(relationId);
3757
3758 } else {
3759
3760 // Updates each role in the relation using
3761 // handleMBeanUnregistration() callback
3762 //
3763 // BEWARE: this roleNameList list MUST BE A COPY of a role name
3764 // list for a referenced MBean in a relation, NOT a
3765 // reference to an original one part of the
3766 // myRefedMBeanObjName2RelIdsMap!!!! Because each role
3767 // which name is in that list will be updated (potentially
3768 // using setRole(). So the Relation Service will update the
3769 // myRefedMBeanObjName2RelIdsMap to refelect the new role
3770 // value!
3771 for (Iterator roleNameIter = roleNameList.iterator();
3772 roleNameIter.hasNext();) {
3773
3774 String currRoleName = (String)(roleNameIter.next());
3775
3776 if (relObj instanceof RelationSupport) {
3777 // Internal relation
3778 // Can throw RoleNotFoundException (but already checked)
3779 //
3780 // Shall not throw
3781 // RelationTypeNotFoundException,
3782 // InvalidRoleValueException (value was correct, removing
3783 // one reference shall not invalidate it, else detected
3784 // above)
3785 try {
3786 ((RelationSupport)relObj).handleMBeanUnregistrationInt(
3787 objectName,
3788 currRoleName,
3789 true,
3790 this);
3791 } catch (RelationTypeNotFoundException exc3) {
3792 throw new RuntimeException(exc3.getMessage());
3793 } catch (InvalidRoleValueException exc4) {
3794 throw new RuntimeException(exc4.getMessage());
3795 }
3796
3797 } else {
3798 // Relation MBean
3799 Object[] params = new Object[2];
3800 params[0] = objectName;
3801 params[1] = currRoleName;
3802 String[] signature = new String[2];
3803 signature[0] = "javax.management.ObjectName";
3804 signature[1] = "java.lang.String";
3805 // Shall not throw InstanceNotFoundException, or
3806 // MBeanException (wrapping RoleNotFoundException or
3807 // MBeanException or InvalidRoleValueException) or
3808 // ReflectionException
3809 try {
3810 myMBeanServer.invoke(((ObjectName)relObj),
3811 "handleMBeanUnregistration",
3812 params,
3813 signature);
3814 } catch (InstanceNotFoundException exc1) {
3815 throw new RuntimeException(exc1.getMessage());
3816 } catch (ReflectionException exc3) {
3817 throw new RuntimeException(exc3.getMessage());
3818 } catch (MBeanException exc2) {
3819 Exception wrappedExc = exc2.getTargetException();
3820 throw new RuntimeException(wrappedExc.getMessage());
3821 }
3822
3823 }
3824 }
3825 }
3826
3827 RELATION_LOGGER.exiting(RelationService.class.getName(),
3828 "handleReferenceUnregistration");
3829 return;
3830 }
3831}