You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@river.apache.org by pe...@apache.org on 2011/12/31 01:13:02 UTC
svn commit: r1225993 [2/2] - in /river/jtsk/skunk/peterConcurrentPolicy:
qa/harness/policy/ qa/src/com/sun/jini/qa/harness/
qa/src/com/sun/jini/test/impl/start/ qa/src/com/sun/jini/test/resources/
qa/src/com/sun/jini/test/spec/config/configurationfile/...
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java?rev=1225993&r1=1225992&r2=1225993&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java Sat Dec 31 00:13:00 2011
@@ -21,6 +21,7 @@ package net.jini.security.policy;
import java.io.IOException;
import java.lang.ref.Reference;
import java.rmi.RemoteException;
+import java.security.PrivilegedActionException;
import org.apache.river.api.security.DelegateSecurityManager;
import java.security.AccessController;
import java.security.AllPermission;
@@ -32,6 +33,7 @@ import java.security.Permissions;
import java.security.Policy;
import java.security.Principal;
import java.security.PrivilegedAction;
+import java.security.PrivilegedExceptionAction;
import java.security.ProtectionDomain;
import java.security.Security;
import java.util.ArrayList;
@@ -43,15 +45,22 @@ import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
+import java.util.TreeSet;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import net.jini.security.GrantPermission;
+import net.jini.security.PermissionComparator;
import org.apache.river.api.security.PermissionGrant;
import org.apache.river.api.security.PermissionGrantBuilder;
import org.apache.river.api.security.policy.RemotePolicy;
-import org.apache.river.api.security.RevokePermission;
+import org.apache.river.api.security.PolicyPermission;
import org.apache.river.api.security.policy.RevokeableDynamicPolicy;
import org.apache.river.impl.security.policy.util.PolicyUtils;
import org.apache.river.impl.util.CollectionsConcurrent;
@@ -162,8 +171,8 @@ public class DynamicPolicyProvider exten
private static final String basePolicyClassProperty =
"net.jini.security.policy.DynamicPolicyProvider.basePolicyClass";
private static final String defaultBasePolicyClass =
-// "net.jini.security.policy.ConcurrentPolicyFile";
- "net.jini.security.policy.PolicyFileProvider";
+ "net.jini.security.policy.ConcurrentPolicyFile";
+// "net.jini.security.policy.PolicyFileProvider";
private static final ProtectionDomain sysDomain =
AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
@@ -186,15 +195,14 @@ public class DynamicPolicyProvider exten
private volatile PermissionGrant[] remotePolicyGrants; // Write protected by grantLock.
/* This lock protects write updating of remotePolicyGrants reference */
private final Object grantLock;
- private final Policy basePolicy; // final looks after its own sync
+ private final Policy basePolicy; // refresh protected by transactionWriteLock
/* cache of ProtectionDomain and their Permissions */
- private final ConcurrentMap<ProtectionDomain, PermissionCollection> cache;
- /* A cache of Permission's for each PermissionGrant, this avoids a mutating
- * PermissionGrant implementation from escallating permissions, this
- * cache should be updated when receiving PermissionGrant and checking
- * the callers Permissions. The current implementation uses a weak identity
- * map that cleans itself. */
- private final ConcurrentMap<PermissionGrant, Permission[]> grantCache;
+ private final ConcurrentMap<ProtectionDomain, PermissionCollection> cache; // protected by transactionWriteLock
+ /* A transaction ID to avoid updating the cache with old information
+ * after it has been cleared */
+ private final Lock transactionWriteLock; // Lock to protect cache clear and transactionID write.
+ private final Lock transactionReadLock; // Lock to protect cache put and transactionID reads.
+ private int transactionID; // Protected by transaction locks
// DynamicPolicy grant's for Proxy's.
private final Collection<PermissionGrant> dynamicPolicyGrants;
private final boolean basePolicyIsDynamic; // Don't use cache if true.
@@ -206,6 +214,7 @@ public class DynamicPolicyProvider exten
// avoid dead locks due to bug 4911907
private final Guard revokePermission;
+ private final Permission implementsPermissionGrant;
private final Guard protectionDomainPermission;
/**
@@ -275,12 +284,10 @@ public class DynamicPolicyProvider exten
ConcurrentMap<Referrer<ProtectionDomain>, Referrer<PermissionCollection>> internal
= new ConcurrentHashMap<Referrer<ProtectionDomain>,Referrer<PermissionCollection>>(120);
cache = RC.concurrentMap(internal, Ref.WEAK_IDENTITY, Ref.SOFT);
- ConcurrentMap<Referrer<PermissionGrant>, Referrer<Permission[]>> gInternal
- = new ConcurrentHashMap<Referrer<PermissionGrant>, Referrer<Permission[]>>(60);
- grantCache = RC.concurrentMap(gInternal, Ref.WEAK, Ref.STRONG);
loggable = logger.isLoggable(Level.FINEST);
grantLock = new Object();
- revokePermission = new RevokePermission();
+ revokePermission = new PolicyPermission("REVOKE");
+ implementsPermissionGrant = new PolicyPermission("implementPermissionGrant");
protectionDomainPermission = new RuntimePermission("getProtectionDomain");
if (basePolicy instanceof DynamicPolicy) {
DynamicPolicy dp = (DynamicPolicy) basePolicy;
@@ -300,6 +307,10 @@ public class DynamicPolicyProvider exten
} else {
basePolicyIsRemote = false;
}
+ transactionID = 0;
+ ReadWriteLock rwl = new ReentrantReadWriteLock();
+ transactionWriteLock = rwl.writeLock();
+ transactionReadLock = rwl.readLock();
ensureDependenciesResolved();
}
@@ -320,12 +331,10 @@ public class DynamicPolicyProvider exten
ConcurrentMap<Referrer<ProtectionDomain>, Referrer<PermissionCollection>> internal
= new ConcurrentHashMap<Referrer<ProtectionDomain>,Referrer<PermissionCollection>>(120);
cache = RC.concurrentMap(internal, Ref.WEAK_IDENTITY, Ref.SOFT);
- ConcurrentMap<Referrer<PermissionGrant>, Referrer<Permission[]>> gInternal
- = new ConcurrentHashMap<Referrer<PermissionGrant>, Referrer<Permission[]>>(60);
- grantCache = RC.concurrentMap(gInternal, Ref.WEAK, Ref.STRONG);
loggable = logger.isLoggable(Level.FINEST);
grantLock = new Object();
- revokePermission = new RevokePermission();
+ revokePermission = new PolicyPermission("REVOKE");
+ implementsPermissionGrant = new PolicyPermission("implementPermissionGrant");
protectionDomainPermission = new RuntimePermission("getProtectionDomain");
if (basePolicy instanceof DynamicPolicy) {
DynamicPolicy dp = (DynamicPolicy) basePolicy;
@@ -345,6 +354,10 @@ public class DynamicPolicyProvider exten
} else {
basePolicyIsRemote = false;
}
+ transactionID = 0;
+ ReadWriteLock rwl = new ReentrantReadWriteLock();
+ transactionWriteLock = rwl.writeLock();
+ transactionReadLock = rwl.readLock();
ensureDependenciesResolved();
}
@@ -434,11 +447,11 @@ Put the policy providers and all referen
PermissionGrant p = dynamicGrants.next();
if ( p.implies(codesource, null) ){
// Only use the trusted grantCache.
- Permission[] perm = grantCache.get(p);
- int s = perm.length;
- for ( int j = 0; j < s; j++){
- permissions.add(perm[j]);
- }
+ Collection<Permission> perms = p.getPermissions();
+ Iterator<Permission> it = perms.iterator();
+ while (it.hasNext()){
+ permissions.add(it.next());
+ }
}
}
return permissions;
@@ -464,22 +477,16 @@ Put the policy providers and all referen
* TODO: Remove PolicyPermission's
*/
PermissionCollection pc = basePolicy.getPermissions(domain);
- PermissionCollection permissions = new Permissions();
- Enumeration<Permission> enu = pc.elements();
- while (enu.hasMoreElements()){
- permissions.add(enu.nextElement());
- }
+ pc = PolicyUtils.asConcurrent(pc);
PermissionGrant [] grantsRefCopy = remotePolicyGrants; // Interim updates not seen.
int l = grantsRefCopy.length;
for ( int i = 0; i < l; i++ ){
if ( grantsRefCopy[i].implies(domain) ){
- // Only use the trusted grantCache.
- Permission[] perm = grantCache.get(grantsRefCopy[i]);
- int s = perm.length;
- for ( int j = 0; j < s; j++){
- PolicyPermission pp = new PolicyPermission(perm[j]);
- permissions.add(pp);
- }
+ Collection<Permission> perms = grantsRefCopy[i].getPermissions();
+ Iterator<Permission> it = perms.iterator();
+ while (it.hasNext()){
+ pc.add(it.next());
+ }
}
}
Iterator<PermissionGrant> dynamicGrants = dynamicPolicyGrants.iterator();
@@ -487,20 +494,14 @@ Put the policy providers and all referen
PermissionGrant p = dynamicGrants.next();
if ( p.implies(domain) ){
// Only use the trusted grantCache.
- Permission[] perm = grantCache.get(p);
- int s = perm.length;
- for ( int j = 0; j < s; j++){
- Permission pp = null;
- if (revokeable) {
- pp = new PolicyPermission(perm[j]);
- }else{
- pp = perm[j];
- }
- permissions.add(pp);
- }
+ Collection<Permission> perms = p.getPermissions();
+ Iterator<Permission> it = perms.iterator();
+ while (it.hasNext()){
+ pc.add(it.next());
+ }
}
}
- return permissions;
+ return pc;
}
/* River-26 Mark Brouwer suggested making UmbrellaPermission's expandable
@@ -518,9 +519,12 @@ Put the policy providers and all referen
}
if (permission == null) throw new NullPointerException("permission not allowed to be null");
// First check our cache if the basePolicy is not dynamic.
+
PermissionCollection pc = domain != null? cache.get(domain): null;
if ( pc != null ) {
- if (pc.implies(permission)) return true;
+ /* Out of date cache is cleared and only updated with the latest
+ * grants don't bother retrieving it again */
+ if ( pc.implies(permission) ) return true;
}
Thread thread = Thread.currentThread();
if (thread.isInterrupted()) return false;
@@ -529,7 +533,16 @@ Put the policy providers and all referen
* while another Permission within that collection is already
* resolved, the Enumeration will cause a ConcurrentModificationException.
*/
- PermissionCollection bpc = basePolicy.getPermissions(domain);
+ int currentTransactionID;
+ PermissionCollection bpc = null;
+ transactionReadLock.lock();
+ try {
+ currentTransactionID = transactionID;
+ bpc = basePolicy.getPermissions(domain);
+ }finally{
+ transactionReadLock.unlock();
+ }
+
/* Be mindful of static Permissions held by the
* ProtectionDomain, a Permission may be implied by the
* the combination of Permission's in the ProtectionDomain and
@@ -556,31 +569,17 @@ Put the policy providers and all referen
pc = PolicyUtils.asConcurrent(bpc);
/* Don't place it in the cache half finished or check it yet since
* mutations are blocking */
-// PermissionCollection existed =
-// domain != null ? cache.putIfAbsent(domain, pc): null;
-// if ( existed != null ){
-// pc = existed;
-// }
-// expandUmbrella(pc); // We need to avoid using PolicyFileProvider as grants from it are not revokable.
-// if ( pc.implies(permission)) return true;
-
- // Once we get to here pc is definitely not null and we have the
- // copy referenced in the cache.
-// if (loggable){
-// logger.log(Level.FINEST, domain + permission.toString() +
-// ": Base policy is not dynamic and returned false" );
-// }
- // If the base policy doesn't imply a Permission then we should check for dynamic grants
- Collection<Permission> dynamicallyGrantedPermissions = new HashSet<Permission>(120);
- PermissionGrant[] grantsRefCopy = remotePolicyGrants; // In case the grants volatile reference is updated.
-
+ PermissionGrant[] grantsRefCopy = remotePolicyGrants; // In case the grants volatile reference is updated.
if (thread.isInterrupted()) return false;
int l = grantsRefCopy.length;
for ( int i = 0; i < l; i++){
if (grantsRefCopy[i].implies(domain)) {
// We only trust grantCache in case of mutable PermissionGrant.
- Permission[] perms = grantCache.get(grantsRefCopy[i]);
- dynamicallyGrantedPermissions.addAll(Arrays.asList(perms));
+ Collection<Permission> perms = grantsRefCopy[i].getPermissions();
+ Iterator<Permission> it = perms.iterator();
+ while (it.hasNext()){
+ pc.add(it.next());
+ }
}
}
if (thread.isInterrupted()) return false;
@@ -588,36 +587,27 @@ Put the policy providers and all referen
while (grants.hasNext()){
PermissionGrant g = grants.next();
if (g.implies(domain)){
- dynamicallyGrantedPermissions.addAll(g.getPermissions());
+ Collection<Permission> perms = g.getPermissions();
+ Iterator<Permission> it = perms.iterator();
+ while (it.hasNext()){
+ pc.add(it.next());
+ }
}
}
if (thread.isInterrupted()) return false;
-// if (loggable) {
-// logger.log(Level.FINEST, "Grants: " + dynamicallyGrantedPermissions.toString());
-// }
-// if (dynamicallyGrantedPermissions.isEmpty()) {
-// // We have no dynamic grants
-// return false;
-// }
- Iterator<Permission> dgpi = dynamicallyGrantedPermissions.iterator();
- while (dgpi.hasNext()){
- pc.add(dgpi.next());
- }
- if (thread.isInterrupted()) return false;
- // If we get refreshed the cache could be empty, which is more pedantic
- // however the result may still be true so we'll return it anyway.
-// if (loggable) {
-// logger.log(Level.FINEST, "PermissionCollection: " + pc.toString());
-// }
// We have added dynamic grants, lets expand any UmbrellaGrant's
expandUmbrella(pc);
- if ( pc.implies(permission) ){
- // The cache is replaced rather than updated, to avoid umbrella grants
- // causing GrantPermission recursion.
- if (domain != null ) cache.replace(domain, pc);
- return true;
+ if (domain != null) {
+ if (transactionReadLock.tryLock()){
+ try {
+ if (transactionID == currentTransactionID)
+ cache.putIfAbsent(domain, pc);
+ }finally {
+ transactionReadLock.unlock();
+ }
+ }
}
- return false;
+ return pc.implies(permission);
}
/**
@@ -630,9 +620,15 @@ Put the policy providers and all referen
*
*/
+ @SuppressWarnings("unchecked")
public void refresh() {
- cache.clear();
- basePolicy.refresh();
+ transactionWriteLock.lock();
+ try {
+ basePolicy.refresh();
+ transactionID++;
+ }finally{
+ transactionWriteLock.unlock();
+ }
// Clean up any void dynamic grants.
Collection<PermissionGrant> remove = new ArrayList<PermissionGrant>(40);
Iterator<PermissionGrant> i = dynamicPolicyGrants.iterator();
@@ -643,15 +639,24 @@ Put the policy providers and all referen
}
}
dynamicPolicyGrants.removeAll(remove);
+ // Increment transaction ID after cache clear,
+ transactionWriteLock.lock();
+ try {
+ cache.clear();
+ transactionID++;
+ }finally{
+ transactionWriteLock.unlock();
+ }
// Don't bother removing void from the remotePolicy, it get's replaced anyway.
// Policy file based grant's don't become void, only dynamic grant's
// to ProtectionDomain or ClassLoader.
- SecurityManager sm = System.getSecurityManager();
+ final SecurityManager sm = System.getSecurityManager();
if (sm != null){
if (sm instanceof DelegateSecurityManager){
((DelegateSecurityManager) sm).clearFromCache(null);
}
}
+
}
public boolean grantSupported() {
@@ -684,10 +689,16 @@ Put the policy providers and all referen
.permissions(permissions)
.context(PermissionGrantBuilder.CLASSLOADER)
.build();
- // We built this grant it's safe to trust.
- grantCache.put(pe, permissions); // Replace any existing too.
// This grant is new, in the grantCache and we trust it.
dynamicPolicyGrants.add(pe);
+ // Increment transaction ID after cache clear,
+ transactionWriteLock.lock();
+ try {
+ cache.clear();
+ transactionID++;
+ }finally{
+ transactionWriteLock.unlock();
+ }
// if (loggable){
// logger.log(Level.FINEST, "Granting: {0}", pe.toString());
// }
@@ -745,8 +756,18 @@ Put the policy providers and all referen
grants.remove();
}
}
- // Unfortunately this is quite expensive, but we don't know which ProtectionDomains a ClassLoader references.
- cache.clear();
+ // Unfortunately we don't know which
+ // ProtectionDomains a ClassLoader references, so we must clear the
+ // cache.
+ // Increment transaction ID after cache clear.
+ transactionWriteLock.lock();
+ try {
+ cache.clear();
+ transactionID++;
+ }finally{
+ transactionWriteLock.unlock();
+ }
+
SecurityManager sm = System.getSecurityManager();
if (sm instanceof DelegateSecurityManager) {
((DelegateSecurityManager) sm).clearFromCache(removed);
@@ -832,7 +853,33 @@ Put the policy providers and all referen
// changes between now and gaining the lock, only the length of the
// HashSet is potentially not optimal, keeping the HashSet creation
// outside of the lock reduces the lock held duration.
- checkNullElements(grants);
+ Set<ProtectionDomain> domains = new HashSet<ProtectionDomain>();
+ int l = grants.length;
+ for (int i = 0; i < l; i++ ){
+ if (grants[i] == null ) throw new NullPointerException("null PermissionGrant prohibited");
+ // This causes a ProtectionDomain security check.
+ final Class c = grants[i].getClass();
+ List<ProtectionDomain> doms = AccessController.doPrivileged(
+ new PrivilegedAction<List<ProtectionDomain>>() {
+ public List<ProtectionDomain> run() {
+ Class[] classes = c.getDeclaredClasses();
+ List<ProtectionDomain> domains = new ArrayList<ProtectionDomain>();
+ int l = classes.length;
+ for ( int i = 0; i < l; i++ ){
+ domains.add(classes[i].getProtectionDomain());
+ }
+ return domains;
+ }
+ });
+ domains.addAll(doms);
+ }
+ Iterator<ProtectionDomain> it = domains.iterator();
+ while (it.hasNext()){
+ if ( ! it.next().implies(implementsPermissionGrant)) {
+ throw new SecurityException("Missing permission: "
+ + implementsPermissionGrant.toString());
+ }
+ }
HashSet<PermissionGrant> holder
= new HashSet<PermissionGrant>(grants.length);
holder.addAll(Arrays.asList(grants));
@@ -843,7 +890,13 @@ Put the policy providers and all referen
PermissionGrant[] updated = new PermissionGrant[holder.size()];
remotePolicyGrants = holder.toArray(updated);
}
- cache.clear();
+ transactionWriteLock.lock();
+ try {
+ cache.clear();
+ transactionID++;
+ }finally{
+ transactionWriteLock.unlock();
+ }
Collection<PermissionGrant> oldGrants = new HashSet<PermissionGrant>(old.length);
oldGrants.addAll(Arrays.asList(old));
oldGrants.removeAll(holder);
@@ -861,52 +914,5 @@ Put the policy providers and all referen
}
// oldGrants now only has the grants which have been removed.
}
-
- /*
- * The sole purpose of this implementation is to make Dynamic permissions
- * printable for debugging from a ProtectionDomain without their contained
- * permissions becoming merged in the static ProtectionDomain permissions.
- */
- private static class PolicyPermission extends Permission {
- private static final long serialVersionUID = 1L;
-
- private final Permission perm;
-
- PolicyPermission(Permission p){
- super("Dynamic Policy");
- perm = p;
- }
-
- @Override
- public boolean implies(Permission permission) {
- return equals(permission);
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj == this) return true;
- if (obj instanceof PolicyPermission &&
- this.perm.equals(((PolicyPermission) obj).perm)) return true;
- return false;
- }
-
- @Override
- public int hashCode() {
- int hash = 7;
- hash = 31 * hash + (this.perm != null ? this.perm.hashCode() : 0);
- return hash;
- }
-
- @Override
- public String toString(){
- return perm.toString();
- }
-
- @Override
- public String getActions() {
- return "";
- }
-
- }
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java?rev=1225993&r1=1225992&r2=1225993&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java Sat Dec 31 00:13:00 2011
@@ -18,14 +18,15 @@
package org.apache.river.api.security;
-import java.net.SocketPermission;
import java.security.AccessControlContext;
import java.security.AccessController;
+import java.security.AllPermission;
import java.security.DomainCombiner;
import java.security.Guard;
import java.security.Permission;
import java.security.PrivilegedAction;
import java.security.ProtectionDomain;
+import java.security.SecurityPermission;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
@@ -40,11 +41,9 @@ import java.util.concurrent.ConcurrentMa
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
-import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.logging.Level;
@@ -77,9 +76,13 @@ extends SecurityManager implements Deleg
private final Action action;
private final ExecutorService executor;
private final Comparator<Referrer<Permission>> permCompare;
+ private final AccessControlContext SMContext;
public DelegateCombinerSecurityManager(){
super();
+ // Get context before this becomes a SecurityManager.
+ // super() checked the permission to create a SecurityManager.
+ SMContext = AccessController.getContext();
dc = new DelegateDomainCombiner();
ConcurrentMap<Referrer<AccessControlContext>,
Referrer<AccessControlContext>> internal =
@@ -90,7 +93,7 @@ extends SecurityManager implements Deleg
= new ConcurrentHashMap<Referrer<AccessControlContext>,
Referrer<Set<Permission>>>(100);
checked = RC.concurrentMap(refmap, Ref.SOFT, Ref.STRONG);
- g = new RevokePermission();
+ g = new SecurityPermission("getPolicy");
action = new Action();
// Make this a tunable property.
double blocking_coefficient = 0.6; // 0 CPU intensive to 0.9 IO intensive
@@ -108,12 +111,19 @@ extends SecurityManager implements Deleg
TimeUnit.SECONDS, new SynchronousQueue<Runnable>(),
new ThreadPoolExecutor.CallerRunsPolicy());
permCompare = RC.comparator(new PermissionComparator());
+ // Refresh the policy, in case it hasn't parsed all policy files.
+ java.security.Policy.getPolicy().refresh();
+ }
+
+ public void checkPermission(Permission perm) throws SecurityException {
+ checkPermission(perm, AccessController.getContext());
}
@Override
public void checkPermission(Permission perm, Object context) throws SecurityException {
if (!(context instanceof AccessControlContext)) throw new SecurityException();
if (perm == null ) throw new NullPointerException("Permission Collection null");
+ if (SMContext.equals(context)) return; // prevents endless loop in debug.
AccessControlContext executionContext = (AccessControlContext) context;
// Checks if Permission has already been checked for this context.
Set<Permission> checkedPerms = checked.get(executionContext);
@@ -125,43 +135,49 @@ extends SecurityManager implements Deleg
if (existed != null) checkedPerms = existed;
}
if (checkedPerms.contains(perm)) return; // don't need to check again.
- if (perm instanceof DelegatePermission) {
- // This is an expensive operation, so we cache the created AccessControlContext.
- AccessControlContext delegateContext = contextCache.get(executionContext);
- if (delegateContext == null) {
- final AccessControlContext finalExecutionContext = executionContext;
- // Create a new AccessControlContext with the DelegateDomainCombiner
- // we don't need to preserve the Subject accross the call
- // we have sufficient privilege.
- delegateContext = AccessController.doPrivileged(
- new PrivilegedAction<AccessControlContext>(){
- public AccessControlContext run() {
- return new AccessControlContext(finalExecutionContext, dc);
- }
+ // This is an expensive operation, so we cache the created AccessControlContext.
+ AccessControlContext delegateContext = contextCache.get(executionContext);
+ if (delegateContext == null) {
+ final AccessControlContext finalExecutionContext = executionContext;
+ // Create a new AccessControlContext with the DelegateDomainCombiner
+ // we don't need to preserve the Subject accross the call
+ // we have sufficient privilege.
+ delegateContext = AccessController.doPrivileged(
+ new PrivilegedAction<AccessControlContext>(){
+ public AccessControlContext run() {
+ return new AccessControlContext(finalExecutionContext, dc);
}
- );
- // Optimise the delegateContext, this runs the DelegateDomainCombiner
- // and returns the AccessControlContext.
- // This is a mutator method, the delegateContext returned
- // is actually the same object passed in, after it is
- // mutated, but just in case that changes in future we
- // return it.
- delegateContext = AccessController.doPrivileged(action, delegateContext);
- contextCache.putIfAbsent(executionContext, delegateContext);
- // Above putIfAbsent: It doesn't matter if it already existed,
- // the context we have is valid to perform a permissionCheck.
- }
- executionContext = delegateContext;
- }
+ }
+ );
+ // Optimise the delegateContext, this runs the DelegateDomainCombiner
+ // and returns the AccessControlContext.
+ // This is a mutator method, the delegateContext returned
+ // is actually the same object passed in, after it is
+ // mutated, but just in case that changes in future we
+ // return it.
+ delegateContext = AccessController.doPrivileged(action, delegateContext);
+ contextCache.putIfAbsent(executionContext, delegateContext);
+ // Above putIfAbsent: It doesn't matter if it already existed,
+ // the context we have is valid to perform a permissionCheck.
+ }
// Normal execution, same as SecurityManager.
- executionContext.checkPermission(perm);
+ delegateContext.checkPermission(perm);
/* It's ok to cache SocketPermission if we use a comparator */
// If we get to here, no exceptions were thrown, we have permission.
// Don't cache SocketPermission.
// if (perm instanceof SocketPermission) return;
checkedPerms.add(perm);
}
-
+
+ /**
+ * This method is intended to be called only by a Policy.
+ *
+ * To clear the cache of checked Permissions requires the following Permission:
+ * java.security.SecurityPermission("getPolicy");
+ *
+ * @param perms
+ * @throws SecurityException
+ */
public void clearFromCache(Set<Permission> perms) throws SecurityException {
// This is a slow operation, with the benefit
// of faster security checks, which occur far more often.
@@ -294,10 +310,11 @@ extends SecurityManager implements Deleg
// interrupt status swallowed.
boolean externalInterrupt = false;
if (!terminated.get()) externalInterrupt = true;
-
- Iterator<Future<Boolean>> it = resultList.iterator();
- while (it.hasNext()){
- it.next().cancel(true);
+ if ( resultList != null ){ // could be interrupted before executor invoking.
+ Iterator<Future<Boolean>> it = resultList.iterator();
+ while (it.hasNext()){
+ it.next().cancel(true);
+ }
}
Logger.getLogger(DelegateCombinerSecurityManager.class.getName()).log(Level.FINEST, null, ex);
// Task interruption is normal, it just means one task returned false.
Copied: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PolicyPermission.java (from r1222835, river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/RevokePermission.java)
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PolicyPermission.java?p2=river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PolicyPermission.java&p1=river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/RevokePermission.java&r1=1222835&r2=1225993&rev=1225993&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/RevokePermission.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PolicyPermission.java Sat Dec 31 00:13:00 2011
@@ -5,49 +5,26 @@
package org.apache.river.api.security;
-import java.security.Permission;
+import java.security.BasicPermission;
/**
- * <p>RevokePermission allows for a permission to be revoked at runtime provided
- * it has been dynamically granted.<p>
- *
- * A RevokePermission cannot dynamically grant itself a permission.<p>
- *
- * A domain with revoke permission can not revoke a RevokePermission
- * unless it has been granted dynamically. </p>
- *
- * -- seems logical.
+ * <p>A "revoke" or "REVOKE" PolicyPermission is allows updating a
+ * RemotePolicy or remove Dynamically granted permission from a
+ * RevokeableDynamicPolicy.</p>
*
+ * <p>A "implementPermissionGrant" PolicyPermission allows a class to implement
+ * org.apache.river.api.security.PermissionGrant interface and use it to
+ * update a RemotePolicy. This is not a permission to grant lightly, since
+ * a poor implementation could destabilise a policy or worse allow the caller
+ * to grant AllPermission anyone using mutation.</p>
*
* @author Peter Firmstone
*/
-public class RevokePermission extends Permission {
+public class PolicyPermission extends BasicPermission {
private static final long serialVersionUID = 1L;
- public RevokePermission(){
- super("");
+ public PolicyPermission(String name){
+ super(name);
}
- @Override
- public boolean implies(Permission permission) {
- if ( !(permission instanceof RevokePermission)) return false;
- if ( permission.getClass() != this.getClass()) return false;
- return true;
- }
-
- @Override
- public boolean equals(Object obj) {
- if (obj instanceof RevokePermission) return true;
- return false;
- }
-
- @Override
- public int hashCode() {
- return RevokePermission.class.hashCode();
- }
-
- @Override
- public String getActions() {
- return "";
- }
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/Messages.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/Messages.java?rev=1225993&r1=1225992&r2=1225993&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/Messages.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/Messages.java Sat Dec 31 00:13:00 2011
@@ -242,7 +242,7 @@ public class Messages {
// Attempt to load the messages.
try {
bundle = setLocale(Locale.getDefault(),
- "org.apache.river.security.policy.util.messages"); //$NON-NLS-1$
+ "org.apache.river.impl.security.policy.util.messages"); //$NON-NLS-1$
} catch (Throwable e) {
e.printStackTrace();
}
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractReferenceComparator.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractReferenceComparator.java?rev=1225993&r1=1225992&r2=1225993&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractReferenceComparator.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/AbstractReferenceComparator.java Sat Dec 31 00:13:00 2011
@@ -31,8 +31,33 @@ abstract class AbstractReferenceComparat
AbstractReferenceComparator() {
}
+ /**
+ * This is implemented such that if either Referrer contains a null
+ * referent, the comparison is only made using Referrer's, this may
+ * have a different natural order, than the comparator provided, however
+ * equals will always return 0, this is important to correctly remove
+ * a Referrer once its referent has been collected.
+ *
+ * The following tests give this a good workout:
+ *
+ * com/sun/jini/test/impl/joinmanager/ZRegisterStorm.td
+ * com/sun/jini/test/spec/renewalmanager/EventTest.td
+ *
+ * @param o1
+ * @param o2
+ * @return
+ */
public int compare(Referrer<T> o1, Referrer<T> o2) {
- return get().compare(o1 != null ? o1.get() : null, o2 != null ? o2.get() : null);
+ if (o1 == o2) return 0;
+ T t1 = o1.get();
+ T t2 = o2.get();
+ if ( t1 != null && t2 != null) return get().compare(t1, t2);
+ int hash1 = o1.hashCode();
+ int hash2 = o2.hashCode();
+ if (hash1 < hash2) return -1;
+ if (hash1 > hash2) return 1;
+ if (o1.equals(o2)) return 0;
+ return -1;
}
@Override
Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java?rev=1225993&r1=1225992&r2=1225993&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceFactory.java Sat Dec 31 00:13:00 2011
@@ -39,6 +39,7 @@ class ReferenceFactory<T> {
private ReferenceFactory(){}
static <T> Referrer<T> create(T t, ReferenceQueue<? super T> queue, Ref type ){
+ if (t == null) throw new NullPointerException("Reference collections cannot contain null");
switch (type){
case WEAK_IDENTITY:
return new ReferrerWrapper<T>(new WeakIdentityReferenceKey<T>(t, queue));
@@ -78,6 +79,7 @@ class ReferenceFactory<T> {
* @return
*/
static <T> Referrer<T> singleUseForLookup(T t, Ref type){
+ if (t == null) throw new NullPointerException("Reference collections cannot contain null");
switch (type){
case WEAK_IDENTITY:
return new TempIdentityReferrer<T>(t);