KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > security > SecurityAssociation


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

7
8 package org.jboss.security;
9
10 import java.security.Principal JavaDoc;
11 import java.util.ArrayList JavaDoc;
12 import java.util.HashMap JavaDoc;
13 import javax.security.auth.Subject JavaDoc;
14
15 import org.jboss.logging.Logger;
16
17 /**
18  * The SecurityAssociation class maintains the security principal and
19  * credentials. This can be done on either a singleton basis or a thread local
20  * basis depending on the server property. When the server property has been set
21  * to true, the security information is maintained in thread local storage. The
22  * type of thread local storage depends on the org.jboss.security.SecurityAssociation.ThreadLocal
23  * property. If this property is true, then the thread local storage object is
24  * of type java.lang.ThreadLocal which results in the current thread's security
25  * information NOT being propagated to child threads.
26  *
27  * When the property is false or does not exist, the thread local storage object
28  * is of type java.lang.InheritableThreadLocal, and any threads spawned by the
29  * current thread will inherit the security information of the current thread.
30  * Subseqent changes to the current thread's security information are NOT
31  * propagated to any previously spawned child threads.
32  *
33  * When the server property is false, security information is maintained in
34  * class variables which makes the information available to all threads within
35  * the current VM.
36  *
37  * Note that this is not a public API class. Its an implementation detail that
38  * is subject to change without notice.
39  *
40  * @author Daniel O'Connor (docodan@nycap.rr.com)
41  * @author Scott.Stark@jboss.org
42  * @version $Revision: 1.19.2.6 $
43  */

44 public final class SecurityAssociation
45 {
46    private static Logger log = Logger.getLogger(SecurityAssociation.class);
47    /**
48     * A flag indicating if trace level logging should be performed
49     */

50    private static boolean trace;
51    /**
52     * A flag indicating if security information is global or thread local
53     */

54    private static boolean server;
55    /**
56     * The SecurityAssociation principal used when the server flag is false
57     */

58    private static Principal JavaDoc principal;
59    /**
60     * The SecurityAssociation credential used when the server flag is false
61     */

62    private static Object JavaDoc credential;
63
64    /**
65     * The SecurityAssociation principal used when the server flag is true
66     */

67    private static ThreadLocal JavaDoc threadPrincipal;
68    /**
69     * The SecurityAssociation credential used when the server flag is true
70     */

71    private static ThreadLocal JavaDoc threadCredential;
72    /**
73     * The SecurityAssociation HashMap<String, Object>
74     */

75    private static ThreadLocal JavaDoc threadContextMap;
76
77    /**
78     * Thread local stacks of run-as principal roles used to implement J2EE
79     * run-as identity propagation
80     */

81    private static RunAsThreadLocalStack threadRunAsStacks = new RunAsThreadLocalStack();
82    /**
83     * Thread local stacks of authenticated subject used to control the current
84     * caller security context
85     */

86    private static SubjectThreadLocalStack threadSubjectStacks = new SubjectThreadLocalStack();
87
88    /**
89     * The permission required to access getPrincpal, getCredential
90     */

91    private static final RuntimePermission JavaDoc getPrincipalInfoPermission =
92       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.getPrincipalInfo");
93    /**
94     * The permission required to access getSubject
95     */

96    private static final RuntimePermission JavaDoc getSubjectPermission =
97       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.getSubject");
98    /**
99     * The permission required to access setPrincpal, setCredential, setSubject
100     * pushSubjectContext, popSubjectContext
101     */

102    private static final RuntimePermission JavaDoc setPrincipalInfoPermission =
103       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.setPrincipalInfo");
104    /**
105     * The permission required to access setServer
106     */

107    private static final RuntimePermission JavaDoc setServerPermission =
108       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.setServer");
109    /**
110     * The permission required to access pushRunAsIdentity/popRunAsIdentity
111     */

112    private static final RuntimePermission JavaDoc setRunAsIdentity =
113       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.setRunAsRole");
114    /**
115     * The permission required to get the current security context info
116     */

117    private static final RuntimePermission JavaDoc getContextInfo =
118       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.accessContextInfo", "get");
119    /**
120     * The permission required to set the current security context info
121     */

122    private static final RuntimePermission JavaDoc setContextInfo =
123       new RuntimePermission JavaDoc("org.jboss.security.SecurityAssociation.accessContextInfo", "set");
124
125    static
126    {
127       boolean useThreadLocal = true;
128       try
129       {
130          useThreadLocal = Boolean.getBoolean("org.jboss.security.SecurityAssociation.ThreadLocal");
131       }
132       catch (SecurityException JavaDoc e)
133       {
134          // Ignore and use the default
135
}
136
137       trace = log.isTraceEnabled();
138       if (useThreadLocal)
139       {
140          threadPrincipal = new ThreadLocal JavaDoc();
141          threadCredential = new ThreadLocal JavaDoc();
142          threadContextMap = new ThreadLocal JavaDoc()
143          {
144             protected Object JavaDoc initialValue()
145             {
146                return new HashMap JavaDoc();
147             }
148          };
149       }
150       else
151       {
152          threadPrincipal = new InheritableThreadLocal JavaDoc();
153          threadCredential = new InheritableThreadLocal JavaDoc();
154          threadContextMap = new InheritableThreadLocal JavaDoc()
155          {
156             protected Object JavaDoc initialValue()
157             {
158                return new HashMap JavaDoc();
159             }
160          };
161       }
162    }
163
164    /**
165     * Get the current authentication principal information. If a security
166     * manager is present, then this method calls the security manager's
167     * <code>checkPermission</code> method with a
168     * <code>RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
169     * </code> permission to ensure it's ok to access principal information. If
170     * not, a <code>SecurityException</code> will be thrown.
171     * @return Principal, the current principal identity.
172     */

173    public static Principal JavaDoc getPrincipal()
174    {
175       SecurityManager JavaDoc sm = System.getSecurityManager();
176       if (sm != null)
177          sm.checkPermission(getPrincipalInfoPermission);
178
179       if (server)
180          return (Principal JavaDoc) threadPrincipal.get();
181       else
182          return principal;
183    }
184
185    /**
186     * Get the caller's principal. If a security manager is present,
187     * then this method calls the security manager's <code>checkPermission</code>
188     * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
189     * </code> permission to ensure it's ok to access principal information. If
190     * not, a <code>SecurityException</code> will be thrown.
191     *
192     * @return Principal, the current principal identity.
193     */

194    public static Principal JavaDoc getCallerPrincipal()
195    {
196       SecurityManager JavaDoc sm = System.getSecurityManager();
197       if (sm != null)
198          sm.checkPermission(getPrincipalInfoPermission);
199
200       if (peekRunAsIdentity(1) != null)
201          return peekRunAsIdentity(1);
202       if (server)
203          return (Principal JavaDoc) threadPrincipal.get();
204       else
205          return principal;
206    }
207
208    /**
209     * Get the current authentication credential information. This can be of any type
210     * including: a String password, a char[] password, an X509 cert, etc. If a
211     * security manager is present, then this method calls the security manager's
212     * <code>checkPermission</code> method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
213     * </code> permission to ensure it's ok to access principal information. If
214     * not, a <code>SecurityException</code> will be thrown.
215     * @return Object, the credential that proves the principal identity.
216     */

217    public static Object JavaDoc getCredential()
218    {
219       SecurityManager JavaDoc sm = System.getSecurityManager();
220       if (sm != null)
221          sm.checkPermission(getPrincipalInfoPermission);
222
223       if (server)
224          return threadCredential.get();
225       else
226          return credential;
227    }
228
229    /**
230     * Get the current Subject information. If a security manager is present,
231     * then this method calls the security manager's checkPermission method with
232     * a RuntimePermission("org.jboss.security.SecurityAssociation.getSubject")
233     * permission to ensure it's ok to access principal information. If not, a
234     * SecurityException will be thrown. Note that this method does not consider
235     * whether or not a run-as identity exists. For access to this information
236     * see the JACC PolicyContextHandler registered under the key
237     * "javax.security.auth.Subject.container"
238     * @return Subject, the current Subject identity.
239     * @see javax.security.jacc.PolicyContext#getContext(String)
240     */

241    public static Subject JavaDoc getSubject()
242    {
243       SecurityManager JavaDoc sm = System.getSecurityManager();
244       if (sm != null)
245          sm.checkPermission(getSubjectPermission);
246
247       SubjectContext sc = threadSubjectStacks.peek();
248       Subject JavaDoc subject = null;
249       if( sc != null )
250          subject = sc.getSubject();
251       return subject;
252    }
253
254    /**
255     * Set the current principal information. If a security manager is present,
256     * then this method calls the security manager's <code>checkPermission</code>
257     * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
258     * </code> permission to ensure it's ok to access principal information. If
259     * not, a <code>SecurityException</code> will be thrown.
260     * @param principal - the current principal identity.
261     */

262    public static void setPrincipal(Principal JavaDoc principal)
263    {
264       SecurityManager JavaDoc sm = System.getSecurityManager();
265       if (sm != null)
266          sm.checkPermission(setPrincipalInfoPermission);
267
268       if (trace)
269          log.trace("setPrincipal, p=" + principal + ", server=" + server);
270       if (server)
271          threadPrincipal.set(principal);
272       else
273          SecurityAssociation.principal = principal;
274       // Integrate with the new SubjectContext
275
SubjectContext sc = threadSubjectStacks.peek();
276       if( sc == null )
277       {
278          // There is no active security context
279
sc = new SubjectContext();
280          threadSubjectStacks.push(sc);
281       }
282       else if( (sc.getFlags() & SubjectContext.PRINCIPAL_WAS_SET) != 0 )
283       {
284          // The current security context has its principal set
285
sc = new SubjectContext();
286          threadSubjectStacks.push(sc);
287       }
288       sc.setPrincipal(principal);
289    }
290
291    /**
292     * Set the current principal credential information. This can be of any type
293     * including: a String password, a char[] password, an X509 cert, etc.
294     *
295     * If a security manager is present, then this method calls the security
296     * manager's <code>checkPermission</code> method with a <code>
297     * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
298     * </code> permission to ensure it's ok to access principal information. If
299     * not, a <code>SecurityException</code> will be thrown.
300     * @param credential - the credential that proves the principal identity.
301     */

302    public static void setCredential(Object JavaDoc credential)
303    {
304       SecurityManager JavaDoc sm = System.getSecurityManager();
305       if (sm != null)
306          sm.checkPermission(setPrincipalInfoPermission);
307
308       if (server)
309          threadCredential.set(credential);
310       else
311          SecurityAssociation.credential = credential;
312       // Integrate with the new SubjectContext
313
SubjectContext sc = threadSubjectStacks.peek();
314       if( sc == null )
315       {
316          // There is no active security context
317
sc = new SubjectContext();
318          threadSubjectStacks.push(sc);
319       }
320       else if( (sc.getFlags() & SubjectContext.CREDENTIAL_WAS_SET) != 0 )
321       {
322          // The current security context has its principal set
323
sc = new SubjectContext();
324          threadSubjectStacks.push(sc);
325       }
326       sc.setCredential(credential);
327    }
328
329    /**
330     * Set the current Subject information. If a security manager is present,
331     * then this method calls the security manager's <code>checkPermission</code>
332     * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
333     * </code> permission to ensure it's ok to access principal information. If
334     * not, a <code>SecurityException</code> will be thrown.
335     * @param subject - the current identity.
336     */

337    public static void setSubject(Subject JavaDoc subject)
338    {
339       SecurityManager JavaDoc sm = System.getSecurityManager();
340       if (sm != null)
341          sm.checkPermission(setPrincipalInfoPermission);
342
343       if (trace)
344          log.trace("setSubject, s=" + subject + ", server=" + server);
345       // Integrate with the new SubjectContext
346
SubjectContext sc = threadSubjectStacks.peek();
347       if( sc == null )
348       {
349          // There is no active security context
350
sc = new SubjectContext();
351          threadSubjectStacks.push(sc);
352       }
353       else if( (sc.getFlags() & SubjectContext.SUBJECT_WAS_SET) != 0 )
354       {
355          // The current security context has its subject set
356
sc = new SubjectContext();
357          threadSubjectStacks.push(sc);
358       }
359       sc.setSubject(subject);
360    }
361
362    /**
363     * Get the current thread context info. If a security manager is present,
364     * then this method calls the security manager's <code>checkPermission</code>
365     * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.accessContextInfo",
366     * "get") </code> permission to ensure it's ok to access context information.
367     * If not, a <code>SecurityException</code> will be thrown.
368     * @param key - the context key
369     * @return the mapping for the key in the current thread context
370     */

371    public static Object JavaDoc getContextInfo(Object JavaDoc key)
372    {
373       SecurityManager JavaDoc sm = System.getSecurityManager();
374       if (sm != null)
375          sm.checkPermission(getContextInfo);
376
377       HashMap JavaDoc contextInfo = (HashMap JavaDoc) threadContextMap.get();
378       return contextInfo.get(key);
379    }
380
381    /**
382     * Set the current thread context info. If a security manager is present,
383     * then this method calls the security manager's <code>checkPermission</code>
384     * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.accessContextInfo",
385     * "set") </code> permission to ensure it's ok to access context information.
386     * If not, a <code>SecurityException</code> will be thrown.
387     * @param key - the context key
388     * @param value - the context value to associate under key
389     * @return the previous mapping for the key if one exists
390     */

391    public static Object JavaDoc setContextInfo(Object JavaDoc key, Object JavaDoc value)
392    {
393       SecurityManager JavaDoc sm = System.getSecurityManager();
394       if (sm != null)
395          sm.checkPermission(setContextInfo);
396
397       HashMap JavaDoc contextInfo = (HashMap JavaDoc) threadContextMap.get();
398       return contextInfo.put(key, value);
399    }
400
401    /**
402     * Push the current authenticated context. This sets the authenticated subject
403     * along with the principal and proof of identity that was used to validate
404     * the subject. This context is used for authorization checks. Typically
405     * just the subject as seen by getSubject() is input into the authorization.
406     * When run under a security manager this requires the
407     * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
408     * permission.
409     * @param subject - the authenticated subject
410     * @param principal - the principal that was input into the authentication
411     * @param credential - the credential that was input into the authentication
412     */

413    public static void pushSubjectContext(Subject JavaDoc subject,
414       Principal JavaDoc principal, Object JavaDoc credential)
415    {
416       SecurityManager JavaDoc sm = System.getSecurityManager();
417       if (sm != null)
418          sm.checkPermission(setPrincipalInfoPermission);
419
420       if (trace)
421          log.trace("pushSubjectContext, subject=" + subject + ", principal="+principal);
422       // Set the legacy single-value access points
423
if (server)
424       {
425          threadPrincipal.set(principal);
426          threadCredential.set(credential);
427       }
428       else
429       {
430          SecurityAssociation.principal = principal;
431          SecurityAssociation.credential = credential;
432       }
433       // Push the subject context
434
SubjectContext sc = new SubjectContext(subject, principal, credential);
435       threadSubjectStacks.push(sc);
436    }
437    /**
438     * Push a duplicate of the current SubjectContext if one exists.
439     * When run under a security manager this requires the
440     * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
441     * permission.
442     */

443    public static void dupSubjectContext()
444    {
445       SecurityManager JavaDoc sm = System.getSecurityManager();
446       if (sm != null)
447          sm.checkPermission(setPrincipalInfoPermission);
448
449       if (trace)
450          log.trace("dupSubjectContext");
451       threadSubjectStacks.dup();
452    }
453
454    /**
455     * Pop the current SubjectContext from the previous pushSubjectContext call
456     * and return the pushed SubjectContext ig there was one.
457     * When run under a security manager this requires the
458     * RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
459     * permission.
460     * @return the SubjectContext pushed previously by a pushSubjectContext call
461     */

462    public static SubjectContext popSubjectContext()
463    {
464       SecurityManager JavaDoc sm = System.getSecurityManager();
465       if (sm != null)
466          sm.checkPermission(setPrincipalInfoPermission);
467
468       SubjectContext sc = threadSubjectStacks.pop();
469       return sc;
470    }
471
472    /**
473     * Clear all principal information. If a security manager is present, then
474     * this method calls the security manager's <code>checkPermission</code>
475     * method with a <code> RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
476     * </code> permission to ensure it's ok to access principal information. If
477     * not, a <code>SecurityException</code> will be thrown.
478     */

479    public static void clear()
480    {
481       SecurityManager JavaDoc sm = System.getSecurityManager();
482       if (sm != null)
483          sm.checkPermission(setPrincipalInfoPermission);
484
485       if (trace)
486          log.trace("clear, server=" + server);
487       if (server == true)
488       {
489          threadPrincipal.set(null);
490          threadCredential.set(null);
491       }
492       else
493       {
494          SecurityAssociation.principal = null;
495          SecurityAssociation.credential = null;
496       }
497       //
498
threadSubjectStacks.clear();
499    }
500
501    /**
502     * Push the current thread of control's run-as identity.
503     */

504    public static void pushRunAsIdentity(RunAsIdentity runAs)
505    {
506       SecurityManager JavaDoc sm = System.getSecurityManager();
507       if (sm != null)
508          sm.checkPermission(setRunAsIdentity);
509       if (trace)
510          log.trace("pushRunAsIdentity, runAs=" + runAs);
511       threadRunAsStacks.push(runAs);
512    }
513
514    /**
515     * Pop the current thread of control's run-as identity.
516     */

517    public static RunAsIdentity popRunAsIdentity()
518    {
519       SecurityManager JavaDoc sm = System.getSecurityManager();
520       if (sm != null)
521          sm.checkPermission(setRunAsIdentity);
522       RunAsIdentity runAs = threadRunAsStacks.pop();
523       if (trace)
524          log.trace("popRunAsIdentity, runAs=" + runAs);
525       return runAs;
526    }
527
528    /**
529     * Look at the current thread of control's run-as identity on the top of the
530     * stack.
531     */

532    public static RunAsIdentity peekRunAsIdentity()
533    {
534       return peekRunAsIdentity(0);
535    }
536
537    /**
538     * Look at the current thread of control's run-as identity at the indicated
539     * depth. Typically depth is either 0 for the identity the current caller
540     * run-as that will be assumed, or 1 for the active run-as the previous
541     * caller has assumed.
542     * @return RunAsIdentity depth frames up.
543     */

544    public static RunAsIdentity peekRunAsIdentity(int depth)
545    {
546       RunAsIdentity runAs = threadRunAsStacks.peek(depth);
547       return runAs;
548    }
549
550    /**
551     * Set the server mode of operation. When the server property has been set to
552     * true, the security information is maintained in thread local storage. This
553     * should be called to enable property security semantics in any
554     * multi-threaded environment where more than one thread requires that
555     * security information be restricted to the thread's flow of control.
556     *
557     * If a security manager is present, then this method calls the security
558     * manager's <code>checkPermission</code> method with a <code>
559     * RuntimePermission("org.jboss.security.SecurityAssociation.setServer")
560     * </code> permission to ensure it's ok to access principal information. If
561     * not, a <code>SecurityException</code> will be thrown.
562     */

563    public static void setServer()
564    {
565       SecurityManager JavaDoc sm = System.getSecurityManager();
566       if (sm != null)
567          sm.checkPermission(setServerPermission);
568
569       server = true;
570    }
571
572    /**
573     * A subclass of ThreadLocal that implements a value stack using an ArrayList
574     * and implements push, pop and peek stack operations on the thread local
575     * ArrayList.
576     */

577    private static class RunAsThreadLocalStack extends ThreadLocal JavaDoc
578    {
579       protected Object JavaDoc initialValue()
580       {
581          return new ArrayList JavaDoc();
582       }
583
584       void push(RunAsIdentity runAs)
585       {
586          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
587          stack.add(runAs);
588       }
589
590       RunAsIdentity pop()
591       {
592          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
593          RunAsIdentity runAs = null;
594          int lastIndex = stack.size() - 1;
595          if (lastIndex >= 0)
596             runAs = (RunAsIdentity) stack.remove(lastIndex);
597          return runAs;
598       }
599
600       /**
601        * Look for the first non-null run-as identity on the stack starting
602        * with the value at depth.
603        * @return The run-as identity if one exists, null otherwise.
604        */

605       RunAsIdentity peek(int depth)
606       {
607          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
608          RunAsIdentity runAs = null;
609          final int stackSize = stack.size();
610          do
611          {
612             int index = stackSize - 1 - depth;
613             if( index >= 0 )
614                runAs = (RunAsIdentity) stack.get(index);
615             depth ++;
616          }
617          while (runAs == null && depth <= stackSize - 1);
618          return runAs;
619       }
620    }
621
622    /**
623     * The encapsulation of the authenticated subject
624     */

625    public static class SubjectContext
626    {
627       public static final int SUBJECT_WAS_SET = 1;
628       public static final int PRINCIPAL_WAS_SET = 2;
629       public static final int CREDENTIAL_WAS_SET = 4;
630
631       private Subject JavaDoc subject;
632       private Principal JavaDoc principal;
633       private Object JavaDoc credential;
634       private int flags;
635
636       public SubjectContext()
637       {
638          this.flags = 0;
639       }
640       public SubjectContext(Subject JavaDoc s, Principal JavaDoc p, Object JavaDoc cred)
641       {
642          this.subject = s;
643          this.principal = p;
644          this.credential = cred;
645          this.flags = SUBJECT_WAS_SET | PRINCIPAL_WAS_SET | CREDENTIAL_WAS_SET;
646       }
647
648       public Subject JavaDoc getSubject()
649       {
650          return subject;
651       }
652       public void setSubject(Subject JavaDoc subject)
653       {
654          this.subject = subject;
655          this.flags |= SUBJECT_WAS_SET;
656       }
657
658       public Principal JavaDoc getPrincipal()
659       {
660          return principal;
661       }
662       public void setPrincipal(Principal JavaDoc principal)
663       {
664          this.principal = principal;
665          this.flags |= PRINCIPAL_WAS_SET;
666       }
667
668       public Object JavaDoc getCredential()
669       {
670          return credential;
671       }
672       public void setCredential(Object JavaDoc credential)
673       {
674          this.credential = credential;
675          this.flags |= CREDENTIAL_WAS_SET;
676       }
677
678       public int getFlags()
679       {
680          return this.flags;
681       }
682    }
683
684    private static class SubjectThreadLocalStack extends ThreadLocal JavaDoc
685    {
686       protected Object JavaDoc initialValue()
687       {
688          return new ArrayList JavaDoc();
689       }
690
691       void push(SubjectContext context)
692       {
693          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
694          stack.add(context);
695       }
696
697       SubjectContext dup()
698       {
699          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
700          SubjectContext context = null;
701          int lastIndex = stack.size() - 1;
702          if (lastIndex >= 0)
703          {
704             context = (SubjectContext) stack.get(lastIndex);
705             stack.add(context);
706          }
707          return context;
708       }
709
710       SubjectContext pop()
711       {
712          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
713          SubjectContext context = null;
714          int lastIndex = stack.size() - 1;
715          if (lastIndex >= 0)
716             context = (SubjectContext) stack.remove(lastIndex);
717          return context;
718       }
719
720       /**
721        * Look for the first non-null run-as identity on the stack starting
722        * with the value at depth.
723        * @return The run-as identity if one exists, null otherwise.
724        */

725       SubjectContext peek()
726       {
727          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
728          SubjectContext context = null;
729          int lastIndex = stack.size() - 1;
730          if (lastIndex >= 0)
731             context = (SubjectContext) stack.get(lastIndex);
732          return context;
733       }
734       /**
735        * Remove all SubjectContext from the current thread stack
736        */

737       void clear()
738       {
739          ArrayList JavaDoc stack = (ArrayList JavaDoc) super.get();
740          stack.clear();
741       }
742    }
743
744 }
745
Popular Tags