FileDocCategorySizeDatePackage
PermissionCache.javaAPI DocGlassfish v2 API12494Fri May 04 22:32:04 BST 2007com.sun.enterprise.security

PermissionCache

public class PermissionCache extends Object
This class is
author
Ron Monzillo

Fields Summary
private static Logger
_logger
private static Policy
policy
private static AllPermission
allPermission
private Permissions
cache
private CodeSource
codesource
private Permission[]
protoPerms
private Class[]
classes
private String
name
private String
pcID
private final Integer
factoryKey
private volatile int
epoch
private volatile boolean
loading
private ReadWriteLock
rwLock
private Lock
rLock
private Lock
wLock
Constructors Summary
public PermissionCache(Integer key, String pcID, CodeSource codesource, Class clazz, String name)

 
    /*
     * USE OF THIS CONSTRUCTOR WITH IS DISCOURAGED PLEASE USE THE Permission 
     * (object) based CONSTRUCTOR.
     * @param key -  Integer that uniquely identifies the cache at the factory
     * @param pcID - a string identifying the policy context and which must 
     *     be set when getPermissions is called (internally). this value may be 
     *     null, in which case the permisions of the default policy context
     *     will be cached.
     * @param codesource - the codesource argument to be used in the call to 
     *     getPermissions. this value may be null.
     * @param class - a single Class object that identifies the permission 
     *     type that will be managed by the cache. This value may be 
     *     null. When this argument is not null, only permissions of the 
     *     identified type  or that resolve to the identified type, 
     *     will be managed within the cache. When null is passed to this
     *     argument, permission type will not be a factor in determining
     *     the cached permissions.
     * @param name - a string corresponding to a value returned by 
     *     Permission.getName(). Only permissions whose getName() value 
     *     matches the name parameter will be included in the cache. This value 
     *     may be null, in which case permission name does not factor into
     *     the permission caching.
     */
          
			      
  	if (codesource == null) {
 	    this.codesource = 
 		new CodeSource(null,
 			       (java.security.cert.Certificate[])null);
  	} else {
  	    this.codesource = codesource;
  	}
 	this.factoryKey = key;
  	this.cache  = null;
  	this.pcID = pcID;
 	this.protoPerms = null;
 	if (clazz != null) {
 	    this.classes = new Class[] {clazz};
 	} else {
 	    this.classes = null;
 	}
  	this.name = name;
 	this.epoch = 1;
 	this.loading = false;
 	this.rwLock = new ReentrantReadWriteLock(true);
 	this.rLock = rwLock.readLock();
 	this.wLock = rwLock.writeLock();
    
public PermissionCache(Integer key, String pcID, CodeSource codesource, Permission[] perms, String name)

 	if (codesource == null) {
 	    this.codesource = 
 		new CodeSource(null,
 			       (java.security.cert.Certificate[])null);
 	} else {
 	    this.codesource = codesource;
 	}
 	this.factoryKey = key;
 	this.cache  = null;
 	this.pcID = pcID;
 	this.protoPerms = perms;
 	if (perms != null && perms.length>0) {
 	    this.classes = new Class[perms.length];
 	    for (int i=0; i<perms.length; i++) {
 		this.classes[i] = perms[i].getClass();
 	    }
 	} else {
 	    this.classes = null;
 	}
 	this.name = name;
 	this.epoch = 1;
 	this.loading = false;
 	this.rwLock = new ReentrantReadWriteLock(true);
 	this.rLock = rwLock.readLock();
 	this.wLock = rwLock.writeLock();
    
Methods Summary
private booleancheckCache(java.security.Permission p, com.sun.enterprise.security.CachedPermissionImpl.Epoch e)


 	// test-and-set to guard critical section
 	rLock.lock();
	try {
	    if (loading) {
		return false;
	    } else if (cache != null) {
		// cache is loaded and readlock is held
		// check permission and return
		return checkLoadedCache(p,e);
	    }
	} finally {
	    rLock.unlock();
	}

	wLock.lock();
	if (loading) {
	    // another thread started the load
	    // release the writelock and return
	    wLock.unlock();
	    return false;
	} else if (cache != null) {
	    // another thread loaded the cache 
	    // get readlock inside writelock. 
	    // check permission and return
	    rLock.lock();
	    wLock.unlock();
	    try {
		// cache is loaded and readlock is held
		// check permission and return
		return checkLoadedCache(p,e);
	    } finally {
		rLock.unlock();
	    }
	} else {
	    // set the load indicators so that readers will 
	    // bypass the cache until it is loaded
	    // release the writelock and return
	    cache = null;
	    loading = true;
	    wLock.unlock();
	}
	
	// cache will be null if we proceed past this point
	// NO LOCKS ARE HELD AT THIS POINT

	Permissions nextCache = new Permissions();

	boolean setPc = false;
	String oldpcID = null;
	try {
	    oldpcID = PolicyContext.getContextID();
	    if (this.pcID != oldpcID && 
		(this.pcID == null || !this.pcID.equals(oldpcID))) { 
		setPc = true;
	    }
	} catch (Exception ex) {
	    _logger.log(Level.SEVERE,"JACC: Unexpected security exception on access decision"
			, ex);
	    return false;
	}

	PermissionCollection pc = null;
	try {
	    if (setPc) {
		setPolicyContextID(this.pcID);
	    }
		
	    pc = this.policy.getPermissions(this.codesource);
	} catch(Exception ex) {
	    _logger.log(Level.SEVERE,"JACC: Unexpected security exception on access decision"
			, ex);
	    return false;
	} finally {
	    if (setPc) {
		try {
		    setPolicyContextID(oldpcID);
		} catch(Exception ex) {
		    _logger.log(Level.SEVERE,"JACC: Unexpected security exception on access decision", ex);
		    return false;
		}
	    }
	}

 	// force resolution of unresolved permissions
 	// so that we can filter out all but the permissions
 	// that are supposed to be in the cache.
 
 	resolvePermissions(pc,p);

	Enumeration granted = pc.elements();
	while (granted.hasMoreElements()) {
	    Permission i = (Permission) granted.nextElement();
	    if (i.equals(allPermission)) {
		nextCache.add(i);
	    } else {
		boolean classMatch = true;
		if (this.classes != null) {
		    classMatch = false;
		    Class iClazz = i.getClass();
		    for (int j=0; j<this.classes.length; j++) {
			if (this.classes[j].equals(iClazz)) {
			    classMatch = true;
			    break;
			}
		    }
		}
		if (classMatch) {
		    if (this.name != null) {
			String name = i.getName();
			if (name != null && this.name.equals(name)) {
			    nextCache.add(i);
			}
		    } else {
			nextCache.add(i);
		    }
		}
	    }
	}

	// get the writelock to mark cache as loaded
 	wLock.lock();
	cache = nextCache;
	loading = false;
	try {
	    // get readlock inside writelock. 
	    rLock.lock();
	    wLock.unlock();
	    // cache is loaded and readlock is held
	    // check permission and return
	    return checkLoadedCache(p,e);
	} finally {
	    rLock.unlock();
	}
    
private booleancheckLoadedCache(java.security.Permission p, com.sun.enterprise.security.CachedPermissionImpl.Epoch e)

	if (e == null) {
	    return cache.implies(p);
	} else {
	    if (e.epoch != epoch) {
		e.granted = cache.implies(p);
		e.epoch = epoch;
	    }
	    return e.granted;
	}
    
public booleancheckPermission(java.security.Permission p, com.sun.enterprise.security.CachedPermissionImpl.Epoch e)

 	return checkCache(p,e);
    
public booleancheckPermission(java.security.Permission p)

 	return checkCache(p,null);
    
public java.lang.IntegergetFactoryKey()

	return this.factoryKey;
    
public synchronized voidreset()

 	wLock.lock();
 	try {
  	    if (cache != null) {
  		// since cache is non-null, we know we are NOT loading
  		// setting cache to null will force a (re)load
		cache = null;
		epoch = (epoch + 1 == 0) ? 1 : epoch + 1;
	    }
	} finally {
 	    wLock.unlock();
  	}
    
private voidresolvePermissions(java.security.PermissionCollection pc, java.security.Permission p)

 	// each call to implies will resolve permissions of the
 	// argument permission type
 	if (this.protoPerms != null && this.protoPerms.length > 0) {
 	    for (int i=0; i<this.protoPerms.length; i++) {	    
 		pc.implies(this.protoPerms[i]);
  	    }
 	} else {
 	    pc.implies(p);
 	}
    
private voidsetPolicyContextID(java.lang.String newID)

        AppservAccessController.doPrivileged(new PrivilegedExceptionAction(){
            public java.lang.Object run() throws Exception{
                PolicyContext.setContextID(newID);
                return null;
            }
        });