History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/management/relation/RelationService.java (1 of 18352 files). Show all

Unified · Split

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