author | dfuchs |
Fri, 20 Jan 2017 18:41:12 +0000 | |
changeset 43235 | da1786d695b6 |
parent 25859 | 3317bb8137f4 |
permissions | -rw-r--r-- |
2 | 1 |
/* |
43235 | 2 |
* Copyright (c) 2000, 2017, Oracle and/or its affiliates. All rights reserved. |
2 | 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 |
|
5506 | 7 |
* published by the Free Software Foundation. Oracle designates this |
2 | 8 |
* particular file as subject to the "Classpath" exception as provided |
5506 | 9 |
* by Oracle in the LICENSE file that accompanied this code. |
2 | 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 |
* |
|
5506 | 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. |
|
2 | 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; |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
38 |
import java.util.concurrent.atomic.AtomicLong; |
43235 | 39 |
import java.lang.System.Logger.Level; |
2 | 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. |
|
1004 | 111 |
private final Map<ObjectName,Map<String,List<String>>> |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
126 |
private final AtomicLong atomicSeqNo = new AtomicLong(); |
2 | 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 |
|
21278 | 135 |
// informed of referenced MBean deregistrations |
2 | 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 |
||
43235 | 160 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY"); |
2 | 161 |
|
162 |
setPurgeFlag(immediatePurgeFlag); |
|
163 |
||
43235 | 164 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 287 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationTypeName); |
2 | 288 |
|
289 |
// Can throw an InvalidRelationTypeException |
|
290 |
RelationType relType = |
|
291 |
new RelationTypeSupport(relationTypeName, roleInfoArray); |
|
292 |
||
293 |
addRelationTypeInt(relType); |
|
294 |
||
43235 | 295 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 324 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY"); |
2 | 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 |
||
43235 | 344 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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() { |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
354 |
ArrayList<String> result; |
2 | 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 |
||
43235 | 382 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationTypeName); |
2 | 383 |
|
384 |
// Can throw a RelationTypeNotFoundException |
|
385 |
RelationType relType = getRelationType(relationTypeName); |
|
386 |
||
43235 | 387 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 416 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
417 |
relationTypeName, roleInfoName); |
|
2 | 418 |
|
419 |
// Can throw a RelationTypeNotFoundException |
|
420 |
RelationType relType = getRelationType(relationTypeName); |
|
421 |
||
422 |
// Can throw a RoleInfoNotFoundException |
|
423 |
RoleInfo roleInfo = relType.getRoleInfo(roleInfoName); |
|
424 |
||
43235 | 425 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 455 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationTypeName); |
2 | 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 |
||
43235 | 497 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 558 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
559 |
relationId, relationTypeName, roleList); |
|
2 | 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); |
|
43235 | 579 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 644 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationObjectName); |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
661 |
String relId; |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
684 |
ObjectName relServObjName; |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
714 |
String relTypeName; |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
735 |
RoleList roleList; |
2 | 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 |
||
43235 | 780 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 807 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 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 |
||
43235 | 837 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", objectName); |
2 | 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 |
||
43235 | 867 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 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() { |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
885 |
List<String> result; |
2 | 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 |
||
43235 | 918 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
919 |
roleName, relationTypeName); |
|
2 | 920 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
921 |
Integer result; |
2 | 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) { |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
938 |
result = Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); |
2 | 939 |
} |
940 |
||
43235 | 941 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 979 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
980 |
role, relationTypeName, initFlag); |
|
2 | 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 |
||
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
992 |
RoleInfo roleInfo; |
2 | 993 |
try { |
994 |
roleInfo = relType.getRoleInfo(roleName); |
|
995 |
} catch (RoleInfoNotFoundException exc) { |
|
43235 | 996 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
997 |
return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); |
2 | 998 |
} |
999 |
||
1000 |
Integer result = checkRoleInt(2, |
|
1001 |
roleName, |
|
1002 |
roleValue, |
|
1003 |
roleInfo, |
|
1004 |
writeChkFlag); |
|
1005 |
||
43235 | 1006 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1036 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 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 |
||
43235 | 1051 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
1090 |
if (!(oldValue instanceof ArrayList<?>)) |
2 | 1091 |
oldValue = new ArrayList<ObjectName>(oldValue); |
1092 |
||
43235 | 1093 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
1094 |
relationId, newRole, oldValue); |
|
2 | 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 |
||
43235 | 1118 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1149 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
1150 |
relationId, unregMBeanList); |
|
2 | 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 |
||
43235 | 1162 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1201 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
1202 |
relationId, newRole, oldValue); |
|
2 | 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 |
||
43235 | 1278 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1312 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
1397 |
String relTypeName; |
2 | 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 |
||
43235 | 1415 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1448 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY"); |
2 | 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; |
|
1004 | 1463 |
synchronized(myRefedMBeanObjName2RelIdsMap) { |
2 | 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 |
||
43235 | 1545 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1580 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
1581 |
mbeanName, relationTypeName, roleName); |
|
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
1598 |
List<String> relIdList; |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
1612 |
String currRelTypeName; |
2 | 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 |
||
43235 | 1653 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1688 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
1689 |
mbeanName, relationTypeName, roleName); |
|
2 | 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 |
||
43235 | 1736 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1760 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY"); |
2 | 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 |
||
43235 | 1774 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1809 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
1810 |
relationId, roleName); |
|
2 | 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)); |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
1845 |
if (invokeResult == null || invokeResult instanceof ArrayList<?>) |
2 | 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 |
||
43235 | 1863 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1895 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 1896 |
|
1897 |
// Can throw RelationServiceNotRegisteredException |
|
1898 |
isActive(); |
|
1899 |
||
1900 |
// Can throw a RelationNotFoundException |
|
1901 |
Object relObj = getRelation(relationId); |
|
1902 |
||
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
1903 |
RoleResult result; |
2 | 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 |
||
43235 | 1939 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 1967 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 1968 |
|
1969 |
// Can throw a RelationNotFoundException |
|
1970 |
Object relObj = getRelation(relationId); |
|
1971 |
||
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
1972 |
RoleResult result; |
2 | 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 |
||
43235 | 1990 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2017 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
2018 |
relationId, roleName); |
|
2 | 2019 |
|
2020 |
// Can throw a RelationNotFoundException |
|
2021 |
Object relObj = getRelation(relationId); |
|
2022 |
||
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2023 |
Integer result; |
2 | 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 |
||
43235 | 2060 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
|
21278 | 2069 |
* consistency of relations by handling referenced MBean deregistrations. |
2 | 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 |
||
43235 | 2108 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
2109 |
relationId, role); |
|
2 | 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 |
||
43235 | 2172 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
|
21278 | 2181 |
* consistency of relations by handling referenced MBean deregistrations. |
2 | 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 |
||
43235 | 2208 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
2209 |
relationId, roleList); |
|
2 | 2210 |
|
2211 |
// Can throw RelationServiceNotRegisteredException |
|
2212 |
isActive(); |
|
2213 |
||
2214 |
// Can throw a RelationNotFoundException |
|
2215 |
Object relObj = getRelation(relationId); |
|
2216 |
||
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2217 |
RoleResult result; |
2 | 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 |
||
43235 | 2257 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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: |
|
21656
d4c777ccb1db
8028014: Doclint warning/error cleanup in javax.management
rriggs
parents:
21278
diff
changeset
|
2267 |
* <P> ObjectName {@literal ->} ArrayList of String (role names) |
2 | 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 |
||
43235 | 2283 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", |
2284 |
relationId); |
|
2 | 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 |
||
43235 | 2307 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2331 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 2332 |
|
2333 |
// Can throw a RelationNotFoundException |
|
2334 |
Object relObj = getRelation(relationId); |
|
2335 |
||
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2336 |
String result; |
2 | 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 |
||
43235 | 2354 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2379 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", notif); |
2 | 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 :) |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2417 |
String relId; |
2 | 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 |
||
43235 | 2437 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2451 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY"); |
2 | 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 |
||
43235 | 2469 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2493 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY"); |
2 | 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 |
||
43235 | 2523 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2547 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationTypeName); |
2 | 2548 |
|
2549 |
// No null relation type accepted, so can use get() |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2550 |
RelationType relType; |
2 | 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 |
||
43235 | 2562 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2589 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0}", relationId); |
2 | 2590 |
|
2591 |
// No null relation accepted, so can use get() |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2592 |
Object rel; |
2 | 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 |
||
43235 | 2602 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2632 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
2633 |
objectName, relationId, roleName); |
|
2 | 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 |
||
43235 | 2686 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2718 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2} {3}", |
2719 |
objectName, relationId, roleName, allRolesFlag); |
|
2 | 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. |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2730 |
Map<String,List<String>> mbeanRefMap = |
2 | 2731 |
(myRefedMBeanObjName2RelIdsMap.get(objectName)); |
2732 |
||
2733 |
if (mbeanRefMap == null) { |
|
2734 |
// The MBean is no longer referenced |
|
43235 | 2735 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 2736 |
return true; |
2737 |
} |
|
2738 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2739 |
List<String> roleNames = null; |
2 | 2740 |
if (!allRolesFlag) { |
2741 |
// Now retrieves the roles of current relation where the MBean |
|
2742 |
// was referenced |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2743 |
roleNames = mbeanRefMap.get(relationId); |
2 | 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 |
||
43235 | 2768 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 2769 |
return noLongerRefFlag; |
2770 |
} |
|
2771 |
||
2772 |
// Updates the listener registered to the MBean Server to be informed of |
|
21278 | 2773 |
// referenced MBean deregistrations |
2 | 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. |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2782 |
private void updateUnregistrationListener(List<ObjectName> newRefList, |
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2783 |
List<ObjectName> obsoleteRefList) |
2 | 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 |
||
43235 | 2793 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1}", |
2794 |
newRefList, obsoleteRefList); |
|
2 | 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) { |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2812 |
for (ObjectName newObjName : newRefList) |
2 | 2813 |
myUnregNtfFilter.enableObjectName(newObjName); |
2814 |
} |
|
2815 |
||
2816 |
if (obsoleteRefList != null) { |
|
2817 |
// Disables ObjectNames in obsoleteRefList |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2818 |
for (ObjectName obsObjName : obsoleteRefList) |
2 | 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 |
||
43235 | 2878 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 2944 |
RELATION_LOGGER.log(Level.TRACE, |
2945 |
"ENTRY {0} {1} {2} {3} {4} {5}", |
|
2946 |
relationBaseFlag, relationObj, relationObjName, |
|
2947 |
relationId, relationTypeName, roleList); |
|
2 | 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. |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2978 |
List<RoleInfo> roleInfoList = new ArrayList<RoleInfo>(relType.getRoleInfos()); |
2 | 2979 |
|
2980 |
if (roleList != null) { |
|
2981 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2982 |
for (Role currRole : roleList.asList()) { |
2 | 2983 |
String currRoleName = currRole.getRoleName(); |
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
2984 |
List<ObjectName> currRoleValue = currRole.getRoleValue(); |
2 | 2985 |
// Retrieves corresponding role info |
2986 |
// Can throw a RoleInfoNotFoundException to be converted into a |
|
2987 |
// RoleNotFoundException |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
2988 |
RoleInfo roleInfo; |
2 | 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. |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3063 |
for (Role currRole : roleList.asList()) { |
2 | 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 |
||
43235 | 3086 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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, |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3114 |
List<ObjectName> roleValue, |
2 | 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 |
||
43235 | 3126 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2} {3} {4}", |
3127 |
chkType, roleName, roleValue, roleInfo, writeChkFlag); |
|
2 | 3128 |
|
3129 |
// Compares names |
|
3130 |
String expName = roleInfo.getName(); |
|
3131 |
if (!(roleName.equals(expName))) { |
|
43235 | 3132 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
3133 |
return Integer.valueOf(RoleStatus.NO_ROLE_WITH_NAME); |
2 | 3134 |
} |
3135 |
||
3136 |
// Checks read access if required |
|
3137 |
if (chkType == 1) { |
|
3138 |
boolean isReadable = roleInfo.isReadable(); |
|
3139 |
if (!isReadable) { |
|
43235 | 3140 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
527 | 3141 |
return Integer.valueOf(RoleStatus.ROLE_NOT_READABLE); |
2 | 3142 |
} else { |
3143 |
// End of check :) |
|
43235 | 3144 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3145 |
return 0; |
2 | 3146 |
} |
3147 |
} |
|
3148 |
||
3149 |
// Checks write access if required |
|
3150 |
if (writeChkFlag) { |
|
3151 |
boolean isWritable = roleInfo.isWritable(); |
|
3152 |
if (!isWritable) { |
|
43235 | 3153 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3154 |
return RoleStatus.ROLE_NOT_WRITABLE; |
2 | 3155 |
} |
3156 |
} |
|
3157 |
||
3158 |
int refNbr = roleValue.size(); |
|
3159 |
||
3160 |
// Checks minimum cardinality |
|
3161 |
boolean chkMinFlag = roleInfo.checkMinDegree(refNbr); |
|
3162 |
if (!chkMinFlag) { |
|
43235 | 3163 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3164 |
return RoleStatus.LESS_THAN_MIN_ROLE_DEGREE; |
2 | 3165 |
} |
3166 |
||
3167 |
// Checks maximum cardinality |
|
3168 |
boolean chkMaxFlag = roleInfo.checkMaxDegree(refNbr); |
|
3169 |
if (!chkMaxFlag) { |
|
43235 | 3170 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3171 |
return RoleStatus.MORE_THAN_MAX_ROLE_DEGREE; |
2 | 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 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3182 |
for (ObjectName currObjName : roleValue) { |
2 | 3183 |
|
3184 |
// Checks it is registered |
|
3185 |
if (currObjName == null) { |
|
43235 | 3186 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3187 |
return RoleStatus.REF_MBEAN_NOT_REGISTERED; |
2 | 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) { |
|
43235 | 3196 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3197 |
return RoleStatus.REF_MBEAN_OF_INCORRECT_CLASS; |
2 | 3198 |
} |
3199 |
||
3200 |
} catch (InstanceNotFoundException exc) { |
|
43235 | 3201 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3202 |
return RoleStatus.REF_MBEAN_NOT_REGISTERED; |
2 | 3203 |
} |
3204 |
} |
|
3205 |
||
43235 | 3206 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
25522
10d789df41bb
8049892: Replace uses of 'new Integer()' with appropriate alternative across core classes
prr
parents:
23010
diff
changeset
|
3207 |
return 0; |
2 | 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, |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3240 |
List<RoleInfo> roleInfoList) |
2 | 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 |
||
43235 | 3258 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2} {3} {4} {5}", |
3259 |
relationBaseFlag, relationObj, relationObjName, |
|
3260 |
relationId, relationTypeName, roleInfoList); |
|
2 | 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 |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3270 |
for (RoleInfo currRoleInfo : roleInfoList) { |
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3271 |
|
2 | 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 |
||
43235 | 3339 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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 |
||
43235 | 3456 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2} {3} {4} {5} {6}", |
3457 |
intNtfType, message, relationId, unregMBeanList, |
|
3458 |
roleName, roleNewValue, oldValue); |
|
2 | 3459 |
|
3460 |
// Relation type name |
|
3461 |
// Note: do not use getRelationTypeName() as if it is a relation MBean |
|
3462 |
// it is already unregistered. |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
3463 |
String relTypeName; |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
3500 |
Long seqNo = atomicSeqNo.incrementAndGet(); |
2 | 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, |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
3516 |
seqNo.longValue(), |
2 | 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, |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
3531 |
seqNo.longValue(), |
2 | 3532 |
timeStamp, |
3533 |
message, |
|
3534 |
relationId, |
|
3535 |
relTypeName, |
|
3536 |
relObjName, |
|
3537 |
roleName, |
|
3538 |
roleNewValue, |
|
3539 |
oldValue); |
|
3540 |
} |
|
3541 |
||
3542 |
sendNotification(ntf); |
|
3543 |
||
43235 | 3544 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 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, |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3568 |
List<String> roleNameList) |
2 | 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 |
||
43235 | 3581 |
RELATION_LOGGER.log(Level.TRACE, "ENTRY {0} {1} {2}", |
3582 |
relationId, objectName, roleNameList); |
|
2 | 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 |
||
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3598 |
for (String currRoleName : roleNameList) { |
2 | 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 |
|
526
61ba2d5ea9da
6701459: Synchronization bug pattern found in javax.management.relation.RelationService
emcmanus
parents:
2
diff
changeset
|
3619 |
RoleInfo currRoleInfo; |
2 | 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! |
|
1510
e747d3193ef2
6763639: Remove "rawtypes" warnings from JMX code
emcmanus
parents:
1004
diff
changeset
|
3655 |
for (String currRoleName : roleNameList) { |
2 | 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 |
||
43235 | 3708 |
RELATION_LOGGER.log(Level.TRACE, "RETURN"); |
2 | 3709 |
return; |
3710 |
} |
|
3711 |
} |