Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: javax/management/relation/RelationSupport.java


1   /*
2    * JBoss, the OpenSource J2EE webOS
3    *
4    * Distributable under LGPL license.
5    * See terms of license at gnu.org.
6    */
7   package javax.management.relation;
8   
9   import java.util.ArrayList;
10  import java.util.HashMap;
11  import java.util.Iterator;
12  import java.util.List;
13  import java.util.Map;
14  
15  import javax.management.InstanceNotFoundException;
16  import javax.management.IntrospectionException;
17  import javax.management.MBeanException;
18  import javax.management.MBeanRegistration;
19  import javax.management.MBeanServer;
20  import javax.management.ObjectName;
21  import javax.management.ReflectionException;
22  import javax.management.RuntimeMBeanException;
23  
24  import javax.management.relation.RelationServiceMBean;
25  
26  import org.jboss.mx.util.MBeanProxy;
27  import org.jboss.mx.util.MBeanProxyCreationException;
28  
29  /**
30   * Implements the management interface for a relation
31   * created internally within the relation service. The relation can
32   * have only roles - no attributes or methods.<p>
33   *
34   * The relation support managed bean can be created externally, including
35   * extending it, and then registered with the relation service.<p>
36   *
37   * @author  <a href="mailto:Adrian.Brock@HappeningTimes.com">Adrian Brock</a>.
38   * @author  <a href="mailto:juha@jboss.org">Juha Lindfors</a>
39   *
40   * @version $Revision: 1.5.6.1 $
41   *
42   * <p><b>Revisions:</b>
43   *
44   * <p><b>20020412 Juha Lindfors:</b>
45   * <ul>
46   * <li>Changed MBeanProxy exception handling on create methods -- only need to
47   *     catch one MBeanProxyCreationException
48   * </li>
49   * </ul> 
50   */
51  public class RelationSupport
52    implements RelationSupportMBean, MBeanRegistration
53  {
54    // Constants -----------------------------------------------------
55  
56    // Attributes ----------------------------------------------------
57  
58    /**
59     * The relation id.
60     */
61    String relationId;
62  
63    /**
64     * The relation service
65     */
66    ObjectName relationService;
67  
68    /**
69     * A proxy to the relation service
70     */
71    private RelationServiceMBean serviceProxy;
72  
73    /**
74     * The mbean server
75     */
76    MBeanServer server;
77  
78    /**
79     * The relation type name
80     */
81    String relationTypeName;
82  
83    /**
84     * The roles mapped by role name
85     */
86    HashMap roles;
87  
88    /**
89     * Wether this relation is registered in the relation service
90     */
91    Boolean registered;
92  
93    // Static --------------------------------------------------------
94  
95    // Constructors --------------------------------------------------
96  
97    /**
98     * Construct a new relation support object.<p>
99     *
100    * This constructor is intended for use when manually registrating
101    * a relation support object or an class that extends it.<p>
102    *
103    * Constructing the object does not register it with the relation
104    * service, only the following is validated at this stage.<p>
105    *
106    * The relation id is mandatory.<br>
107    * The relation service name is mandatory.<br>.
108    * The relation type name is mandatory.<br>
109    * The same name is used for more than one role.<p>
110    *
111    * @param relationId the relation Id
112    * @param relationService the object name of the relation service
113    * @param relationTypeName the name of the relation type
114    * @param roleList the roles in this relation
115    * @exception IllegalArgumentException for null values.
116    * @exception InvalidRoleValueException when two roles have the same name.
117    */
118   public RelationSupport(String relationId, ObjectName relationService,
119                          String relationTypeName, RoleList roleList)
120     throws IllegalArgumentException, InvalidRoleValueException
121   {
122     init(relationId, relationService, null, relationTypeName, roleList);
123   }
124 
125   /**
126    * Construct a new relation support object.<p>
127    *
128    * This constructor is intended for use when manually registrating
129    * a relation that delegates to relation support.<p>
130    *
131    * Constructing the object does not register it with the relation
132    * service, only the following is validated at this stage.<p>
133    *
134    * The relation id is mandatory.<br>
135    * The relation service name is mandatory.<br>.
136    * The mbean service is mandatory.<br>.
137    * The relation type name is mandatory.<br>
138    * The same name is used for more than one role.<p>
139    *
140    * @param relationId the relation Id
141    * @param relationService the object name of the relation service
142    * @param mbeanServer the object name of the relation service
143    * @param relationTypeName the name of the relation type
144    * @param roleList the roles in this relation
145    * @exception IllegalArgumentException for null values.
146    * @exception InvalidRoleValueException when two roles have the same name.
147    */
148   public RelationSupport(String relationId, ObjectName relationService,
149                          MBeanServer mbeanServer, String relationTypeName, 
150                          RoleList roleList)
151     throws IllegalArgumentException, InvalidRoleValueException
152   {
153     init(relationId, relationService, mbeanServer, relationTypeName,
154          roleList);
155   }
156 
157   // Relation implementation -----------------------------------------
158 
159   public RoleResult getAllRoles()
160     throws RelationServiceNotRegisteredException
161   {
162     RoleList resolvedResult = new RoleList();
163     RoleUnresolvedList unresolvedResult = new RoleUnresolvedList();
164     RoleResult result = new RoleResult(resolvedResult, unresolvedResult);
165     synchronized (roles)
166     {
167       Iterator iterator = roles.values().iterator();
168       while (iterator.hasNext())
169       {
170         Role role = (Role) iterator.next();
171         int status = checkRoleReadable(role);
172         if (status == 0)
173           resolvedResult.add(role);
174         else
175           unresolvedResult.add(new RoleUnresolved(role.getRoleName(),
176                                                   role.getRoleValue(),
177                                                   status));
178       }
179     }
180     return result;
181   }
182 
183   public Map getReferencedMBeans()
184   {
185     HashMap result = new HashMap();
186     synchronized (roles)
187     {
188       // Look through the roles in this relation
189       Iterator iterator = roles.values().iterator();
190       while (iterator.hasNext())
191       {
192         Role role = (Role) iterator.next();
193         String roleName = role.getRoleName();
194 
195         // Get the mbeans in the role
196         ArrayList mbeans = (ArrayList) role.getRoleValue();
197 
198         for (int i = 0; i < mbeans.size(); i++)
199         {
200           ObjectName mbean = (ObjectName) mbeans.get(i);
201 
202           // Make sure this mbean has an entry
203           ArrayList resultRoles = (ArrayList) result.get(mbean);
204           if (resultRoles == null)
205           {
206             resultRoles = new ArrayList();
207             result.put(mbean, resultRoles);
208           }
209 
210           // It seems the role name should be duplicated?
211           // Include the following test if this is a bug in RI.
212           // if (resultRoles.contains(roleName) == false)
213 
214           // Add the role to this mbean
215           resultRoles.add(roleName);
216         }
217       }
218     }
219 
220     // All done 
221     return result;
222   }
223 
224   public String getRelationId()
225   {
226     return relationId;
227   }
228 
229   public ObjectName getRelationServiceName()
230   {
231     return relationService;
232   }
233 
234   public String getRelationTypeName()
235   {
236     return relationTypeName;
237   }
238 
239   public List getRole(String roleName)
240     throws IllegalArgumentException, RoleNotFoundException, 
241            RelationServiceNotRegisteredException
242   {
243     if (roleName == null)
244       throw new IllegalArgumentException("null role name");
245     validateRoleReadable(roleName);
246     Role role = validateRoleFound(roleName);
247     return role.getRoleValue();
248   }
249 
250   public Integer getRoleCardinality(String roleName)
251     throws IllegalArgumentException, RoleNotFoundException
252   {
253     if (roleName == null)
254       throw new IllegalArgumentException("null role name");
255     Role role = validateRoleFound(roleName);
256     return new Integer(role.getRoleValue().size());
257   }
258 
259   public RoleResult getRoles(String[] roleNames)
260     throws IllegalArgumentException, RelationServiceNotRegisteredException
261   {
262     RoleList resolvedResult = new RoleList();
263     RoleUnresolvedList unresolvedResult = new RoleUnresolvedList();
264     RoleResult result = new RoleResult(resolvedResult, unresolvedResult);
265     for (int i = 0; i < roleNames.length; i++)
266     {
267       Role role = (Role) roles.get(roleNames[i]);
268       int status = checkRoleReadable(role);
269       if (status == 0)
270         resolvedResult.add(role);
271       else
272         unresolvedResult.add(new RoleUnresolved(role.getRoleName(),
273                                                 role.getRoleValue(),
274                                                 status));
275     }
276     return result;
277   }
278 
279   public void handleMBeanUnregistration(ObjectName objectName, String roleName)
280     throws RoleNotFoundException, InvalidRoleValueException,
281            RelationServiceNotRegisteredException, RelationTypeNotFoundException,
282            RelationNotFoundException
283   {
284     checkRegistered();
285     Role role = validateRoleFound(roleName);
286     ArrayList values = (ArrayList) role.getRoleValue();
287     ArrayList oldRoleValue = new ArrayList(values);
288     if (values.remove(objectName) == false)
289       throw new InvalidRoleValueException(roleName + " " + objectName.toString());
290     updateRole(role, oldRoleValue);
291   }
292 
293   public RoleList retrieveAllRoles()
294   {
295     RoleList result = new RoleList(roles.size());
296     synchronized (roles)
297     {
298       Iterator iterator = roles.values().iterator();
299       while (iterator.hasNext())
300         result.add((Role) iterator.next());
301     }
302     return result;
303   }
304 
305   public void setRole(Role role)
306     throws IllegalArgumentException, InvalidRoleValueException,
307            RoleNotFoundException, RelationServiceNotRegisteredException,
308            RelationTypeNotFoundException, RelationNotFoundException
309   {
310     if (role == null)
311       throw new IllegalArgumentException("null role");
312     Role copy = (Role) role.clone();
313     checkRegistered();
314     RoleValidator.validateRole(relationService, server, relationTypeName, copy,
315                                true);
316     Role oldRole = (Role) roles.get(role.getRoleName());
317     ArrayList oldRoleValue = (ArrayList) oldRole.getRoleValue();
318     updateRole(copy, oldRoleValue);
319   }
320 
321   public RoleResult setRoles(RoleList roleList)
322     throws IllegalArgumentException, RelationServiceNotRegisteredException,
323            RelationTypeNotFoundException, RelationNotFoundException
324   {
325     if (roleList == null)
326       throw new IllegalArgumentException("null role list");
327     RoleList copy = new RoleList(roleList);
328     checkRegistered();
329     RoleResult result = RoleValidator.checkRoles(relationService, server,
330                                                  relationTypeName, copy, true);
331     synchronized (result.getRoles())
332     {
333       Iterator iterator = result.getRoles().iterator();
334       while (iterator.hasNext())
335       {
336         Role role = (Role) iterator.next();
337         Role oldRole = (Role) roles.get(role.getRoleName());
338         ArrayList oldRoleValue = (ArrayList) oldRole.getRoleValue();
339         updateRole(role, oldRoleValue);
340       }
341     }
342     return result;
343   }
344 
345   // RelationSupport implementation --------------------------------
346 
347   public Boolean isInRelationService()
348   {
349     return registered;
350   }
351 
352   public void setRelationServiceManagementFlag(Boolean value)
353   {
354     synchronized (registered)
355     {
356       registered = new Boolean(value.booleanValue());
357     }
358   }
359 
360   // MBeanRegistration implementation ------------------------------
361 
362   public ObjectName preRegister(MBeanServer server, ObjectName objectName)
363     throws Exception
364   {
365     this.server = server;
366     return objectName;
367   }
368 
369   public void postRegister(Boolean registered)
370   {
371   }
372 
373   public void preDeregister()
374     throws Exception
375   {
376   }
377 
378   public void postDeregister()
379   {
380     server = null;
381   }
382 
383   // Private ----------------------------------------------------------
384 
385   /**
386    * Constructor support.<p>
387    *
388    * See the constructors for more information
389    *
390    * @param relationId the relation Id
391    * @param relationService the object name of the relation service
392    * @param mbeanServer the object name of the relation service
393    * @param relationTypeName the name of the relation type
394    * @param roleList the roles in this relation
395    * @exception IllegalArgumentException for null values.
396    * @exception InvalidRoleValueException when two roles have the same name.
397    */
398   private void init(String relationId, ObjectName relationService,
399                     MBeanServer mbeanServer, String relationTypeName, 
400                     RoleList roleList)
401     throws IllegalArgumentException, InvalidRoleValueException
402   {
403     // Validation
404     if (relationId == null)
405       throw new IllegalArgumentException("null relation id");
406     if (relationService == null)
407       throw new IllegalArgumentException("null relation service");
408     if (relationTypeName == null)
409       throw new IllegalArgumentException("null relation type name");
410 
411     // Easy parameters
412     this.relationId = relationId;
413     this.relationTypeName = relationTypeName;
414     this.relationService = relationService;
415     if (mbeanServer != null)
416       server = mbeanServer;
417     registered = new Boolean(false);
418 
419     // Set up a hash map for the roles for quicker access
420     if (roleList == null)
421       roles = new HashMap();
422     else
423     {
424       Object[] roleArray = roleList.toArray();
425       roles = new HashMap(roleArray.length);
426       for (int i = 0; i < roleArray.length; i++)
427       {
428         Role role = (Role) roleArray[i];
429         if (roles.containsKey(role.getRoleName()))
430           throw new IllegalArgumentException("duplicate role name");
431         roles.put(role.getRoleName(), role);
432       }
433     }
434   }
435 
436   /**
437    * Check that we are registered with the relation service
438    *
439    * @exception RelationNotFoundException when the relation
440    *            is not registered with the relation service.
441    */
442   private void checkRegistered()
443      throws RelationNotFoundException
444   {
445     if (isInRelationService().booleanValue() == false)
446       throw new RelationNotFoundException("not registered with relation service");
447     // What is the purpose of this flag? Why not invoke hasRelation?
448   }
449 
450   /**
451    * Check a role is readable
452    *
453    * @param role the role to check
454    * @return zero for success a value from RoleStatus otherwise.
455    * @exception RelationServiceNotRegisteredException when the relation
456    *            is not registered with an MBeanServer.
457    */
458   private int checkRoleReadable(Role role)
459     throws RelationServiceNotRegisteredException
460   {
461     checkServiceProxy();
462     try
463     {
464       return serviceProxy.checkRoleReading(role.getRoleName(), 
465                relationTypeName).intValue();
466     }
467     // RelationTypeNotFound has to be a runtime exception because
468     // the spec doesn't allow for this exception
469     catch (RelationTypeNotFoundException e)
470     {
471       throw new RuntimeException(e.toString());
472     }
473   }
474 
475   /**
476    * Check a role is writable
477    *
478    * @param role the role to check
479    * @param initFlag don't check the writeablitiy when this flag is true
480    * @return zero for success a value from RoleStatus otherwise.
481    * @exception RelationServiceNotRegisteredException when the relation
482    *            is not registered with an MBeanServer.
483    * @exception RelationTypeNotFoundException when the relation type
484    *            is not registered with the relation service
485    */
486   private int checkRoleWritable(Role role, boolean initFlag)
487     throws RelationServiceNotRegisteredException, RelationTypeNotFoundException
488   {
489     checkServiceProxy();
490     try
491     {
492       return serviceProxy.checkRoleWriting(role, relationTypeName, 
493                new Boolean(initFlag)).intValue();
494     }
495     // RelationTypeNotFound has to be a runtime exception because
496     // the spec doesn't allow for this exception
497     catch (RelationTypeNotFoundException e)
498     {
499       throw new RuntimeException(e.toString());
500     }
501   }
502 
503   /**
504    * Update the role
505    *
506    * @param role the role to set
507    * @param oldRoleVale the old role value
508    */
509   private void updateRole(Role role, ArrayList oldRoleValue)
510   {
511     roles.put(role.getRoleName(), role);
512     try
513     {
514       checkServiceProxy();
515       serviceProxy.updateRoleMap(relationId, role, oldRoleValue);
516       serviceProxy.sendRoleUpdateNotification(relationId, role, oldRoleValue);
517     }
518     catch (Exception e)
519     {
520         throw new RuntimeException(e.toString());
521     }
522   }
523 
524   /**
525    * Validate the role is found
526    *
527    * @param roleName the role name to validate
528    * @return the found role
529    * @exception RoleNotFoundException when the role does not exist
530    */
531   private Role validateRoleFound(String roleName)
532     throws RoleNotFoundException
533   {
534     Role result = (Role) roles.get(roleName);
535     if (result == null)
536       throw new RoleNotFoundException(roleName);
537     return result;
538   }
539 
540   /**
541    * Validate the role is readable, i.e. it is found and readable
542    *
543    * @param roleName the role name to validate
544    * @exception RoleNotFoundException when the role is not readable
545    * @exception RelationServiceNotRegisteredException when the relation
546    *            is not registered with an MBeanServer.
547    */
548   private void validateRoleReadable(String roleName)
549     throws RoleNotFoundException, RelationServiceNotRegisteredException
550   {
551     int status = 0;
552     checkServiceProxy();
553     try
554     {
555       status = serviceProxy.checkRoleReading(roleName, 
556                                              relationTypeName).intValue();
557     }
558     // RelationTypeNotFound has to be a runtime exception because
559     // the spec doesn't allow for this exception
560     catch (RelationTypeNotFoundException e)
561     {
562       throw new RuntimeException(e.toString());
563     }
564 
565     if (status == 3)
566       throw new RoleNotFoundException(roleName);
567     if (status == 6)
568       throw new RoleNotFoundException(roleName + " is not readable");
569   }
570 
571   /**
572    * Validate the role is writable, i.e. it is found and readable
573    *
574    * @param roleName the role name to validate
575    * @param initFlag don't check the writeability when this flag is true
576    * @return the found role
577    * @exception RoleNotFoundException when the role is not writable
578    * @exception RelationServiceNotRegisteredException when the relation
579    *            is not registered with an MBeanServer.
580    * @exception RelationTypeNotFoundException when the relation type
581    *            is not registered with the relation service
582    */
583   private Role validateRoleWritable(String roleName, boolean initFlag)
584     throws RoleNotFoundException, RelationServiceNotRegisteredException,
585            RelationTypeNotFoundException
586   {
587     Role result = validateRoleFound(roleName);
588     if (checkRoleWritable(result, initFlag) != 0)
589       throw new RoleNotFoundException("role not writable");
590     return result;
591   }
592 
593   /**
594    * Check the relation service proxy has been constructed.
595    *
596    * @exception RelationServiceNotRegisteredException when the relation
597    *            service has not been registered with the MBeanServer
598    */
599   private void checkServiceProxy()
600     throws RelationServiceNotRegisteredException
601   {
602     if (serviceProxy == null)
603     {
604       try
605       {
606           serviceProxy = (RelationServiceMBean) MBeanProxy.get(
607                         RelationServiceMBean.class, relationService, server);
608       }
609       catch (MBeanProxyCreationException e)
610       {
611         throw new RelationServiceNotRegisteredException(e.toString());
612       }
613     }
614   }
615 }