Clover coverage report - JBoss
Coverage timestamp: Fri Mar 7 2003 04:05:35 GMT
file stats: LOC: 349   Methods: 15
NCLOC: 181   Classes: 2
 
 Source file Conditionals Statements Methods TOTAL
SecurityAssociation.java 82.5% 90.7% 100% 89.4%
 1   
 /*
 2   
  * JBoss, the OpenSource J2EE webOS
 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;
 11   
 import java.util.ArrayList;
 12   
 import javax.security.auth.Subject;
 13   
 
 14   
 /** The SecurityAssociation class maintains the security principal and
 15   
 credentials. This can be done on either a singleton basis or a thread
 16   
 local basis depending on the server property. When the server property has
 17   
 been set to true, the security information is maintained in thread local
 18   
 storage. The type of thread local storage depends on the
 19   
 org.jboss.security.SecurityAssociation.ThreadLocal property.
 20   
 If this property is true, then the thread local storage object is of
 21   
 type java.lang.ThreadLocal which results in the current thread's
 22   
 security information NOT being propagated to child threads.
 23   
 
 24   
 When the property is false or does not exist, the thread local storage object
 25   
 is of type java.lang.InheritableThreadLocal, and any threads spawned by the
 26   
 current thread will inherit the security information of the current thread.
 27   
 Subseqent changes to the current thread's security information are NOT
 28   
 propagated to any previously spawned child threads.
 29   
 
 30   
 When the server property is false, security information is maintained in
 31   
 class variables which makes the information available to all threads within
 32   
 the current VM.
 33   
 
 34   
 @author Daniel O'Connor (docodan@nycap.rr.com)
 35   
 @author Scott.Stark@jboss.org
 36   
 @version $Revision: 1.10.2.1 $
 37   
  */
 38   
 public final class SecurityAssociation
 39   
 {
 40   
    /** A flag indicating if security information is global or thread local */
 41   
    private static boolean server;
 42   
    /** The SecurityAssociation principal used when the server flag is false */
 43   
    private static Principal principal;
 44   
    /** The SecurityAssociation credential used when the server flag is false */
 45   
    private static Object credential;
 46   
    /** The SecurityAssociation Subject used when the server flag is false */
 47   
    private static Subject subject;
 48   
 
 49   
    /** The SecurityAssociation principal used when the server flag is true */
 50   
    private static ThreadLocal threadPrincipal;
 51   
    /** The SecurityAssociation credential used when the server flag is true */
 52   
    private static ThreadLocal threadCredential;
 53   
    /** The SecurityAssociation Subject used when the server flag is true */
 54   
    private static ThreadLocal threadSubject;
 55   
 
 56   
    /** Thread local stacks of run-as principal roles used to implement J2EE
 57   
     run-as identity propagation */
 58   
    private static RunAsThreadLocalStack threadRunAsStacks = new RunAsThreadLocalStack();
 59   
    /** The permission required to access getPrincpal, getCredential, getSubject */
 60   
    private static final RuntimePermission getPrincipalInfoPermission =
 61   
       new RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo");
 62   
    /** The permission required to access setPrincpal, setCredential, setSubject */
 63   
    private static final RuntimePermission setPrincipalInfoPermission =
 64   
       new RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo");
 65   
    /** The permission required to access setServer */
 66   
    private static final RuntimePermission setServerPermission =
 67   
       new RuntimePermission("org.jboss.security.SecurityAssociation.setServer");
 68   
    /** The permission required to access pushRunAsRole/popRunAsRole */
 69   
    private static final RuntimePermission setRunAsRole =
 70   
       new RuntimePermission("org.jboss.security.SecurityAssociation.setRunAsRole");
 71   
 
 72   
    static
 73   
    {
 74  53
       boolean useThreadLocal = false;
 75  53
       try
 76   
       {
 77  53
          useThreadLocal = Boolean.getBoolean("org.jboss.security.SecurityAssociation.ThreadLocal");
 78   
       }
 79   
       catch(SecurityException e)
 80   
       {
 81   
          // Ignore and use the default
 82   
       }
 83   
       
 84  53
       if( useThreadLocal )
 85   
       {
 86  0
          threadPrincipal = new ThreadLocal();
 87  0
          threadCredential = new ThreadLocal();
 88  0
          threadSubject = new ThreadLocal();
 89   
       }
 90   
       else
 91   
       {
 92  53
          threadPrincipal = new InheritableThreadLocal();
 93  53
          threadCredential = new InheritableThreadLocal();
 94  53
          threadSubject = new InheritableThreadLocal();
 95   
       }
 96   
    }
 97   
 
 98   
    /** Get the current principal information.
 99   
     If a security manager is present, then this method calls the security
 100   
     manager's <code>checkPermission</code> method with a
 101   
     <code>
 102   
     RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
 103   
     </code>
 104   
     permission to ensure it's ok to access principal information.
 105   
     If not, a <code>SecurityException</code> will be thrown.
 106   
     @return Principal, the current principal identity.
 107   
     */
 108  23116
    public static Principal getPrincipal()
 109   
    {
 110  23116
       SecurityManager sm = System.getSecurityManager();
 111  23116
       if( sm != null )
 112  266
          sm.checkPermission(getPrincipalInfoPermission);
 113   
 
 114  23116
       if (server)
 115  20083
          return (Principal) threadPrincipal.get();
 116   
       else
 117  3033
          return principal;
 118   
    }
 119   
    
 120   
    /** Get the current principal credential information. This can be of
 121   
     any type including: a String password, a char[] password, an X509 cert,
 122   
     etc.
 123   
     If a security manager is present, then this method calls the security
 124   
     manager's <code>checkPermission</code> method with a
 125   
     <code>
 126   
     RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
 127   
     </code>
 128   
     permission to ensure it's ok to access principal information.
 129   
     If not, a <code>SecurityException</code> will be thrown.
 130   
     @return Object, the credential that proves the principal identity.
 131   
     */
 132  23116
    public static Object getCredential()
 133   
    {
 134  23116
       SecurityManager sm = System.getSecurityManager();
 135  23116
       if( sm != null )
 136  266
          sm.checkPermission(getPrincipalInfoPermission);
 137   
 
 138  23116
       if (server)
 139  20083
          return threadCredential.get();
 140   
       else
 141  3033
          return credential;
 142   
    }
 143   
 
 144   
    /** Get the current Subject information.
 145   
     If a security manager is present, then this method calls the security
 146   
     manager's <code>checkPermission</code> method with a
 147   
     <code>
 148   
     RuntimePermission("org.jboss.security.SecurityAssociation.getPrincipalInfo")
 149   
     </code>
 150   
     permission to ensure it's ok to access principal information.
 151   
     If not, a <code>SecurityException</code> will be thrown.
 152   
     @return Subject, the current Subject identity.
 153   
     */
 154  1029
    public static Subject getSubject()
 155   
    {
 156  1029
       SecurityManager sm = System.getSecurityManager();
 157  1029
       if( sm != null )
 158  0
          sm.checkPermission(getPrincipalInfoPermission);
 159   
 
 160  1029
       if (server)
 161  1029
          return (Subject) threadSubject.get();
 162   
       else
 163  0
          return subject;
 164   
    }
 165   
 
 166   
    /** Set the current principal information.
 167   
     If a security manager is present, then this method calls the security
 168   
     manager's <code>checkPermission</code> method with a
 169   
     <code>
 170   
     RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
 171   
     </code>
 172   
     permission to ensure it's ok to access principal information.
 173   
     If not, a <code>SecurityException</code> will be thrown.
 174   
     @param principal, the current principal identity.
 175   
     */
 176  23299
    public static void setPrincipal( Principal principal )
 177   
    {
 178  23299
       SecurityManager sm = System.getSecurityManager();
 179  23299
       if( sm != null )
 180  23
          sm.checkPermission(setPrincipalInfoPermission);
 181   
 
 182  23299
       if (server)
 183  23276
          threadPrincipal.set( principal );
 184   
       else
 185  23
          SecurityAssociation.principal = principal;
 186   
    }
 187   
    
 188   
    /** Set the current principal credential information. This can be of
 189   
     any type including: a String password, a char[] password, an X509 cert,
 190   
     etc.
 191   
 
 192   
     If a security manager is present, then this method calls the security
 193   
     manager's <code>checkPermission</code> method with a
 194   
     <code>
 195   
     RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
 196   
     </code>
 197   
     permission to ensure it's ok to access principal information.
 198   
     If not, a <code>SecurityException</code> will be thrown.
 199   
     @param credential, the credential that proves the principal identity.
 200   
     */
 201  23299
    public static void setCredential( Object credential )
 202   
    {
 203  23299
       SecurityManager sm = System.getSecurityManager();
 204  23299
       if( sm != null )
 205  23
          sm.checkPermission(setPrincipalInfoPermission);
 206   
 
 207  23299
       if (server)
 208  23276
          threadCredential.set( credential );
 209   
       else
 210  23
          SecurityAssociation.credential = credential;
 211   
    }
 212   
 
 213   
    /** Set the current Subject information.
 214   
     If a security manager is present, then this method calls the security
 215   
     manager's <code>checkPermission</code> method with a
 216   
     <code>
 217   
     RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
 218   
     </code>
 219   
     permission to ensure it's ok to access principal information.
 220   
     If not, a <code>SecurityException</code> will be thrown.
 221   
     @param principal, the current principal identity.
 222   
     */
 223  1057
    public static void setSubject(Subject subject)
 224   
    {
 225  1057
       SecurityManager sm = System.getSecurityManager();
 226  1057
       if( sm != null )
 227  23
          sm.checkPermission(setPrincipalInfoPermission);
 228   
 
 229  1057
       if (server)
 230  1034
          threadSubject.set( subject );
 231   
       else
 232  23
          SecurityAssociation.subject = subject;
 233   
    }
 234   
 
 235   
    /** Clear all principal information.
 236   
     If a security manager is present, then this method calls the security
 237   
     manager's <code>checkPermission</code> method with a
 238   
     <code>
 239   
     RuntimePermission("org.jboss.security.SecurityAssociation.setPrincipalInfo")
 240   
     </code>
 241   
     permission to ensure it's ok to access principal information.
 242   
     If not, a <code>SecurityException</code> will be thrown.
 243   
     @param principal, the current principal identity.
 244   
     */
 245  16
    public static void clear()
 246   
    {
 247  16
       SecurityManager sm = System.getSecurityManager();
 248  16
       if( sm != null )
 249  15
          sm.checkPermission(setPrincipalInfoPermission);
 250  16
       if( server == true )
 251   
       {
 252  1
          threadPrincipal.set(null);
 253  1
          threadCredential.set(null);
 254  1
          threadSubject.set(null);
 255   
       }
 256   
       else
 257   
       {
 258  15
          SecurityAssociation.principal = null;
 259  15
          SecurityAssociation.credential = null;
 260  15
          SecurityAssociation.subject = null;
 261   
       }
 262   
    }
 263   
 
 264   
    /** Push the current thread of control's run-as principal role.
 265   
     */
 266  7
    public static void pushRunAsRole(Principal runAsRole)
 267   
    {
 268  7
       SecurityManager sm = System.getSecurityManager();
 269  7
       if( sm != null )
 270  0
          sm.checkPermission(setRunAsRole);
 271  7
       threadRunAsStacks.push(runAsRole);
 272   
    }
 273   
    /** Pop the current thread of control's run-as principal role.
 274   
     */
 275  7
    public static Principal popRunAsRole()
 276   
    {
 277  7
       SecurityManager sm = System.getSecurityManager();
 278  7
       if( sm != null )
 279  0
          sm.checkPermission(setRunAsRole);
 280  7
       Principal runAsRole = threadRunAsStacks.pop();
 281  7
       return runAsRole;
 282   
    }
 283   
    /** Look at the current thread of control's run-as principal role.
 284   
     */
 285  329
    public static Principal peekRunAsRole()
 286   
    {
 287  329
       Principal runAsRole = threadRunAsStacks.peek();
 288  329
       return runAsRole;
 289   
    }
 290   
 
 291   
    /** Set the server mode of operation. When the server property has
 292   
     been set to true, the security information is maintained in thread local
 293   
     storage. This should be called to enable property security semantics
 294   
     in any multi-threaded environment where more than one thread requires
 295   
     that security information be restricted to the thread's flow of control.
 296   
 
 297   
     If a security manager is present, then this method calls the security
 298   
     manager's <code>checkPermission</code> method with a
 299   
     <code>
 300   
     RuntimePermission("org.jboss.security.SecurityAssociation.setServer")
 301   
     </code>
 302   
     permission to ensure it's ok to access principal information.
 303   
     If not, a <code>SecurityException</code> will be thrown.
 304   
     */
 305  1
    public static void setServer()
 306   
    {
 307  1
       SecurityManager sm = System.getSecurityManager();
 308  1
       if( sm != null )
 309  0
          sm.checkPermission(setPrincipalInfoPermission);
 310   
 
 311  1
       server = true;
 312   
    }
 313   
 
 314   
    /** A subclass of ThreadLocal that implements a value stack
 315   
     using an ArrayList and implements push, pop and peek stack
 316   
     operations on the thread local ArrayList.
 317   
     */
 318   
    private static class RunAsThreadLocalStack extends ThreadLocal
 319   
    {
 320  14
       protected Object initialValue()
 321   
       {
 322  14
          return new ArrayList();
 323   
       }
 324  7
       void push(Principal runAs)
 325   
       {
 326  7
          ArrayList stack = (ArrayList) super.get();
 327  7
          stack.add(runAs);
 328   
       }
 329  7
       Principal pop()
 330   
       {
 331  7
          ArrayList stack = (ArrayList) super.get();
 332  7
          Principal runAs = null;
 333  7
          int lastIndex = stack.size() - 1;
 334  7
          if( lastIndex >= 0 )
 335  7
             runAs = (Principal) stack.remove(lastIndex);
 336  7
          return runAs;
 337   
       }
 338  329
       Principal peek()
 339   
       {
 340  329
          ArrayList stack = (ArrayList) super.get();
 341  329
          Principal runAs = null;
 342  329
          int lastIndex = stack.size() - 1;
 343  329
          if( lastIndex >= 0 )
 344  6
             runAs = (Principal) stack.get(lastIndex);
 345  329
          return runAs;
 346   
       }
 347   
    }
 348   
 }
 349