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