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 2010/08/14 06:39:27 UTC
svn commit: r985427 - in /incubator/river/jtsk/trunk/src:
net/jini/security/policy/ org/apache/river/api/security/
org/apache/river/imp/security/policy/cdc/
org/apache/river/imp/security/policy/se/
Author: peter_firmstone
Date: Sat Aug 14 04:39:26 2010
New Revision: 985427
URL: http://svn.apache.org/viewvc?rev=985427&view=rev
Log:
ExecutionContextManager implementation for the RevokableDynamicPolicy, please review.
Added:
incubator/river/jtsk/trunk/src/org/apache/river/api/security/Reaper.java (with props)
incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/ECM.java (with props)
Removed:
incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/Controller.java
Modified:
incubator/river/jtsk/trunk/src/net/jini/security/policy/DynamicPolicyProvider.java
incubator/river/jtsk/trunk/src/org/apache/river/api/security/ExecutionContextManager.java
incubator/river/jtsk/trunk/src/org/apache/river/api/security/PermissionGrant.java
incubator/river/jtsk/trunk/src/org/apache/river/api/security/RevokeableDynamicPolicy.java
incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java
incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
Modified: incubator/river/jtsk/trunk/src/net/jini/security/policy/DynamicPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/net/jini/security/policy/DynamicPolicyProvider.java?rev=985427&r1=985426&r2=985427&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/net/jini/security/policy/DynamicPolicyProvider.java (original)
+++ incubator/river/jtsk/trunk/src/net/jini/security/policy/DynamicPolicyProvider.java Sat Aug 14 04:39:26 2010
@@ -325,7 +325,7 @@ public class DynamicPolicyProvider exten
return instance.getPermissionGrants();
}
- public ExecutionContextManager getExecutionContextManager(Permission p) {
- return instance.getExecutionContextManager(p);
+ public ExecutionContextManager getExecutionContextManager() {
+ return instance.getExecutionContextManager();
}
}
Modified: incubator/river/jtsk/trunk/src/org/apache/river/api/security/ExecutionContextManager.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/api/security/ExecutionContextManager.java?rev=985427&r1=985426&r2=985427&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/api/security/ExecutionContextManager.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/api/security/ExecutionContextManager.java Sat Aug 14 04:39:26 2010
@@ -28,14 +28,30 @@ import java.util.Set;
* </p><p>
* The ExecutionContextManager will only call
* AccessControlContext.checkPermission(Permission) once, for each context. This
- * ensures that checkPermission isn't called again until the context changes, or
+ * ensures checkPermission isn't re called, until the context changes, or
* the Permission checked by this ExecutionContextManager experiences a
- * revoke for any ProtectionDomain by the RevokeableDynamicPolicy.
+ * revoke for any ProtectionDomain via a RevokeableDynamicPolicy.
* </p><p>
- * A Runnable may be submitted to the ExecutionContextManager to be executed
+ * A Reaper may be submitted to the ExecutionContextManager to be executed
* when a Permission Revocation matching the stored Permission occurs.
* </p><p>
* Use of this class is not limited to Revokeable Permission's.
+ * </p><p>
+ * Typical usage:
+ * </p>
+ * <code>
+ * ecm.begin(reaper);
+ * try{
+ * ecm.checkPermission(permissionA);
+ * ecm.checkPermission(permissionB);
+ * // do something
+ * return;
+ * } finally {
+ * ecm.end();
+ * }
+ * </code>
+ * <p>
+ * When protecting method's, the method must return from the try block.
* </p>
* @author Peter Firmstone
* @see RevokeableDynamicPolicy
@@ -43,6 +59,32 @@ import java.util.Set;
* @see AccessControlContext
*/
public interface ExecutionContextManager {
+
+ /**
+ * <p>
+ * Marks the beginning of Management of the Execution context, of the
+ * AccessControlContext and submits a reaper to intercept and clean up
+ * in the event of a revocation during the execution of the try finally
+ * block. This method may be omitted if a Reaper is not required. The
+ * consequence of there being no reaper, is that a call in progress during
+ * revocation will return normally immediately after revocation has
+ * occurred, the permission will have been checked prior to revocation
+ * however and any further permission checks, if they have been revoked
+ * will throw an AccessControlException.
+ * <p></p>
+ * This links the current Thread to a Runnable
+ * Reaper. The checkPermission() call places the Thread and
+ * AccessControlContext into the execution cache.
+ * <p></p>
+ * The execution cache is used to monitor methods or protected blocks that
+ * must be intercepted
+ * </p>
+ * @param r - Reaper provided to clean up if Revocation occurs during
+ * the execution that follows this call, until the try block exits,
+ * the current thread is not interrupted, rather the reaper is expected
+ * to know what resources need to be closed.
+ */
+ void begin(Reaper r);
/**
* <p>
@@ -68,27 +110,37 @@ public interface ExecutionContextManager
* </p><p>
* ExecutionContextManager should be used sparingly, the more generic
* or widely applicable the Permission, the more efficient the
- * ExecutionContextManager is in memory usage terms.
- * </p><p>
- * This method also add's the current context to the current execution
- * cache, it is not removed from that cache until after the addAction
- * Runnable has been run, or accessControlExit() has been called.
+ * ExecutionContextManager is in memory usage terms. Clients using
+ * the ECM, should be careful to release references to their permission
+ * objects, used permission checks, since garbage collection is relied
+ * upon to clean up cached AccessControlContext's, conversely, the
+ * permission shouldn't be created in the checkPermission(permission) call,
+ * since this would cause the object to be created on every invocation
+ * and probably garbage collected between invocations.
+ * </p><p>
+ * This method also add's the current thread and context to the execution
+ * cache, it is not removed from that cache until after end()
+ * has been called.
* </p>
*
- * @throws java.security.AccessControlException
+ * @param p Permission to be checked, if result not already in cache.
+ * @throws java.security.AccessControlException
*/
- public void checkPermission() throws AccessControlException;
+ public void checkPermission(Permission p) throws AccessControlException;
/**
* <p>
* This method is to advise the ExecutionContextManager that the
* current method or protected region has returned, it must
* always follow the checkPermission() call, in response,
- * the ECM removes the current context from the execution context cache.
+ * the ECM removes the current context from the execution context cache
+ * and releases the reference to the Runnable reaper.
* </p><p>
* If the execution context is still in the cache at the time of
- * revocation, the Runnable added by addAction will be run only if
- * affected directly by the revocation. This is determined by
+ * revocation, the reaper will be run only if affected directly by the
+ * revocation, the thread may be asked to wait for a short period, to
+ * allow the determination to be made.
+ * Revocation applicability is determined by
* AccessControlContext.checkPermission(Permission p) where p is the
* Permission affected.
* </p><p>
@@ -96,44 +148,18 @@ public interface ExecutionContextManager
* which always executes in the event of an exception or normal return.
* </p>
* <code>
+ * ecm.begin(reaper);
* try{
- * ecm.checkPermission();
+ * ecm.checkPermission(permission);
* // do something
* return;
- * } catch (AccessControlException e) {
- * throw new SecurityException("Method blah caused an...", e);
* } finally {
- * ecm.accessControlExit();
+ * ecm.end();
* }
* </code>
* <p>
* This should not be confused with AccessController.doPrivileged blocks
* </p>
*/
- public void accessControlExit();
-
- /**
- * Get the Permission monitored by this ExecutionContextManager.
- * @return Permission monitored by the ExecutionContextManager
- */
- public Permission getPermission();
-
- /**
- * <p>
- * Action to be taken in event that the Permission monitored by this
- * ExecutionContextManager has experienced a revocation event. This
- * allows Sockets to be closed, or any clean up to occur or any other
- * task that must be performed to reset state.
- * </p><p>
- * This may not be the only action performed, since the same
- * ExecutionContextManager may be used by multiple clients, the Runnable
- * is only weakly referenced, garbage collection is relied upon for its
- * removal.
- * </p><p>
- * The implementer must have the Permission's required for
- * execution, no privileges are assigned.
- * </p>
- * @param r - Clean up task to be performed.
- */
- public void addAction(Runnable r);
-}
+ void end();
+}
\ No newline at end of file
Modified: incubator/river/jtsk/trunk/src/org/apache/river/api/security/PermissionGrant.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/api/security/PermissionGrant.java?rev=985427&r1=985426&r2=985427&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/api/security/PermissionGrant.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/api/security/PermissionGrant.java Sat Aug 14 04:39:26 2010
@@ -77,7 +77,7 @@ public interface PermissionGrant {
/**
* Returns an array of permissions defined by this PermissionGrant, array
- * may be null, but non null array must not contain any null elements.
+ * may be null, but array must not contain null elements.
* @return
*/
Permission[] getPermissions();
Added: incubator/river/jtsk/trunk/src/org/apache/river/api/security/Reaper.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/api/security/Reaper.java?rev=985427&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/api/security/Reaper.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/api/security/Reaper.java Sat Aug 14 04:39:26 2010
@@ -0,0 +1,30 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.river.api.security;
+
+/**
+ * A Reaper is used to clean up or alter execution.
+ * @author Peter Firmstone.
+ * @see ExecutionContextManager
+ */
+public interface Reaper extends Runnable {
+
+ void put(Thread t);
+
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/api/security/Reaper.java
------------------------------------------------------------------------------
svn:eol-style = native
Modified: incubator/river/jtsk/trunk/src/org/apache/river/api/security/RevokeableDynamicPolicy.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/api/security/RevokeableDynamicPolicy.java?rev=985427&r1=985426&r2=985427&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/api/security/RevokeableDynamicPolicy.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/api/security/RevokeableDynamicPolicy.java Sat Aug 14 04:39:26 2010
@@ -51,8 +51,9 @@ public interface RevokeableDynamicPolicy
* Revokes can only be performed synchronuously with other Revokes.
*
* @param grants
+ * @throws java.lang.Exception if revoke unsuccessful.
*/
- public void revoke(List<PermissionGrant> grants);
+ public void revoke(List<PermissionGrant> grants) throws Exception;
/**
* Get a List copy of the current PermissionGrant's in force.
* @return
@@ -84,7 +85,7 @@ public interface RevokeableDynamicPolicy
* @param p Permission the ExecutionContextManager will check.
* @return a new ExecutionContextManager instance.
*/
- public ExecutionContextManager getExecutionContextManager(Permission p);
+ public ExecutionContextManager getExecutionContextManager();
/**
*
* @return true if Revoke supported.
Modified: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java?rev=985427&r1=985426&r2=985427&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java Sat Aug 14 04:39:26 2010
@@ -583,7 +583,7 @@ public class DynamicPolicyProviderImpl e
throw new UnsupportedOperationException("Not supported.");
}
- public ExecutionContextManager getExecutionContextManager(Permission p) {
+ public ExecutionContextManager getExecutionContextManager() {
throw new UnsupportedOperationException("Not supported yet.");
}
}
Modified: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java?rev=985427&r1=985426&r2=985427&view=diff
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java (original)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java Sat Aug 14 04:39:26 2010
@@ -162,6 +162,7 @@ public class DynamicConcurrentPolicyProv
// private final WriteLock dwl;
// private final Set<Denied> denied;
// private volatile boolean checkDenied;
+ private final ECM execControlManager;
public DynamicConcurrentPolicyProvider(){
@@ -179,6 +180,7 @@ public class DynamicConcurrentPolicyProv
// denied = new HashSet<Denied>(30);
// checkDenied = false;
grantLock = new Object();
+ execControlManager = new ECM();
}
/**
@@ -529,7 +531,7 @@ public class DynamicConcurrentPolicyProv
}
}
- public void revoke(List<PermissionGrant> grants) {
+ public void revoke(List<PermissionGrant> grants) throws Exception {
if (initialized == false) throw new RuntimeException("Object not initialized");
if (basePolicyIsDynamic && revokeable){
RevokeableDynamicPolicy bp = (RevokeableDynamicPolicy) basePolicy;
@@ -537,7 +539,7 @@ public class DynamicConcurrentPolicyProv
return;
}
AccessController.checkPermission(new RevokePermission());
- HashSet<Class> removed = new HashSet<Class>();
+ HashSet<Permission> removed = new HashSet<Permission>();
List<Runnable> jobs = null;
HashSet<PermissionGrant> holder = new HashSet<PermissionGrant>(pGrants.length);
synchronized (grantLock){
@@ -549,7 +551,7 @@ public class DynamicConcurrentPolicyProv
Permission [] perms = grantCache.get(pGrants[i]);
int len = perms.length;
for ( int c =0; c < len ; c++ ){
- removed.add(perms[c].getClass());
+ removed.add(perms[c]);
}
continue;
}
@@ -557,10 +559,8 @@ public class DynamicConcurrentPolicyProv
}
PermissionGrant[] updated = new PermissionGrant[holder.size()];
pGrants = holder.toArray(updated);
- jobs = Controller.revoke(removed);
+ execControlManager.revoke(removed);
}
- //TODO jobs to tidy up after revocation.
-
}
public List<PermissionGrant> getPermissionGrants() {
@@ -577,9 +577,8 @@ public class DynamicConcurrentPolicyProv
return grants;
}
-
- public ExecutionContextManager getExecutionContextManager(Permission p) {
- return Controller.getECManager(p);
+ public ExecutionContextManager getExecutionContextManager() {
+ return execControlManager;
}
}
Added: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/ECM.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/ECM.java?rev=985427&view=auto
==============================================================================
--- incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/ECM.java (added)
+++ incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/ECM.java Sat Aug 14 04:39:26 2010
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.river.imp.security.policy.se;
+
+import java.security.AccessControlContext;
+import java.security.AccessControlException;
+import java.security.AccessController;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.river.api.security.ExecutionContextManager;
+import org.apache.river.api.security.Reaper;
+import org.apache.river.imp.util.ConcurrentWeakIdentityMap;
+
+/**
+ * Only a Single instance of ECM is required per policy, it is threadsafe.
+ * Threads will wait until revoke is complete.
+ *
+ * @author Peter Firmstone
+ */
+class ECM implements ExecutionContextManager{
+
+ private final ConcurrentMap<Permission,Set<AccessControlContext>> checkedCache;
+ private final ConcurrentMap<AccessControlContext, Set<Thread>> executionCache;
+ private final ConcurrentMap<Thread, Set<AccessControlContext>> threadAssociation;
+ private final ConcurrentMap<Thread, Reaper> association;
+ private final ExecutorService executor;
+ private final ReadWriteLock blockLock;
+ private final Lock rl; // This lock is held briefly by callers of begin and end.
+ private final Lock wl; // This lock is held by revocation.
+
+ ECM(){
+ /* The clients control garbage collection, the Permission objects
+ * are those passed by clients.*/
+ checkedCache = new ConcurrentWeakIdentityMap<Permission, Set<AccessControlContext>>();
+ /* The thread association controls the removal of AccessContolContext
+ * keys from the executionCache, since the threadAssociation holds a
+ * strong reference from the thread, which is removed when end()
+ * is executed.
+ */
+ executionCache = new ConcurrentWeakIdentityMap<AccessControlContext, Set<Thread>>();
+ threadAssociation = new ConcurrentHashMap<Thread, Set<AccessControlContext>>();
+ /* The association is only made while threads are within the clients
+ * try finally block.
+ */
+ association = new ConcurrentHashMap<Thread, Reaper>();
+ // TODO: Analyse needs, enable client configuration of thread pool.
+ executor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()+1);
+ /* This lock guards revocation */
+ blockLock = new ReentrantReadWriteLock();
+ rl = blockLock.readLock();
+ wl = blockLock.writeLock();
+ }
+
+ void revoke(Set<Permission> perms) throws InterruptedException, ExecutionException{
+ wl.lock();
+ try {
+ /* This is where we determine what needs to be revoked, we first
+ * get all the AccessControlContexts for the Permission class,
+ * these are removed from the checkedCache, then we narrow
+ * down the AccessControlContext's to only those in the
+ * execution cache, each AccessControlContext in the execution cache
+ * has checkPermission(Permission) called for each permission
+ * with a Class identical to one of the revoked permission's.
+ * Any AccessControlContext's that throw AccessControlException will be
+ * caught and have a Reaper run, when it exists, for all Threads referenced
+ * from that AccessControlContext.
+ *
+ * The RevokeableDynamicPolicy will have updated the current
+ * Permission's after revocation, so the ProtectionDomain's in
+ * the AccessControlContext will now throw an AccessControlException
+ * if the revocation applied to them.
+ *
+ * The wl lock will be released, any threads that were interrupted
+ * will exit through the finally block and remove themselves
+ * from the execution cache. Those that aren't may throw
+ * an exception and bubble up the stack, due to closing sockets
+ * etc.
+ *
+ * The execution cache is comprised of the following fields:
+ * executionCache
+ * threadAssociation
+ */
+ // Identify Permission's with matching class files to those revoked.
+ Set<Class> permClasses = new HashSet<Class>();
+ Iterator<Permission> itp = perms.iterator();
+ while (itp.hasNext()){
+ permClasses.add(itp.next().getClass());
+ }
+ // Remove Permission's and AccessControlContexts from the checked cache.
+ Map<Permission, Set<AccessControlContext>> removed =
+ new HashMap<Permission, Set<AccessControlContext>>();
+ Iterator<Permission> keysIt = checkedCache.keySet().iterator();
+ while (keysIt.hasNext()){
+ Permission p = keysIt.next();
+ if (permClasses.contains(p.getClass())){
+ Set<AccessControlContext> a = checkedCache.get(p);
+ keysIt.remove();
+ removed.put(p, a);
+ }
+ }
+ // Match the AccessControlContexts with the execution cache;
+ Set<AccessControlContext> exCache = executionCache.keySet();
+ // Get the AccessControlContext's in the execution cache that fail.
+ Set<AccessControlContext> accFails = new HashSet<AccessControlContext>();
+ Iterator<Permission> retests = removed.keySet().iterator();
+ while (retests.hasNext()){
+ Permission p = retests.next();
+ Set<AccessControlContext> rechecks = removed.get(p);
+ Iterator<AccessControlContext> recheck = rechecks.iterator();
+ while (recheck.hasNext()){
+ AccessControlContext a = recheck.next();
+ if (accFails.contains(a)) continue;
+ // This really narrows down the checks.
+ if (exCache.contains(a)){
+ try {
+ a.checkPermission(p);
+ } catch (AccessControlException e){
+ accFails.add(a);
+ }
+ }
+ }
+ }
+ // Identify the threads and prepare reapers.
+ Set<Runnable> reapers = new HashSet<Runnable>();
+ Iterator<AccessControlContext> failedAcc = accFails.iterator();
+ while (failedAcc.hasNext()){
+ AccessControlContext fail = failedAcc.next();
+ Set<Thread> threads = executionCache.get(fail);
+ Iterator<Thread> i = threads.iterator();
+ while (i.hasNext()) {
+ Thread t = i.next();
+ Reaper r = association.get(t);
+ if ( r == null ) continue;
+ r.put(t);
+ reapers.add(r);
+ }
+ }
+ /* Process the reapers, this requires a thread pool, but we don't
+ * want to return until all reapers have completed.
+ */
+ Iterator<Runnable> reaper = reapers.iterator();
+ List<Future> results = new ArrayList<Future>(reapers.size());
+ while ( reaper.hasNext()) {
+ results.add(executor.submit(reaper.next()));
+ }
+ Iterator<Future> result = results.iterator();
+ while (result.hasNext()){
+ // Waits for result.
+ result.next().get();
+ }
+ /* We're done, go home & rest */
+ } finally {
+ wl.unlock();
+ }
+ }
+
+ public void begin(Reaper r) {
+ Thread currentThread = Thread.currentThread();
+ if ( r == null ) return;
+ association.put(currentThread, r);
+ }
+
+ public void checkPermission(Permission p) throws AccessControlException {
+ Thread currentThread = Thread.currentThread();
+ AccessControlContext executionContext = AccessController.getContext();
+ rl.lock();
+ try {
+ // execution cache, fast for repeated calls.
+ Set<Thread> exCacheThreadSet = executionCache.get(executionContext);
+ if ( exCacheThreadSet == null ){
+ exCacheThreadSet = Collections.synchronizedSet(new HashSet<Thread>());
+ Set<Thread> existed = executionCache.putIfAbsent(executionContext, exCacheThreadSet);
+ if (existed != null){
+ exCacheThreadSet = existed;
+ }
+ }
+ exCacheThreadSet.add(currentThread);// end execution cache.
+ // thread association, fast for repeated calls.
+ Set<AccessControlContext> thAssocSet = threadAssociation.get(currentThread);
+ if ( thAssocSet == null ){
+ thAssocSet = Collections.synchronizedSet(new HashSet<AccessControlContext>());
+ Set<AccessControlContext> existed = threadAssociation.putIfAbsent(currentThread, thAssocSet);
+ if (existed != null){
+ thAssocSet = existed;
+ }
+ }
+ thAssocSet.add(executionContext); // end thread association.
+ // checkedCache - the permission check, fast for repeated calls.
+ Set<AccessControlContext> checked = checkedCache.get(p);
+ if (checked == null ){
+ checked = Collections.synchronizedSet(new HashSet<AccessControlContext>());
+ Set<AccessControlContext> existed = checkedCache.putIfAbsent(p, checked);
+ if (existed != null){
+ checked = existed;
+ }
+ }
+ if ( checked.contains(executionContext)) return; // it's passed before.
+ executionContext.checkPermission(p); // Throws AccessControlException
+ // If we get here cache the AccessControlContext.
+ checked.add(executionContext); // end checkedCache.
+ } finally {
+ rl.unlock();
+ }
+ }
+
+ public void end() {
+ // Removal from execution cache.
+ Thread t = Thread.currentThread();
+ rl.lock();
+ try {
+ association.remove(t);
+ Set<AccessControlContext> accSet = threadAssociation.remove(t);
+ Iterator<AccessControlContext> it = accSet.iterator();
+ while (it.hasNext()){
+ AccessControlContext acc = it.next();
+ executionCache.get(acc).remove(t);
+ }
+ }finally {
+ rl.unlock();
+ }
+ }
+}
Propchange: incubator/river/jtsk/trunk/src/org/apache/river/imp/security/policy/se/ECM.java
------------------------------------------------------------------------------
svn:eol-style = native