KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > security > plugins > JaasSecurityManager


1 /*
2  * JBoss, Home of Professional Open Source
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.security.plugins;
8
9 import java.lang.reflect.Method JavaDoc;
10 import java.lang.reflect.UndeclaredThrowableException JavaDoc;
11 import java.security.Principal JavaDoc;
12 import java.security.acl.Group JavaDoc;
13 import java.util.Arrays JavaDoc;
14 import java.util.Enumeration JavaDoc;
15 import java.util.HashSet JavaDoc;
16 import java.util.Iterator JavaDoc;
17 import java.util.Set JavaDoc;
18 import javax.security.auth.Subject JavaDoc;
19 import javax.security.auth.callback.CallbackHandler JavaDoc;
20 import javax.security.auth.login.LoginContext JavaDoc;
21 import javax.security.auth.login.LoginException JavaDoc;
22
23 import org.jboss.logging.Logger;
24 import org.jboss.security.AnybodyPrincipal;
25 import org.jboss.security.NobodyPrincipal;
26 import org.jboss.security.RealmMapping;
27 import org.jboss.security.SecurityAssociation;
28 import org.jboss.security.SubjectSecurityManager;
29 import org.jboss.security.auth.callback.SecurityAssociationHandler;
30 import org.jboss.system.ServiceMBeanSupport;
31 import org.jboss.util.CachePolicy;
32 import org.jboss.util.TimedCachePolicy;
33
34 /** The JaasSecurityManager is responsible both for authenticating credentials
35  associated with principals and for role mapping. This implementation relies
36  on the JAAS LoginContext/LoginModules associated with the security
37  domain name associated with the class for authentication,
38  and the context JAAS Subject object for role mapping.
39  
40  @see #isValid(Principal, Object, Subject)
41  @see #getPrincipal(Principal)
42  @see #doesUserHaveRole(Principal, Set)
43  
44  @author <a HREF="on@ibis.odessa.ua">Oleg Nitz</a>
45  @author Scott.Stark@jboss.org
46  @version $Revision: 1.41.2.5 $
47 */

48 public class JaasSecurityManager extends ServiceMBeanSupport
49    implements SubjectSecurityManager, RealmMapping
50 {
51    /** The authentication cache object.
52     */

53    public static class DomainInfo implements TimedCachePolicy.TimedEntry
54    {
55       private static Logger log = Logger.getLogger(DomainInfo.class);
56       private static boolean trace = log.isTraceEnabled();
57       private LoginContext JavaDoc loginCtx;
58       private Subject JavaDoc subject;
59       private Object JavaDoc credential;
60       private Principal JavaDoc callerPrincipal;
61       private long expirationTime;
62       /** Is there an active authentication in process */
63       private boolean needsDestroy;
64       /** The number of users sharing this DomainInfo */
65       private int activeUsers;
66
67       public DomainInfo(int lifetime)
68       {
69          expirationTime = 1000 * lifetime;
70       }
71
72       synchronized int acquire()
73       {
74          return activeUsers ++;
75       }
76       synchronized int release()
77       {
78          int users = activeUsers --;
79          if( needsDestroy == true && users == 0 )
80          {
81             if( trace )
82                log.trace("needsDestroy is true, doing logout");
83             logout();
84          }
85          return users;
86       }
87       synchronized void logout()
88       {
89          if( trace )
90             log.trace("logout, subject="+subject+", this="+this);
91          try
92          {
93             if( loginCtx != null )
94                loginCtx.logout();
95          }
96          catch(Throwable JavaDoc e)
97          {
98             if( trace )
99                log.trace("Cache entry logout failed", e);
100          }
101       }
102
103       public void init(long now)
104       {
105          expirationTime += now;
106       }
107       public boolean isCurrent(long now)
108       {
109          return expirationTime > now;
110       }
111       public boolean refresh()
112       {
113          return false;
114       }
115       /**
116        * This
117        */

118       public void destroy()
119       {
120          if( trace )
121          {
122             log.trace("destroy, subject="+subject+", this="+this
123                +", activeUsers="+activeUsers);
124          }
125
126          synchronized( this )
127          {
128             if( activeUsers == 0 )
129                logout();
130             else
131             {
132                if( trace )
133                   log.trace("destroy saw activeUsers="+activeUsers);
134                needsDestroy = true;
135             }
136          }
137       }
138       public Object JavaDoc getValue()
139       {
140          return this;
141       }
142       public String JavaDoc toString()
143       {
144          StringBuffer JavaDoc tmp = new StringBuffer JavaDoc(super.toString());
145          tmp.append('[');
146          tmp.append(SubjectActions.toString(subject));
147          tmp.append(",credential.class=");
148          if( credential != null )
149          {
150             Class JavaDoc c = credential.getClass();
151             tmp.append(c.getName());
152             tmp.append('@');
153             tmp.append(System.identityHashCode(c));
154          }
155          else
156          {
157             tmp.append("null");
158          }
159          tmp.append(",expirationTime=");
160          tmp.append(expirationTime);
161          tmp.append(']');
162
163          return tmp.toString();
164       }
165    }
166
167    /** The name of the domain this instance is securing. It is used as
168     the appName into the SecurityPolicy.
169     */

170    private String JavaDoc securityDomain;
171    /** A cache of DomainInfo objects keyd by Principal. This is now
172     always set externally by our security manager service.
173     */

174    private CachePolicy domainCache;
175    /** The JAAS callback handler to use in defaultLogin */
176    private CallbackHandler JavaDoc handler;
177    /** The setSecurityInfo(Principal, Object) method of the handler obj */
178    private Method JavaDoc setSecurityInfo;
179
180    /** The log4j category for the security manager domain
181     */

182    protected Logger log;
183    protected boolean trace;
184
185    /** Creates a default JaasSecurityManager for with a securityDomain
186     name of 'other'.
187     */

188    public JaasSecurityManager()
189    {
190       this("other", new SecurityAssociationHandler());
191    }
192    /** Creates a JaasSecurityManager for with a securityDomain
193     name of that given by the 'securityDomain' argument.
194     @param securityDomain the name of the security domain
195     @param handler the JAAS callback handler instance to use
196     @exception UndeclaredThrowableException thrown if handler does not
197       implement a setSecurityInfo(Princpal, Object) method
198     */

199    public JaasSecurityManager(String JavaDoc securityDomain, CallbackHandler JavaDoc handler)
200    {
201       this.securityDomain = securityDomain;
202       this.handler = handler;
203       String JavaDoc categoryName = getClass().getName()+'.'+securityDomain;
204       this.log = Logger.getLogger(categoryName);
205       this.trace = log.isTraceEnabled();
206
207       // Get the setSecurityInfo(Principal principal, Object credential) method
208
Class JavaDoc[] sig = {Principal JavaDoc.class, Object JavaDoc.class};
209       try
210       {
211          setSecurityInfo = handler.getClass().getMethod("setSecurityInfo", sig);
212       }
213       catch (Exception JavaDoc e)
214       {
215          String JavaDoc msg = "Failed to find setSecurityInfo(Princpal, Object) method in handler";
216          throw new UndeclaredThrowableException JavaDoc(e, msg);
217       }
218       log.debug("CallbackHandler: "+handler);
219    }
220
221    /** The domainCache is typically a shared object that is populated
222     by the login code(LoginModule, etc.) and read by this class in the
223     isValid() method.
224     @see #isValid(Principal, Object, Subject)
225     */

226    public void setCachePolicy(CachePolicy domainCache)
227    {
228       this.domainCache = domainCache;
229       log.debug("CachePolicy set to: "+domainCache);
230    }
231
232    /** Not really used anymore as the security manager service manages the
233     security domain authentication caches.
234     */

235    public void flushCache()
236    {
237       if( domainCache != null )
238          domainCache.flush();
239    }
240
241    /** Get the name of the security domain associated with this security mgr.
242     @return Name of the security manager security domain.
243     */

244    public String JavaDoc getSecurityDomain()
245    {
246       return securityDomain;
247    }
248
249    /** Get the currently authenticated Subject. This is a thread local
250     property shared across all JaasSecurityManager instances.
251     @return The Subject authenticated in the current thread if one
252     exists, null otherwise.
253     */

254    public Subject JavaDoc getActiveSubject()
255    {
256       /* This does not use SubjectActions.getActiveSubject since the caller
257          must have the correct permissions to access the
258          SecurityAssociation.getSubject method.
259       */

260       return SecurityAssociation.getSubject();
261    }
262
263    /** Validate that the given credential is correct for principal. This
264     returns the value from invoking isValid(principal, credential, null).
265     @param principal - the security domain principal attempting access
266     @param credential - the proof of identity offered by the principal
267     @return true if the principal was authenticated, false otherwise.
268     */

269    public boolean isValid(Principal JavaDoc principal, Object JavaDoc credential)
270    {
271       return isValid(principal, credential, null);
272    }
273
274    /** Validate that the given credential is correct for principal. This first
275     will check the current CachePolicy object if one exists to see if the
276     user's cached credentials match the given credential. If there is no
277     credential cache or the cache information is invalid or does not match,
278     the user is authenticated against the JAAS login modules configured for
279     the security domain.
280     @param principal - the security domain principal attempting access
281     @param credential the proof of identity offered by the principal
282     @param activeSubject - if not null, a Subject that will be populated with
283       the state of the authenticated Subject.
284     @return true if the principal was authenticated, false otherwise.
285     */

286    public boolean isValid(Principal JavaDoc principal, Object JavaDoc credential,
287       Subject JavaDoc activeSubject)
288    {
289       // Check the cache first
290
DomainInfo cacheInfo = getCacheInfo(principal, true);
291       if( trace )
292          log.trace("Begin isValid, principal:"+principal+", cache info: "+cacheInfo);
293
294       boolean isValid = false;
295       if( cacheInfo != null )
296       {
297          isValid = validateCache(cacheInfo, credential, activeSubject);
298          if( cacheInfo != null )
299             cacheInfo.release();
300       }
301       if( isValid == false )
302          isValid = authenticate(principal, credential, activeSubject);
303       if( trace )
304          log.trace("End isValid, "+isValid);
305       return isValid;
306    }
307
308    /** Map the argument principal from the deployment environment principal
309     to the developer environment. This is called by the EJB context
310     getCallerPrincipal() to return the Principal as described by
311     the EJB developer domain.
312     @return a Principal object that is valid in the deployment environment
313     if one exists. If no Subject exists or the Subject has no principals
314     then the argument principal is returned.
315     */

316    public Principal JavaDoc getPrincipal(Principal JavaDoc principal)
317    {
318       Principal JavaDoc result = principal;
319       // Get the CallerPrincipal group member
320
synchronized( domainCache )
321       {
322          DomainInfo info = getCacheInfo(principal, false);
323          if( trace )
324             log.trace("getPrincipal, cache info: "+info);
325          if( info != null )
326          {
327             result = info.callerPrincipal;
328             // If the mapping did not have a callerPrincipal just use principal
329
if( result == null )
330                result = principal;
331             info.release();
332          }
333       }
334
335       return result;
336    }
337
338    /** Does the current Subject have a role(a Principal) that equates to one
339     of the role names. This method obtains the Group named 'Roles' from
340     the principal set of the currently authenticated Subject as determined
341     by the SecurityAssociation.getSubject() method and then creates a
342     SimplePrincipal for each name in roleNames. If the role is a member of the
343     Roles group, then the user has the role. This requires that the caller
344     establish the correct SecurityAssociation subject prior to calling this
345     method. In the past this was done as a side-effect of an isValid() call,
346     but this is no longer the case.
347
348     @param principal - ignored. The current authenticated Subject determines
349     the active user and assigned user roles.
350     @param rolePrincipals - a Set of Principals for the roles to check.
351     
352     @see java.security.acl.Group;
353     @see Subject#getPrincipals()
354     */

355    public boolean doesUserHaveRole(Principal JavaDoc principal, Set JavaDoc rolePrincipals)
356    {
357       boolean hasRole = false;
358       // Check that the caller is authenticated to the current thread
359
Subject JavaDoc subject = SubjectActions.getActiveSubject();
360       if( subject != null )
361       {
362          // Check the caller's roles
363
if( trace )
364             log.trace("doesUserHaveRole(Set), subject: "+subject);
365
366          Group JavaDoc roles = getSubjectRoles(subject);
367          if( trace )
368             log.trace("roles="+roles);
369          if( roles != null )
370          {
371             Iterator JavaDoc iter = rolePrincipals.iterator();
372             while( hasRole == false && iter.hasNext() )
373             {
374                Principal JavaDoc role = (Principal JavaDoc) iter.next();
375                hasRole = doesRoleGroupHaveRole(role, roles);
376                if( trace )
377                   log.trace("hasRole("+role+")="+hasRole);
378             }
379          }
380          if( trace )
381             log.trace("hasRole="+hasRole);
382       }
383       return hasRole;
384    }
385
386    /** Does the current Subject have a role(a Principal) that equates to one
387     of the role names.
388
389     @see #doesUserHaveRole(Principal, Set)
390
391     @param principal - ignored. The current authenticated Subject determines
392     the active user and assigned user roles.
393     @param role - the application domain role that the principal is to be
394       validated against.
395     @return true if the active principal has the role, false otherwise.
396     */

397    public boolean doesUserHaveRole(Principal JavaDoc principal, Principal JavaDoc role)
398    {
399       boolean hasRole = false;
400       // Check that the caller is authenticated to the current thread
401
Subject JavaDoc subject = SubjectActions.getActiveSubject();
402       if( subject != null )
403       {
404          // Check the caller's roles
405
if( trace )
406             log.trace("doesUserHaveRole(Principal), subject: "+subject);
407
408             Group JavaDoc roles = getSubjectRoles(subject);
409             if( roles != null )
410             {
411                hasRole = doesRoleGroupHaveRole(role, roles);
412             }
413       }
414       return hasRole;
415    }
416
417    /** Return the set of domain roles the current active Subject 'Roles' group
418       found in the subject Principals set.
419
420     @param principal - ignored. The current authenticated Subject determines
421     the active user and assigned user roles.
422     @return The Set<Principal> for the application domain roles that the
423     principal has been assigned.
424    */

425    public Set JavaDoc getUserRoles(Principal JavaDoc principal)
426    {
427       HashSet JavaDoc userRoles = null;
428       // Check that the caller is authenticated to the current thread
429
Subject JavaDoc subject = SubjectActions.getActiveSubject();
430       if( subject != null )
431       {
432          // Copy the caller's roles
433
if( trace )
434             log.trace("getUserRoles, subject: "+subject);
435
436          Group JavaDoc roles = getSubjectRoles(subject);
437          if( roles != null )
438          {
439             userRoles = new HashSet JavaDoc();
440             Enumeration JavaDoc members = roles.members();
441             while( members.hasMoreElements() )
442             {
443                Principal JavaDoc role = (Principal JavaDoc) members.nextElement();
444                userRoles.add(role);
445             }
446          }
447       }
448       return userRoles;
449    }
450
451    /** Check that the indicated application domain role is a member of the
452     user's assigned roles. This handles the special AnybodyPrincipal and
453     NobodyPrincipal independent of the Group implementation.
454
455     @param role , the application domain role required for access
456     @param userRoles , the set of roles assigned to the user
457     @return true if role is in userRoles or an AnybodyPrincipal instance, false
458     if role is a NobodyPrincipal or no a member of userRoles
459     */

460    protected boolean doesRoleGroupHaveRole(Principal JavaDoc role, Group JavaDoc userRoles)
461    {
462       // First check that role is not a NobodyPrincipal
463
if (role instanceof NobodyPrincipal)
464          return false;
465
466       // Check for inclusion in the user's role set
467
boolean isMember = userRoles.isMember(role);
468       if (isMember == false)
469       { // Check the AnybodyPrincipal special cases
470
isMember = (role instanceof AnybodyPrincipal);
471       }
472
473       return isMember;
474    }
475
476    /** Currently this simply calls defaultLogin() to do a JAAS login using the
477     security domain name as the login module configuration name.
478     
479     * @param principal - the user id to authenticate
480     * @param credential - an opaque credential.
481     * @return false on failure, true on success.
482     */

483    private boolean authenticate(Principal JavaDoc principal, Object JavaDoc credential,
484       Subject JavaDoc theSubject)
485    {
486       Subject JavaDoc subject = null;
487       boolean authenticated = false;
488       LoginException JavaDoc authException = null;
489
490       try
491       {
492          // Validate the principal using the login configuration for this domain
493
LoginContext JavaDoc lc = defaultLogin(principal, credential);
494          subject = lc.getSubject();
495
496          // Set the current subject if login was successful
497
if( subject != null )
498          {
499             // Copy the current subject into theSubject
500
if( theSubject != null )
501             {
502                SubjectActions.copySubject(subject, theSubject);
503             }
504             else
505             {
506                theSubject = subject;
507             }
508
509             authenticated = true;
510             // Build the Subject based DomainInfo cache value
511
updateCache(lc, subject, principal, credential);
512          }
513       }
514       catch(LoginException JavaDoc e)
515       {
516          // Don't log anonymous user failures unless trace level logging is on
517
if( principal != null && principal.getName() != null || trace )
518             log.trace("Login failure", e);
519          authException = e;
520       }
521       // Set the security association thread context info exception
522
SubjectActions.setContextInfo("org.jboss.security.exception", authException);
523
524       return authenticated;
525    }
526
527    /** Pass the security info to the login modules configured for
528     this security domain using our SecurityAssociationHandler.
529     @return The authenticated Subject if successful.
530     @exception LoginException throw if login fails for any reason.
531     */

532    private LoginContext JavaDoc defaultLogin(Principal JavaDoc principal, Object JavaDoc credential)
533       throws LoginException JavaDoc
534    {
535       /* We use our internal CallbackHandler to provide the security info. A
536       copy must be made to ensure there is a unique handler per active
537       login since there can be multiple active logins.
538       */

539       Object JavaDoc[] securityInfo = {principal, credential};
540       CallbackHandler JavaDoc theHandler = null;
541       try
542       {
543          theHandler = (CallbackHandler JavaDoc) handler.getClass().newInstance();
544          setSecurityInfo.invoke(theHandler, securityInfo);
545       }
546       catch (Throwable JavaDoc e)
547       {
548          if( trace )
549             log.trace("Failed to create/setSecurityInfo on handler", e);
550          LoginException JavaDoc le = new LoginException JavaDoc("Failed to setSecurityInfo on handler");
551          le.initCause(e);
552          throw le;
553       }
554       Subject JavaDoc subject = new Subject JavaDoc();
555       LoginContext JavaDoc lc = null;
556       if( trace )
557          log.trace("defaultLogin, principal="+principal);
558       lc = SubjectActions.createLoginContext(securityDomain, subject, theHandler);
559       lc.login();
560       if( trace )
561          log.trace("defaultLogin, lc="+lc+", subject="+SubjectActions.toString(subject));
562       return lc;
563    }
564
565    /** Validate the cache credential value against the provided credential
566     */

567    private boolean validateCache(DomainInfo info, Object JavaDoc credential,
568       Subject JavaDoc theSubject)
569    {
570       if( trace )
571       {
572          StringBuffer JavaDoc tmp = new StringBuffer JavaDoc("Begin validateCache, info=");
573          tmp.append(info.toString());
574          tmp.append(";credential.class=");
575          if( credential != null )
576          {
577             Class JavaDoc c = credential.getClass();
578             tmp.append(c.getName());
579             tmp.append('@');
580             tmp.append(System.identityHashCode(c));
581          }
582          else
583          {
584             tmp.append("null");
585          }
586          log.trace(tmp.toString());
587       }
588
589       Object JavaDoc subjectCredential = info.credential;
590       boolean isValid = false;
591       // Check for a null credential as can be the case for an anonymous user
592
if( credential == null || subjectCredential == null )
593       {
594          // Both credentials must be null
595
isValid = (credential == null) && (subjectCredential == null);
596       }
597       // See if the credential is assignable to the cache value
598
else if( subjectCredential.getClass().isAssignableFrom(credential.getClass()) )
599       {
600         /* Validate the credential by trying Comparable, char[], byte[],
601          Object[], and finally Object.equals()
602          */

603          if( subjectCredential instanceof Comparable JavaDoc )
604          {
605             Comparable JavaDoc c = (Comparable JavaDoc) subjectCredential;
606             isValid = c.compareTo(credential) == 0;
607          }
608          else if( subjectCredential instanceof char[] )
609          {
610             char[] a1 = (char[]) subjectCredential;
611             char[] a2 = (char[]) credential;
612             isValid = Arrays.equals(a1, a2);
613          }
614          else if( subjectCredential instanceof byte[] )
615          {
616             byte[] a1 = (byte[]) subjectCredential;
617             byte[] a2 = (byte[]) credential;
618             isValid = Arrays.equals(a1, a2);
619          }
620          else if( subjectCredential.getClass().isArray() )
621          {
622             Object JavaDoc[] a1 = (Object JavaDoc[]) subjectCredential;
623             Object JavaDoc[] a2 = (Object JavaDoc[]) credential;
624             isValid = Arrays.equals(a1, a2);
625          }
626          else
627          {
628             isValid = subjectCredential.equals(credential);
629          }
630       }
631
632       // If the credentials match, set the thread's active Subject
633
if( isValid )
634       {
635          // Copy the current subject into theSubject
636
if( theSubject != null )
637          {
638             SubjectActions.copySubject(info.subject, theSubject);
639          }
640       }
641       if( trace )
642          log.trace("End validateCache, isValid="+isValid);
643
644       return isValid;
645    }
646  
647    /** An accessor method that synchronizes access on the domainCache
648     to avoid a race condition that can occur when the cache entry expires
649     in the presence of multi-threaded access. The allowRefresh flag should
650     be true for authentication accesses and false for other accesses.
651     Previously the other accesses included authorization and caller principal
652     mapping. Now the only use of the
653
654     @param principal - the caller identity whose cached credentials are to
655     be accessed.
656     @param allowRefresh - a flag indicating if the cache access should flush
657     any expired entries.
658     */

659    private DomainInfo getCacheInfo(Principal JavaDoc principal, boolean allowRefresh)
660    {
661       if( domainCache == null )
662          return null;
663
664       DomainInfo cacheInfo = null;
665       synchronized( domainCache )
666       {
667           if( allowRefresh == true )
668             cacheInfo = (DomainInfo) domainCache.get(principal);
669           else
670             cacheInfo = (DomainInfo) domainCache.peek(principal);
671          if( cacheInfo != null )
672             cacheInfo.acquire();
673       }
674       return cacheInfo;
675    }
676
677    private Subject JavaDoc updateCache(LoginContext JavaDoc lc, Subject JavaDoc subject,
678       Principal JavaDoc principal, Object JavaDoc credential)
679    {
680       // If we don't have a cache there is nothing to update
681
if( domainCache == null )
682          return subject;
683
684       int lifetime = 0;
685       if( domainCache instanceof TimedCachePolicy )
686       {
687          TimedCachePolicy cache = (TimedCachePolicy) domainCache;
688          lifetime = cache.getDefaultLifetime();
689       }
690       DomainInfo info = new DomainInfo(lifetime);
691       info.loginCtx = lc;
692       info.subject = new Subject JavaDoc();
693       SubjectActions.copySubject(subject, info.subject, true);
694       info.credential = credential;
695
696       if( trace )
697       {
698          log.trace("updateCache, inputSubject="+SubjectActions.toString(subject)
699             +", cacheSubject="+SubjectActions.toString(info.subject));
700       }
701
702      /* Get the Subject callerPrincipal by looking for a Group called
703         'CallerPrincipal'
704       */

705       Set JavaDoc subjectGroups = subject.getPrincipals(Group JavaDoc.class);
706       Iterator JavaDoc iter = subjectGroups.iterator();
707       while( iter.hasNext() )
708       {
709          Group JavaDoc grp = (Group JavaDoc) iter.next();
710          String JavaDoc name = grp.getName();
711          if( name.equals("CallerPrincipal") )
712          {
713             Enumeration JavaDoc members = grp.members();
714             if( members.hasMoreElements() )
715                info.callerPrincipal = (Principal JavaDoc) members.nextElement();
716          }
717       }
718       
719      /* Handle null principals with no callerPrincipal. This is an indication
720         of an user that has not provided any authentication info, but
721         has been authenticated by the domain login module stack. Here we look
722         for the first non-Group Principal and use that.
723       */

724       if( principal == null && info.callerPrincipal == null )
725       {
726          Set JavaDoc subjectPrincipals = subject.getPrincipals(Principal JavaDoc.class);
727          iter = subjectPrincipals.iterator();
728          while( iter.hasNext() )
729          {
730             Principal JavaDoc p = (Principal JavaDoc) iter.next();
731             if( (p instanceof Group JavaDoc) == false )
732                info.callerPrincipal = p;
733          }
734       }
735
736      /* If the user already exists another login is active. Currently
737         only one is allowed so remove the old and insert the new. Synchronize
738         on the domainCache to ensure the removal and addition are an atomic
739         operation so that getCacheInfo cannot see stale data.
740       */

741       synchronized( domainCache )
742       {
743          if( domainCache.peek(principal) != null )
744             domainCache.remove(principal);
745          domainCache.insert(principal, info);
746          if( trace )
747             log.trace("Inserted cache info: "+info);
748       }
749       return info.subject;
750    }
751
752    /**
753     * Get the Subject roles by looking for a Group called 'Roles'
754     * @param theSubject - the Subject to search for roles
755     * @return the Group contain the subject roles if found, null otherwise
756     */

757    private Group JavaDoc getSubjectRoles(Subject JavaDoc theSubject)
758    {
759        Set JavaDoc subjectGroups = theSubject.getPrincipals(Group JavaDoc.class);
760        Iterator JavaDoc iter = subjectGroups.iterator();
761        Group JavaDoc roles = null;
762        while( iter.hasNext() )
763        {
764           Group JavaDoc grp = (Group JavaDoc) iter.next();
765           String JavaDoc name = grp.getName();
766           if( name.equals("Roles") )
767              roles = grp;
768        }
769       return roles;
770    }
771 }
772
Popular Tags