Coverage Report - org.codehaus.plexus.DefaultComponentRegistry
 
Classes in this File Line Coverage Branch Coverage Complexity
DefaultComponentRegistry
74 %
139/187
62 %
49/78
4,036
DefaultComponentRegistry$1
83 %
5/6
75 %
3/4
4,036
DefaultComponentRegistry$Key
66 %
20/30
37 %
12/32
4,036
 
 1  
 package org.codehaus.plexus;
 2  
 
 3  
 import static org.codehaus.plexus.component.CastUtils.isAssignableFrom;
 4  
 
 5  
 import java.util.ArrayList;
 6  
 import java.util.Collections;
 7  
 import java.util.Comparator;
 8  
 import java.util.IdentityHashMap;
 9  
 import java.util.Iterator;
 10  
 import java.util.LinkedHashMap;
 11  
 import java.util.List;
 12  
 import java.util.Map;
 13  
 import java.util.Set;
 14  
 import java.util.TreeMap;
 15  
 import java.util.Map.Entry;
 16  
 
 17  
 import org.codehaus.plexus.classworlds.realm.ClassRealm;
 18  
 import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException;
 19  
 import org.codehaus.plexus.component.factory.ComponentInstantiationException;
 20  
 import org.codehaus.plexus.component.manager.ComponentManager;
 21  
 import org.codehaus.plexus.component.manager.ComponentManagerFactory;
 22  
 import org.codehaus.plexus.component.repository.ComponentDescriptor;
 23  
 import org.codehaus.plexus.component.repository.ComponentRepository;
 24  
 import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException;
 25  
 import org.codehaus.plexus.component.repository.exception.ComponentLookupException;
 26  
 import org.codehaus.plexus.lifecycle.LifecycleHandler;
 27  
 import org.codehaus.plexus.lifecycle.LifecycleHandlerManager;
 28  
 import org.codehaus.plexus.lifecycle.UndefinedLifecycleHandlerException;
 29  
 import org.codehaus.plexus.logging.Logger;
 30  
 import org.codehaus.plexus.util.StringUtils;
 31  
 
 32  
 public class DefaultComponentRegistry implements ComponentRegistry
 33  
 {
 34  
     private static final String DEFAULT_INSTANTIATION_STRATEGY = "singleton";
 35  
 
 36  
     private final MutablePlexusContainer container;
 37  
     private final ComponentRepository repository;
 38  
     private final LifecycleHandlerManager lifecycleHandlerManager;
 39  
     private final Logger logger;
 40  
 
 41  
     private boolean disposingComponents; 
 42  
 
 43  61
     private final Map<String, ComponentManagerFactory> componentManagerFactories =
 44  
         Collections.synchronizedMap( new TreeMap<String, ComponentManagerFactory>() );
 45  
 
 46  61
     private final Map<Key, ComponentManager<?>> componentManagers = new TreeMap<Key, ComponentManager<?>>();
 47  61
     private final Map<Object, ComponentManager<?>> componentManagersByComponent = new IdentityHashMap<Object, ComponentManager<?>>();
 48  
 
 49  61
     private final Map<Key, Object> unmanagedComponents = new TreeMap<Key, Object>();
 50  
 
 51  
     public DefaultComponentRegistry( MutablePlexusContainer container,
 52  
                                      ComponentRepository repository,
 53  
                                      LifecycleHandlerManager lifecycleHandlerManager )
 54  61
     {
 55  61
         this.container = container;
 56  61
         this.repository = repository;
 57  61
         this.lifecycleHandlerManager = lifecycleHandlerManager;
 58  61
         logger = container.getLogger();
 59  61
     }
 60  
 
 61  
     public void dispose()
 62  
     {
 63  
         List<ComponentManager<?>> managers;
 64  58
         synchronized ( this )
 65  
         {
 66  58
             managers = new ArrayList<ComponentManager<?>>( componentManagers.values() );
 67  58
             componentManagers.clear();
 68  58
             componentManagersByComponent.clear();
 69  58
             unmanagedComponents.clear();
 70  
 
 71  58
             disposingComponents = true;
 72  58
         }
 73  
 
 74  
         // reverse sort the managers by startId
 75  58
         Collections.sort( managers, new Comparator<ComponentManager<?>>() {
 76  
             public int compare( ComponentManager<?> left, ComponentManager<?> right )
 77  
             {
 78  484
                 if (left.getStartId() < right.getStartId() )
 79  
                 {
 80  207
                     return 1;
 81  
                 }
 82  277
                 else if (left.getStartId() == right.getStartId() )
 83  
                 {
 84  0
                     return 0;
 85  
                 }
 86  
                 else
 87  
                 {
 88  277
                     return -1;
 89  
                 }
 90  
             }
 91  
         });
 92  
 
 93  
         // Call dispose callback outside of synchronized lock to avoid deadlocks
 94  
         try
 95  
         {
 96  58
             for ( ComponentManager<?> componentManager : managers )
 97  
             {
 98  
                 try
 99  
                 {
 100  208
                     componentManager.dispose();
 101  
                 }
 102  0
                 catch ( Exception e )
 103  
                 {
 104  
                     // todo dain use a monitor instead of a logger
 105  0
                     logger.error( "Error while disposing component manager. Continuing with the rest", e );
 106  208
                 }
 107  208
             }
 108  
         }
 109  
         finally 
 110  
         {
 111  58
             synchronized ( this )
 112  
             {
 113  58
                 disposingComponents = false;
 114  58
             }
 115  58
         }
 116  58
     }
 117  
 
 118  
     public void registerComponentManagerFactory( ComponentManagerFactory componentManagerFactory )
 119  
     {
 120  122
         componentManagerFactories.put( componentManagerFactory.getId(), componentManagerFactory );
 121  122
     }
 122  
 
 123  
     public void addComponentDescriptor( ComponentDescriptor<?> componentDescriptor ) 
 124  
         throws CycleDetectedInComponentGraphException
 125  
     {
 126  1174
         repository.addComponentDescriptor( componentDescriptor );
 127  1173
     }
 128  
 
 129  
     @SuppressWarnings("unchecked")
 130  
     public synchronized <T> void addComponent( T component, String role, String roleHint )
 131  
     {
 132  2
         ComponentDescriptor descriptor = new ComponentDescriptor(component.getClass(), null );
 133  2
         descriptor.setRole( role );
 134  2
         descriptor.setRoleHint( roleHint );
 135  
 
 136  2
         Key key = new Key( descriptor.getRealm(), role, roleHint );
 137  
 
 138  2
         unmanagedComponents.put( key, component );
 139  2
     }
 140  
 
 141  
     public <T> ComponentDescriptor<T> getComponentDescriptor( Class<T> type, String role, String roleHint )
 142  
     {
 143  1307
         return repository.getComponentDescriptor( type, role, roleHint );
 144  
     }
 145  
 
 146  
     @Deprecated
 147  
     public ComponentDescriptor<?> getComponentDescriptor( String role, String roleHint, ClassRealm realm )
 148  
     {
 149  0
         return repository.getComponentDescriptor( role, roleHint, realm );
 150  
     }
 151  
 
 152  
     public <T> Map<String, ComponentDescriptor<T>> getComponentDescriptorMap( Class<T> type, String role )
 153  
     {
 154  254302
         return repository.getComponentDescriptorMap( type, role );
 155  
     }
 156  
 
 157  
     public <T> List<ComponentDescriptor<T>> getComponentDescriptorList( Class<T> type, String role )
 158  
     {
 159  62
         return repository.getComponentDescriptorList( type, role );
 160  
     }
 161  
 
 162  
     public <T> T lookup( Class<T> type, String role, String roleHint ) throws ComponentLookupException
 163  
     {
 164  
         // verify arguments
 165  1185
         if ( type == null )
 166  
         {
 167  0
             throw new NullPointerException( "type is null" );
 168  
         }
 169  1185
         if ( role == null )
 170  
         {
 171  0
             throw new NullPointerException( "role is null" );
 172  
         }
 173  1185
         if ( roleHint == null )
 174  
         {
 175  0
             roleHint = "";
 176  
         }
 177  
 
 178  1185
         return getComponent( type, role, roleHint, null );
 179  
     }
 180  
 
 181  
     public <T> T lookup( ComponentDescriptor<T> componentDescriptor )
 182  
         throws ComponentLookupException
 183  
     {
 184  125272
         return getComponent( componentDescriptor.getRoleClass(), componentDescriptor.getRole(),
 185  
                              componentDescriptor.getRoleHint(), componentDescriptor );
 186  
     }
 187  
 
 188  
     public <T> Map<String, T> lookupMap( Class<T> type, String role, List<String> roleHints )
 189  
         throws ComponentLookupException
 190  
     {
 191  
         // verify arguments
 192  3
         if ( type == null )
 193  
         {
 194  0
             throw new NullPointerException( "type is null" );
 195  
         }
 196  3
         if ( role == null )
 197  
         {
 198  0
             throw new NullPointerException( "role is null" );
 199  
         }
 200  
 
 201  
         // if no hints provided, get all valid hints for this role
 202  3
         Map<String, T> components = new LinkedHashMap<String, T>();
 203  3
         if ( roleHints == null )
 204  
         {
 205  3
             Map<String, ComponentDescriptor<T>> componentDescriptors = getComponentDescriptorMap( type, role );
 206  3
             for ( Entry<String, ComponentDescriptor<T>> entry : componentDescriptors.entrySet() )
 207  
             {
 208  6
                 String roleHint = entry.getKey();
 209  6
                 ComponentDescriptor<T> componentDescriptor = entry.getValue();
 210  
                 // todo dain catch the exception... it isn't the callers problem when one component in a collection fails
 211  6
                 T component = getComponent( type, role, roleHint, componentDescriptor );
 212  6
                 components.put( roleHint, component );
 213  6
             }
 214  3
         }
 215  
         else
 216  
         {
 217  0
             for ( String roleHint : roleHints )
 218  
             {
 219  
                 // todo dain catch the exception... it isn't the callers problem when one component in a collection fails
 220  0
                 T component = getComponent( type, role, roleHint, null );
 221  0
                 components.put( roleHint, component );
 222  0
             }
 223  
         }
 224  
 
 225  3
         return components;
 226  
     }
 227  
 
 228  
     public <T> List<T> lookupList( Class<T> type, String role, List<String> roleHints ) throws ComponentLookupException
 229  
     {
 230  
         // verify arguments
 231  62
         if ( type == null )
 232  
         {
 233  0
             throw new NullPointerException( "type is null" );
 234  
         }
 235  62
         if ( role == null )
 236  
         {
 237  0
             throw new NullPointerException( "role is null" );
 238  
         }
 239  
 
 240  
         // if no hints provided, get all valid hints for this role
 241  62
         List<T> components = new ArrayList<T>();
 242  62
         if ( roleHints == null )
 243  
         {
 244  62
             List<ComponentDescriptor<T>> componentDescriptors = getComponentDescriptorList( type, role );
 245  62
             for ( ComponentDescriptor<T> componentDescriptor : componentDescriptors )
 246  
             {
 247  
                 // todo dain catch the exception... it isn't the callers problem when one component in a collection fails
 248  6
                 T component = getComponent( type, role, componentDescriptor.getRoleHint(), componentDescriptor );
 249  6
                 components.add( component );
 250  6
             }
 251  62
         }
 252  
         else
 253  
         {
 254  0
             for ( String roleHint : roleHints )
 255  
             {
 256  
                 // todo dain catch the exception... it isn't the callers problem when one component in a collection fails
 257  0
                 T component = getComponent( type, role, roleHint, null );
 258  0
                 components.add( component );
 259  0
             }
 260  
         }
 261  
 
 262  62
         return components;
 263  
     }
 264  
 
 265  
     public void release( Object component )
 266  
         throws ComponentLifecycleException
 267  
     {
 268  9
         if ( component == null )
 269  
         {
 270  0
             return;
 271  
         }
 272  
 
 273  
         // get the component manager
 274  
         ComponentManager<?> componentManager;
 275  9
         synchronized ( this )
 276  
         {
 277  9
             componentManager = componentManagersByComponent.get( component );
 278  9
             if ( componentManager == null )
 279  
             {
 280  
                 // This needs to be tracked down but the user doesn't need to see this
 281  
                 // during the maven bootstrap this logger is null.
 282  
                 //logger.debug( "Component manager not found for returned component. Ignored. component=" + component );
 283  0
                 return;
 284  
             }
 285  9
         }
 286  
 
 287  
         // release the component from the manager
 288  9
         componentManager.release( component );
 289  
 
 290  
         // only drop the reference to this component if there are no other uses of the component
 291  
         // multiple uses of a component is common with singleton beans
 292  9
         if ( componentManager.getConnections() <= 0 )
 293  
         {
 294  0
             synchronized ( this )
 295  
             {
 296  0
                 componentManagersByComponent.remove( component );
 297  0
             }
 298  
         }
 299  9
     }
 300  
 
 301  
     public void removeComponentRealm( ClassRealm classRealm ) throws PlexusContainerException
 302  
     {
 303  0
         repository.removeComponentRealm( classRealm );
 304  
         
 305  0
         List<ComponentManager<?>> dispose = new ArrayList<ComponentManager<?>>();
 306  
         try
 307  
         {
 308  0
             synchronized ( this )
 309  
             {
 310  0
                 for ( Iterator<Entry<Key, ComponentManager<?>>> it = componentManagers.entrySet().iterator(); it.hasNext(); )
 311  
                 {
 312  0
                     Entry<Key, ComponentManager<?>> entry = it.next();
 313  0
                     Key key = entry.getKey();
 314  
 
 315  0
                     ComponentManager<?> componentManager = entry.getValue();
 316  
 
 317  0
                     if ( key.realm.equals( classRealm ) )
 318  
                     {
 319  0
                         dispose.add( componentManager );
 320  0
                         it.remove();
 321  
                     }
 322  
                     else
 323  
                     {
 324  0
                         componentManager.dissociateComponentRealm( classRealm );
 325  
                     }
 326  0
                 }
 327  0
             }
 328  
 
 329  
             // Call dispose callback outside of synchronized lock to avoid deadlocks
 330  0
             for ( ComponentManager<?> componentManager : dispose )
 331  
             {
 332  0
                 componentManager.dispose();
 333  0
             }
 334  
         }
 335  0
         catch ( ComponentLifecycleException e )
 336  
         {
 337  0
             throw new PlexusContainerException( "Failed to dissociate component realm: " + classRealm.getId(), e );
 338  0
         }
 339  0
     }
 340  
 
 341  
     private <T> T getComponent( Class<T> type, String role, String roleHint, ComponentDescriptor<T> descriptor )
 342  
         throws ComponentLookupException
 343  
     {
 344  
         // lookup for unmanaged components first
 345  
 
 346  126373
         T component = this.<T>getUnmanagedComponent( role, roleHint ); // weird syntax due to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6302954
 347  
 
 348  127826
         if ( component != null )
 349  
         {
 350  2
             return component;
 351  
         }
 352  
 
 353  127824
         ComponentManager<T> componentManager = getComponentManager( type, role, roleHint, descriptor );
 354  
 
 355  
         // Get instance from manager... may result in creation
 356  
         try
 357  
         {
 358  127796
             component = componentManager.getComponent();
 359  127792
             synchronized ( this )
 360  
             {
 361  127793
                 componentManagersByComponent.put( component, componentManager );
 362  127793
             }
 363  127793
             return component;
 364  
         }
 365  1
         catch ( ComponentInstantiationException e )
 366  
         {
 367  1
             throw new ComponentLookupException(
 368  
                 "Unable to lookup component '" + componentManager.getRole() + "', it could not be created.",
 369  
                 componentManager.getRole(), componentManager.getRoleHint(), componentManager.getRealm(), e );
 370  
         }
 371  2
         catch ( ComponentLifecycleException e )
 372  
         {
 373  2
             throw new ComponentLookupException(
 374  
                 "Unable to lookup component '" + componentManager.getRole() + "', it could not be started.",
 375  
                 componentManager.getRole(), componentManager.getRoleHint(), componentManager.getRealm(), e );
 376  
         }
 377  
     }
 378  
 
 379  
     @SuppressWarnings("unchecked")
 380  
     private synchronized <T> T getUnmanagedComponent( String role, String roleHint )
 381  
     {
 382  127826
         Set<ClassRealm> realms = getSearchRealms( true );
 383  
 
 384  127826
         if ( realms != null )
 385  
         {
 386  
             // ignore unmanaged components, they are not associated with realms 
 387  
             // but lookup realm is provided via thread context classloader 
 388  126672
             return null;
 389  
         }
 390  
         else
 391  
         {
 392  1154
             if ( StringUtils.isEmpty( roleHint ) )
 393  
             {
 394  1110
                 roleHint = PlexusConstants.PLEXUS_DEFAULT_HINT;
 395  
             }
 396  
 
 397  1154
             return (T) unmanagedComponents.get( new Key( null, role, roleHint ) );
 398  
         }
 399  
     }
 400  
 
 401  
     private synchronized <T> ComponentManager<T> getComponentManager( Class<T> type, String role, String roleHint, ComponentDescriptor<T> descriptor )
 402  
         throws ComponentLookupException
 403  
     {
 404  127824
         if ( disposingComponents )
 405  
         {
 406  1
             throw new ComponentLookupException("ComponentRegistry is not active",
 407  
                 role,
 408  
                 roleHint );
 409  
         }
 410  
 
 411  127823
         if ( descriptor == null )
 412  
         {
 413  1182
             descriptor = getComponentDescriptor( type, role, roleHint );
 414  
         }
 415  
 
 416  127823
         ComponentManager<T> componentManager = null;
 417  
 
 418  127823
         if ( descriptor != null )
 419  
         {
 420  127796
             componentManager = getComponentManager( type, role, descriptor.getRoleHint(), descriptor.getRealm() );
 421  
         }
 422  
         else
 423  
         {
 424  27
             componentManager = getComponentManager( type, role, roleHint );
 425  
         }
 426  
 
 427  127823
         if ( componentManager == null )
 428  
         {
 429  
             // we need to create a component manager, but first we must have a descriptor
 430  237
             if ( descriptor == null )
 431  
             {
 432  27
                 descriptor = getComponentDescriptor( type, role, roleHint );
 433  27
                 if ( descriptor == null )
 434  
                 {
 435  27
                     throw new ComponentLookupException(
 436  
                         "Component descriptor cannot be found in the component repository",
 437  
                         role,
 438  
                         roleHint );
 439  
                 }
 440  
                 // search also into descriptor realm as the key of a created component is per descriptor realm
 441  0
                 componentManager = getComponentManager( type, role, descriptor.getRoleHint(), descriptor.getRealm() );
 442  
             }
 443  
 
 444  210
             if ( componentManager == null )
 445  
             {
 446  210
                 componentManager = createComponentManager( descriptor, role, descriptor.getRoleHint() );
 447  
             }
 448  
         }
 449  
 
 450  127796
         return componentManager;
 451  
     }
 452  
 
 453  
     @SuppressWarnings( "unchecked" )
 454  
     private <T> ComponentManager<T> getComponentManager( Class<T> type, String role, String roleHint )
 455  
     {
 456  27
         Set<ClassRealm> realms = getSearchRealms( false );
 457  
 
 458  
         // return the component in the first realm
 459  27
         for ( ClassRealm realm : realms )
 460  
         {
 461  27
             ComponentManager<?> manager = componentManagers.get( new Key( realm, role, roleHint ) );
 462  27
             if ( manager != null && isAssignableFrom( type, manager.getType() ) )
 463  
             {
 464  0
                 return (ComponentManager<T>) manager;
 465  
             }
 466  27
         }
 467  27
         return null;
 468  
     }
 469  
 
 470  
     @SuppressWarnings( "unchecked" )
 471  
     private <T> ComponentManager<T> getComponentManager( Class<T> type, String role, String roleHint, ClassRealm realm )
 472  
     {
 473  127796
         ComponentManager<?> manager = componentManagers.get( new Key( realm, role, roleHint ) );
 474  127796
         if ( manager != null && isAssignableFrom( type, manager.getType() ) )
 475  
         {
 476  127586
             return (ComponentManager<T>) manager;
 477  
         }
 478  210
         return null;
 479  
     }
 480  
 
 481  
     @SuppressWarnings( "unchecked" )
 482  
     private Set<ClassRealm> getSearchRealms( boolean specifiedOnly )
 483  
     {
 484  
         // determine realms to search
 485  127853
         Set<ClassRealm> realms = ClassRealmUtil.getContextRealms( container.getClassWorld() );
 486  
 
 487  127853
         if ( realms.isEmpty() )
 488  
         {
 489  1180
             if ( specifiedOnly )
 490  
             {
 491  1154
                 return null;
 492  
             }
 493  
 
 494  26
             realms.addAll( container.getClassWorld().getRealms() );
 495  
         }
 496  
 
 497  126699
         return realms;
 498  
     }
 499  
 
 500  
     private <T> ComponentManager<T> createComponentManager( ComponentDescriptor<T> descriptor,
 501  
                                                             String role,
 502  
                                                             String roleHint )
 503  
         throws ComponentLookupException
 504  
     {
 505  
         // Get the ComponentManagerFactory
 506  210
         String instantiationStrategy = descriptor.getInstantiationStrategy();
 507  210
         if ( instantiationStrategy == null )
 508  
         {
 509  194
             instantiationStrategy = DEFAULT_INSTANTIATION_STRATEGY;
 510  
         }
 511  210
         ComponentManagerFactory componentManagerFactory = componentManagerFactories.get( instantiationStrategy );
 512  210
         if ( componentManagerFactory == null )
 513  
         {
 514  0
             throw new ComponentLookupException( "Unsupported instantiation strategy: " + instantiationStrategy,
 515  
                 role,
 516  
                 roleHint,
 517  
                 descriptor.getRealm() );
 518  
         }
 519  
 
 520  
         // Get the LifecycleHandler
 521  
         LifecycleHandler lifecycleHandler;
 522  
         try
 523  
         {
 524  210
             lifecycleHandler = lifecycleHandlerManager.getLifecycleHandler( descriptor.getLifecycleHandler() );
 525  
         }
 526  0
         catch ( UndefinedLifecycleHandlerException e )
 527  
         {
 528  0
             throw new ComponentLookupException( "Undefined lifecycle handler: " + descriptor.getLifecycleHandler(),
 529  
                 role,
 530  
                 roleHint,
 531  
                 descriptor.getRealm() );
 532  210
         }
 533  
 
 534  
         // Create the ComponentManager
 535  210
         ComponentManager<T> componentManager = componentManagerFactory.createComponentManager( container,
 536  
             lifecycleHandler,
 537  
             descriptor,
 538  
             role,
 539  
             roleHint );
 540  
 
 541  
         // Add componentManager to indexes
 542  210
         Key key = new Key( descriptor.getRealm(), role, roleHint );
 543  210
         componentManagers.put( key, componentManager );
 544  
 
 545  210
         return componentManager;
 546  
     }
 547  
 
 548  801199
     private static class Key implements Comparable<Key>
 549  
     {
 550  
         private final ClassRealm realm;
 551  
         private final String role;
 552  
         private final String roleHint;
 553  
         private final int hashCode;
 554  
 
 555  
         private Key( ClassRealm realm, String role, String roleHint )
 556  129189
         {
 557  129189
             this.realm = realm;
 558  
 
 559  129189
             if ( role == null )
 560  
             {
 561  0
                 role = "null";
 562  
             }
 563  129189
             this.role = role;
 564  
 
 565  129189
             if ( roleHint == null )
 566  
             {
 567  0
                 roleHint = "null";
 568  
             }
 569  129189
             this.roleHint = roleHint;
 570  
 
 571  
             int hashCode;
 572  129189
             hashCode = ( realm != null ? realm.hashCode() : 0 );
 573  129189
             hashCode = 31 * hashCode + role.hashCode();
 574  129189
             hashCode = 31 * hashCode + roleHint.hashCode();
 575  129189
             this.hashCode = hashCode;
 576  129189
         }
 577  
 
 578  
         public boolean equals( Object o )
 579  
         {
 580  0
             if ( this == o )
 581  
             {
 582  0
                 return true;
 583  
             }
 584  0
             if ( o == null || getClass() != o.getClass() )
 585  
             {
 586  0
                 return false;
 587  
             }
 588  
 
 589  0
             Key key = (Key) o;
 590  
 
 591  0
             return !( realm != null ? !realm.equals( key.realm ) : key.realm != null ) &&
 592  
                 role.equals( key.role ) &&
 593  
                 roleHint.equals( key.roleHint );
 594  
 
 595  
         }
 596  
 
 597  
         public int hashCode()
 598  
         {
 599  0
             return hashCode;
 600  
         }
 601  
 
 602  
         public String toString()
 603  
         {
 604  0
             return realm + "/" + role + "/" + roleHint;
 605  
         }
 606  
 
 607  
         public int compareTo( Key o )
 608  
         {
 609  
             int value;
 610  672010
             if ( realm != null )
 611  
             {
 612  672006
                 value = o.realm == null? -1 : realm.getId().compareTo( o.realm.getId() );
 613  
             }
 614  
             else
 615  
             {
 616  4
                 value = o.realm == null ? 0 : 1;
 617  
             }
 618  
 
 619  672010
             if ( value == 0 )
 620  
             {
 621  127947
                 value = role.compareTo( o.role );
 622  127947
                 if ( value == 0 )
 623  
                 {
 624  127722
                     value = roleHint.compareTo( o.roleHint );
 625  
                 }
 626  
             }
 627  672010
             return value;
 628  
         }
 629  
     }
 630  
 }