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/09/20 13:35:03 UTC

svn commit: r998893 - in /incubator/river/jtsk/skunk/pepe/src: net/jini/core/lookup/ net/jini/lookup/ net/jini/security/policy/ org/apache/river/api/lookup/ org/apache/river/api/security/ org/apache/river/imp/security/policy/cdc/ org/apache/river/imp/s...

Author: peter_firmstone
Date: Mon Sep 20 11:35:03 2010
New Revision: 998893

URL: http://svn.apache.org/viewvc?rev=998893&view=rev
Log:
Remove unwanted classes, renamed and modified some existing and added more of the delegate framework.

Added:
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java
      - copied, changed from r996089, incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/MarshalledServiceItem.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamFilter.java
      - copied, changed from r996089, incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamFilter.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamUnmarshaller.java
      - copied, changed from r996089, incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamUnmarshaller.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java
      - copied, changed from r996093, incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/StreamServiceRegistrar.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/AccessControlDelegate.java   (with props)
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java   (with props)
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ACCC.java
      - copied, changed from r996089, incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ECM.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/util/ConcurrentCollections.java   (with props)
Removed:
    incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/MarshalledServiceItem.java
    incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/StreamServiceRegistrar.java
    incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamFilter.java
    incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamUnmarshaller.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/ExecutionContextManager.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/Reaper.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ECM.java
Modified:
    incubator/river/jtsk/skunk/pepe/src/net/jini/security/policy/DynamicPolicyProvider.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokePermission.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokeableDynamicPolicy.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java
    incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java

Modified: incubator/river/jtsk/skunk/pepe/src/net/jini/security/policy/DynamicPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/net/jini/security/policy/DynamicPolicyProvider.java?rev=998893&r1=998892&r2=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/net/jini/security/policy/DynamicPolicyProvider.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/net/jini/security/policy/DynamicPolicyProvider.java Mon Sep 20 11:35:03 2010
@@ -7,7 +7,7 @@ package net.jini.security.policy;
 
 import java.util.List;
 import org.apache.river.api.security.Denied;
-import org.apache.river.api.security.ExecutionContextManager;
+import org.apache.river.api.security.AccessControlDelegate;
 import org.apache.river.api.security.PermissionGrantBuilder;
 import org.apache.river.imp.security.policy.cdc.DynamicPolicyProviderImpl;
 import java.security.AccessControlException;
@@ -325,7 +325,7 @@ public class DynamicPolicyProvider exten
         return instance.getPermissionGrants();
     }
 
-    public ExecutionContextManager getExecutionContextManager() {
-	return instance.getExecutionContextManager();
+    public AccessControlDelegate getAccessControlDelegate() {
+	return instance.getAccessControlDelegate();
     }
 }

Copied: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java (from r996089, incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/MarshalledServiceItem.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java?p2=incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java&p1=incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/MarshalledServiceItem.java&r1=996089&r2=998893&rev=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/MarshalledServiceItem.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/MarshalledServiceItem.java Mon Sep 20 11:35:03 2010
@@ -3,8 +3,9 @@
  * and open the template in the editor.
  */
 
-package net.jini.core.lookup;
+package org.apache.river.api.lookup;
 
+import net.jini.core.lookup.*;
 import java.net.URI;
 import java.security.CodeSource;
 import java.util.Collection;

Copied: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamFilter.java (from r996089, incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamFilter.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamFilter.java?p2=incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamFilter.java&p1=incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamFilter.java&r1=996089&r2=998893&rev=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamFilter.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamFilter.java Mon Sep 20 11:35:03 2010
@@ -3,8 +3,9 @@
  * and open the template in the editor.
  */
 
-package net.jini.lookup;
+package org.apache.river.api.lookup;
 
+import net.jini.lookup.*;
 import org.apache.river.api.util.ResultStream;
 import java.util.ArrayList;
 import java.util.Arrays;

Copied: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamUnmarshaller.java (from r996089, incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamUnmarshaller.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamUnmarshaller.java?p2=incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamUnmarshaller.java&p1=incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamUnmarshaller.java&r1=996089&r2=998893&rev=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/net/jini/lookup/ServiceResultStreamUnmarshaller.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/ServiceResultStreamUnmarshaller.java Mon Sep 20 11:35:03 2010
@@ -3,8 +3,9 @@
  * and open the template in the editor.
  */
 
-package net.jini.lookup;
+package org.apache.river.api.lookup;
 
+import org.apache.river.api.lookup.MarshalledServiceItem;
 import org.apache.river.api.util.ResultStream;
 import net.jini.core.lookup.*;
 

Copied: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java (from r996093, incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/StreamServiceRegistrar.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java?p2=incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java&p1=incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/StreamServiceRegistrar.java&r1=996093&r2=998893&rev=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/net/jini/core/lookup/StreamServiceRegistrar.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/lookup/StreamServiceRegistrar.java Mon Sep 20 11:35:03 2010
@@ -15,8 +15,9 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package net.jini.core.lookup;
+package org.apache.river.api.lookup;
 
+import net.jini.core.lookup.*;
 import java.io.IOException;
 import org.apache.river.api.util.ResultStream;
 

Added: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/AccessControlDelegate.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/AccessControlDelegate.java?rev=998893&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/AccessControlDelegate.java (added)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/AccessControlDelegate.java Mon Sep 20 11:35:03 2010
@@ -0,0 +1,105 @@
+/*
+ * 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;
+
+import java.security.AccessControlException;
+import java.security.AccessControlContext;
+import java.security.Permission;
+import java.util.Collection;
+
+/**
+ * <p>
+ * An AccessControlDelegate is designed to be repeatedly called, where calling
+ * AccessController.checkPermission(Permission) is usually too great an overhead.
+ * </p><p>
+ * The AccessControlDelegate will only call 
+ * AccessControlContext.checkPermission(Permission) once, for each context.  This
+ * ensures checkPermission isn't re called, until the context changes, or
+ * the Permission checked by this AccessControlDelegate experiences a 
+ * revoke for any dynamic ProtectionDomain using a RevokeableDynamicPolicy.
+ * </p><p>
+ * A Reaper may be submitted to the AccessControlDelegate 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, although a
+ * revocation event will cause #checkPermission(Permission) to block
+ * until the revocation process is complete.
+ * </p><p>
+ * When protecting method's, the method must return from the try block.
+ * </p>
+ * @author Peter Firmstone
+ * @see RevokeableDynamicPolicy
+ * @see Permission
+ * @see AccessControlContext
+ */
+public interface AccessControlDelegate {
+
+    /**
+     * <p>
+     * This is a call made by a Security Delegate, or other Object used to
+     * control access to privileged methods or constructors, similar to the
+     * AccessController.checkPermission(Permission) call.  
+     * The Permission check is optimised, however
+     * Typically a method may only be concerned with a single Permission check,
+     * but in many existing cases, the AccessController check is too expensive 
+     * to be called on every method invocation.  The AccessControlDelegate 
+     * should optimise this call by ensuring that checkPermission(Permission) is only
+     * called once per AccessControlContext.  In other words if the caller's
+     * AccessControlContext hasn't changed, then checkPermission(Permission)
+     * isn't called again as it would be assumed to succeed, unless the 
+     * RevokeableDynamicPolicy revokes a Permission with the same class,
+     * in which case the Permission must be checked again.
+     * </p><p>
+     * Typically in the Java platform it isn't feasable to call 
+     * AccessController.checkPermission on every invocation, as a result,
+     * there are guarded objects or security sensitive objects have
+     * SecurityManager checkPermission(Permission) called in their constructor.
+     * </p><p>
+     * AccessControlDelegate combined with Security Delegates and DelegatePermission's
+     * provides a more thorough form of protection.
+     * </p><p>
+     * AccessControlDelegate should be used for repeated
+     * calls, it caches the results from the AccessControlContext.
+     * </p><p>
+     * Clients using the AccessControlDelegate, should be careful
+     * to release references to their Permission objects,
+     * since garbage collection is relied upon to clean up cached 
+     * AccessControlContext's, conversely, Permission objects, shouldn't be
+     * created in the checkPermission( new RuntimePermission("blah")) call,
+     * since this would cause the object to be created on every invocation
+     * and probably garbage collected between invocations, thrashing the cache
+     * and causing an AccessControlContext.checkPermssion(Permission) call
+     * as well.
+     * </p><p>
+     * In addition this method weakly caches the current AccessControlContext.
+     * </p><p>
+     * The AccessControlDelegate reserves special treatment of DelegatePermission's,
+     * if a ProtectionDomain doesn't have a DelegatePermission, but it does
+     * have the Permission the DelegatePermission represents, then it is allowed
+     * the DelegatePermission also.
+     * </p>
+     * 
+     * @see DelegatePermission
+     * @see RevokeableDynamicPolicy
+     * @param perm Permission to be checked, if result not already in cache.
+     * @throws java.security.AccessControlException
+     * @throws java.lang.NullPointerException 
+     */
+    public void checkPermission(Permission perm) 
+	    throws AccessControlException, NullPointerException;
+}
\ No newline at end of file

Propchange: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/AccessControlDelegate.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java?rev=998893&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java (added)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java Mon Sep 20 11:35:03 2010
@@ -0,0 +1,148 @@
+/*
+ * 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;
+
+import java.security.Permission;
+import java.security.PermissionCollection;
+import java.security.Permissions;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.Set;
+
+/**
+ * A DelegatePermission represents any another Permission, called the candidate.
+ * 
+ * A DelegatePermission is used by a Security Delegate in checkPermission
+ * calls.
+ * 
+ * A Security Delegate does not have an interface that identifies it as a Delegate,
+ * it is a wrapper class that has the interface or class type identical to 
+ * the object it encapsulates, to discuise it from clients.
+ * 
+ * Security Delegates enable sensitive objects to be used by code that isn't
+ * fully trusted and may want to monitor, such as a 
+ * file write that is limited by the number of bytes written, or a Permission
+ * to write a file, that we might decide to retract or revoke if the code
+ * does something we don't like, such as exceed a pre set limit or behave
+ * in a manner we would like to avoid, such as hogging network bandwidth.
+ * 
+ * A DelegatePermission never implies it's candidate, however if a 
+ * ProtectionDomain has the Permission the delegate represents, then the 
+ * AccessControlDelegate, which a Security Delegate must utilise,
+ * must ensure that it is also checked.
+ * 
+ * The DelegatePermissionCollection returned by newPermissionCollection() is not
+ * synchronized, this decision was made because PermissionCollection's are 
+ * usually accessed from within a heterogenous PermissionCollection like 
+ * Permissions that synchronizes anyway.  The decision made for the
+ * PermissionCollection contract to be synchronized has been broken deliberately
+ * in this case, existing PermissionCollection implementatations don't cleanly
+ * protect their internal state with synchronization, since the Enumeration
+ * returned by elements() will throw a ConcurrentModificationException if in a 
+ * loop when Permission's are being added to a PermissionCollection.
+ * 
+ * PermissionCollection's are used mostly read only.
+ * 
+ * @author Peter Firmstone
+ */
+public class DelegatePermission extends Permission{
+    private static final long serialVersionUID = 1L;
+    private final Permission permission;
+    
+    public DelegatePermission(Permission p){
+	super(p.getClass().toString() + " " + p.getName());
+	permission = p;
+    }
+
+    @Override
+    public boolean implies(Permission permission) {
+	if (permission == null) return false;
+	if (!(permission instanceof DelegatePermission)) return false;
+	if ( permission.getClass() != this.getClass()) return false;
+	return this.permission.implies(((DelegatePermission) permission).getPermission());
+    }
+    
+    public Permission getPermission(){
+	return permission;
+    }
+
+    @Override
+    public boolean equals(Object obj) {
+	if (obj == this) return true;
+	if (obj == null) return false;
+	if (!(obj instanceof DelegatePermission)) return false;
+	return permission.equals(((DelegatePermission) permission).getPermission());
+    }
+
+    @Override
+    public int hashCode() {
+	int hash = 5;
+	hash = 41 * hash + (this.permission != null ? this.permission.hashCode() : 0);
+	return hash;
+    }
+
+    @Override
+    public String getActions() {
+	return permission.getActions();
+    }
+    
+    @Override
+    public PermissionCollection newPermissionCollection() {
+	return new DelegatePermissionCollection();
+    }
+    
+    private static class DelegatePermissionCollection extends PermissionCollection {
+	private static final long serialVersionUID = 1L;
+	private final PermissionCollection candidates;
+	private final Set<Permission> delegates;
+	
+	DelegatePermissionCollection(){
+	    candidates = new Permissions();
+	    delegates = new HashSet<Permission>(50);
+	}
+
+	@Override
+	public void add(Permission permission) {
+	    if (! (permission instanceof DelegatePermission))
+	    throw new IllegalArgumentException("invalid permission: "+ permission);
+	if (isReadOnly())
+	    throw new SecurityException("attempt to add a Permission to a " +
+		    "readonly PermissionCollection");
+	    delegates.add(permission);
+	    candidates.add(((DelegatePermission) permission).getPermission());
+	}
+
+	@Override
+	public boolean implies(Permission permission) {
+	    if ( !(permission instanceof DelegatePermission)) return false;
+	    if ( permission == null ) return false;
+	    if (delegates.contains(permission)) return true;
+	    return candidates.implies(
+		    ((DelegatePermission )permission).getPermission());
+	}
+
+	@Override
+	public Enumeration<Permission> elements() {
+	    return Collections.enumeration(delegates);
+	}
+	
+    }
+
+}

Propchange: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/DelegatePermission.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokePermission.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokePermission.java?rev=998893&r1=998892&r2=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokePermission.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokePermission.java Mon Sep 20 11:35:03 2010
@@ -30,8 +30,9 @@ public class RevokePermission extends Pe
     
     @Override
     public boolean implies(Permission permission) {
-        if (permission instanceof RevokePermission) return true;
-        return false;
+        if ( !(permission instanceof RevokePermission)) return false;
+	if ( permission.getClass() != this.getClass()) return false;
+        return true;
     }
 
     @Override

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokeableDynamicPolicy.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokeableDynamicPolicy.java?rev=998893&r1=998892&r2=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokeableDynamicPolicy.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/api/security/RevokeableDynamicPolicy.java Mon Sep 20 11:35:03 2010
@@ -106,16 +106,22 @@ public interface RevokeableDynamicPolicy
      * 
      * Instead what is needed is a permission check that is efficient enough
      * to allow the methods that provide the privileged functionality to be
-     * called for every method invocation.  What the ExecutionContextManager
+     * called for every method invocation.  What the AccessControlDelegate
      * does is minimise the checkPermission calls by skipping checkPermission for
      * any execution AccessControlContext that has already passed, unless
      * a Permission related to the one being managed is revoked, in which case
      * the cache of AccessControlContext's previously checked are cleared.
      * 
-     * @param p Permission the ExecutionContextManager will check.
-     * @return a new ExecutionContextManager instance.
+     * The AccessControlDelegate also manages special semantics required by
+     * DelegatePermission checks, which require that a ProtectionDomain, have
+     * either the DelegatePermission, or the candidate Permission which the
+     * DelegatePermission represents (contains).
+     * 
+     * @see DelegatePermission
+     * @param p Permission the AccessControlDelegate will check.
+     * @return a new AccessControlDelegate instance.
      */
-    public ExecutionContextManager getExecutionContextManager();
+    public AccessControlDelegate getAccessControlDelegate();
     /**
      * 
      * @return true if Revoke supported.

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java?rev=998893&r1=998892&r2=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/cdc/DynamicPolicyProviderImpl.java Mon Sep 20 11:35:03 2010
@@ -49,7 +49,7 @@ import net.jini.security.GrantPermission
 import org.apache.river.api.security.Denied;
 import org.apache.river.api.security.PermissionGrant;
 import org.apache.river.api.security.PermissionGrantBuilder;
-import org.apache.river.api.security.ExecutionContextManager;
+import org.apache.river.api.security.AccessControlDelegate;
 import org.apache.river.imp.security.policy.spi.RevokeableDynamicPolicySpi;
 
 /**
@@ -583,7 +583,7 @@ public class DynamicPolicyProviderImpl e
         throw new UnsupportedOperationException("Not supported.");
     }
 
-    public ExecutionContextManager getExecutionContextManager() {
+    public AccessControlDelegate getAccessControlDelegate() {
 	throw new UnsupportedOperationException("Not supported yet.");
     }
 }

Copied: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ACCC.java (from r996089, incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ECM.java)
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ACCC.java?p2=incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ACCC.java&p1=incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ECM.java&r1=996089&r2=998893&rev=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ECM.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/ACCC.java Mon Sep 20 11:35:03 2010
@@ -18,25 +18,31 @@
 
 package org.apache.river.imp.security.policy.se;
 
+import java.lang.reflect.Field;
 import java.security.AccessControlContext;
 import java.security.AccessControlException;
 import java.security.AccessController;
 import java.security.Permission;
-import java.util.Collection;
-import java.util.Collections;
+import java.security.PrivilegedAction;
+import java.security.ProtectionDomain;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.ExecutionException;
 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 java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.river.api.security.AccessControlDelegate;
+import org.apache.river.api.security.DelegatePermission;
+import org.apache.river.imp.util.ConcurrentCollections;
 import org.apache.river.imp.util.ConcurrentSoftMap;
 
 /**
- * Only a Single instance of ECM is required per policy, it is threadsafe.
+ * Only a Single instance of ACCC is required per policy, it is threadsafe.
  * Threads will wait until revoke is complete.
  * 
  * Implementers Note:  It hasn't been determined if the cache should be
@@ -49,17 +55,37 @@ import org.apache.river.imp.util.Concurr
  * 
  * @author Peter Firmstone
  */
-class ECM implements ExecutionContextManager{
-    
-    private final ConcurrentMap<Permission,Set<AccessControlContext>> checkedCache;
+class ACCC implements AccessControlDelegate{
+
+    private final ConcurrentMap<AccessControlContext,DelegateContextCheck> checks;
     private final ReadWriteLock revokeLock;
     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 ConcurrentSoftMap<Permission, Set<AccessControlContext>>(300);
+    /* REMIND: do the DelegatePermission check and check the candidate Permission
+     * contained within is checked also.
+     * 
+     * It is important that the DelegatePermission check is not expanded in
+     * the Policy, since this would exclude Static ProtectionDomain's or 
+     * different Security Frameworks from working, eg OSGi.
+     * 
+     * The DelegatePermission or candidate Permission have to be checked
+     * and return true for each ProtectionDomain in the AccessControlContext.
+     * This requires a slightly different algorithm than the AccessControlContext
+     * permission check.
+     * 
+     * We would first have to get the current AccessControlContext from the stack,
+     * this would already have been optimised and combined.
+     * 
+     * Then we would need to use reflection to access the ProtectionDomain[]
+     * context and iterate through each domain and check implies for
+     * the DelegatePermission or candidate Permission the DelegatePermission
+     * contains.
+     */ 
+    
+    ACCC(){
+	/* Previous checks */
+	checks = new ConcurrentSoftMap<AccessControlContext,DelegateContextCheck>(40);
 	/* This lock guards revocation */ 
 	revokeLock = new ReentrantReadWriteLock();
 	rl = revokeLock.readLock();
@@ -76,13 +102,13 @@ class ECM implements ExecutionContextMan
 		permClasses.add(itp.next().getClass());
 	    }
 	    // Remove Permission's and AccessControlContexts from the checked cache.
-	    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();
-		}		
+	    Iterator<DelegateContextCheck> checkIt = checks.values().iterator();
+	    while (checkIt.hasNext()){
+		DelegateContextCheck c = checkIt.next();
+		Iterator<Class> it = permClasses.iterator();
+		while (it.hasNext()){
+		    c.removePermission(it.next());
+		}
 	    }
 	    /* We're done, go home & rest */
 	} finally {
@@ -90,34 +116,114 @@ class ECM implements ExecutionContextMan
 	}
     }
 
-    public void checkPermission(Collection<Permission> perms) throws AccessControlException {
-	if (perms == null ) throw new NullPointerException("Permission Collection null");
-	if (perms.isEmpty()) return; // Should we do this or is it a bug?
+    public void checkPermission(Permission perm) throws AccessControlException {
+	if (perm == null ) throw new NullPointerException("Permission Collection null");
 	//Thread currentThread = Thread.currentThread();
-	AccessControlContext executionContext = AccessController.getContext();
-	HashSet<Permission> permissions = new HashSet<Permission>(perms.size());
-	permissions.addAll(perms);
+	AccessControlContext executionContext = AccessController.getContext();	
 	rl.lock();
 	try {
-	    // checkedCache - the permission check, fast for repeated calls.
-	    Iterator<Permission> permiter = permissions.iterator();
-	    while (permiter.hasNext()){
-		Permission p = permiter.next();
-		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;
-		    }
+	    // checkedCache - the permission check, fast for repeated calls.    
+	    //Set<AccessControlContext> checked = checkedCache.get(perm);
+	    DelegateContextCheck checked = checks.get(executionContext);
+	    if (checked == null ){
+		checked = new DelegateContextCheck(executionContext);
+		DelegateContextCheck existed = 
+			checks.putIfAbsent(executionContext, checked);
+		if (existed != null){
+		    checked = existed;
 		}
-		if ( checked.contains(executionContext)) continue; // it's passed before.
-		executionContext.checkPermission(p); // Throws AccessControlException
-		// If we get here cache the AccessControlContext.
-		checked.add(executionContext);
 	    }
+	    checked.checkPermission(perm); // Throws AccessControlException
 	} finally {
 	    rl.unlock();
 	}
     }
+    
+    private static class DelegateContextCheck {
+	private final AccessControlContext acc;
+	private final ConcurrentMap<Class,Set<Permission>> passed;
+	// The context is only consulted directly for DelegatePermission
+	private final ProtectionDomain[] context;
+	
+	DelegateContextCheck(final AccessControlContext acc){
+	    this.acc = acc;
+	    passed = new ConcurrentHashMap<Class,Set<Permission>>();
+	    /* If context is null for whatever reason, then the AccessControlContext
+	     * will be consulted directly, but only for the DelegatePermission,
+	     * in most cases, the context is null because only system classes
+	     * are on the stack.
+	     * However if there is an error, then we default to the safest
+	     * action of directly consulting the AccessControlContext instead.
+	     */
+	    ProtectionDomain[] contx = AccessController.doPrivileged( new PrivilegedAction<ProtectionDomain[]>(){
+		public ProtectionDomain[] run() {
+		    try {
+			Field field = acc.getClass().getDeclaredField("context");
+			field.setAccessible(true);
+			return (ProtectionDomain[]) field.get(acc);
+		    } catch (IllegalArgumentException ex) {
+			Logger.getLogger(ACCC.class.getName()).log(Level.SEVERE, null, ex);
+			return null;
+		    } catch (IllegalAccessException ex) {
+			Logger.getLogger(ACCC.class.getName()).log(Level.SEVERE, null, ex);
+			return null;
+		    } catch (NoSuchFieldException ex) {
+			Logger.getLogger(ACCC.class.getName()).log(Level.SEVERE, null, ex);
+			return null;
+		    } catch (SecurityException ex) {
+			Logger.getLogger(ACCC.class.getName()).log(Level.SEVERE, null, ex);
+			return null;
+		    }
+		}
+	    });
+	    if ( contx != null ){
+		context = contx.clone();
+	    }else{
+		context = null;
+	    }
+	}
+	
+	void checkPermission(Permission perm) throws AccessControlException {
+	    if (perm == null) throw new NullPointerException("null Permission" +
+		    " not allowed");
+	    Set<Permission> perms = passed.get(perm.getClass());
+	    if (perms.contains(perm)) return;
+	    // We haven't checked this permission before!
+	    if ( perm instanceof DelegatePermission ) {
+		// This throws AccessControlException when Permission not true
+	      if( !implies((DelegatePermission) perm) ){
+		  // context was null if we get here.
+		acc.checkPermission(perm);
+	      }
+	    } else {
+		acc.checkPermission(perm);
+	    }
+	    // If we get to here then we have permission.
+	    if (perms == null ){
+		perms = ConcurrentCollections.multiReadSet(new HashSet<Permission>());
+		Set<Permission> existed = passed.putIfAbsent(perm.getClass(), perms);
+		if ( existed != null ){
+		    perms = existed;
+		}
+	    }
+	    perms.add(perm);	    
+	}
+	
+	private boolean implies(DelegatePermission perm) throws AccessControlException{
+	    if (context == null) return false; // safe
+	    int l = context.length;
+	    for (int i = 0; i < l; i++){
+		if ( context[i] != null && (!context[i].implies(perm) 
+			|| !context[i].implies(perm.getPermission()))) {
+		    throw new AccessControlException("access denied " + perm, perm);
+		}
+	    }
+	    return true;
+	} 
+	
+	void removePermission(Class c){
+	    passed.remove(c);
+	}
+	
+    }
 }

Modified: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java?rev=998893&r1=998892&r2=998893&view=diff
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java (original)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/security/policy/se/DynamicConcurrentPolicyProvider.java Mon Sep 20 11:35:03 2010
@@ -34,7 +34,7 @@ import net.jini.security.policy.PolicyIn
 import net.jini.security.policy.UmbrellaGrantPermission;
 import org.apache.river.api.security.Denied;
 import org.apache.river.api.security.PermissionGrant;
-import org.apache.river.api.security.ExecutionContextManager;
+import org.apache.river.api.security.AccessControlDelegate;
 import org.apache.river.imp.security.policy.spi.RevokeableDynamicPolicySpi;
 import org.apache.river.api.security.PermissionGrantBuilder;
 import org.apache.river.api.security.RevokePermission;
@@ -162,7 +162,7 @@ public class DynamicConcurrentPolicyProv
 //    private final WriteLock dwl;
 //    private final Set<Denied> denied;
 //    private volatile boolean checkDenied;
-    private final ECM execControlManager;
+    private final ACCC execControlManager;
     
     
     public DynamicConcurrentPolicyProvider(){
@@ -180,7 +180,7 @@ public class DynamicConcurrentPolicyProv
 //        denied = new HashSet<Denied>(30);
 //        checkDenied = false;
 	grantLock = new Object();
-	execControlManager = new ECM();
+	execControlManager = new ACCC();
     }
     
     /**
@@ -578,7 +578,7 @@ public class DynamicConcurrentPolicyProv
 	return grants;
     }
 
-    public ExecutionContextManager getExecutionContextManager() {
+    public AccessControlDelegate getAccessControlDelegate() {
 	return execControlManager;
     }
 

Added: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/util/ConcurrentCollections.java
URL: http://svn.apache.org/viewvc/incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/util/ConcurrentCollections.java?rev=998893&view=auto
==============================================================================
--- incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/util/ConcurrentCollections.java (added)
+++ incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/util/ConcurrentCollections.java Mon Sep 20 11:35:03 2010
@@ -0,0 +1,262 @@
+/*
+ * 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.util;
+
+import java.io.IOException;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Set;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+
+/**
+ *
+ * @author Peter Firmstone.
+ */
+public class ConcurrentCollections {
+    // Not instantiable
+    private ConcurrentCollections() {}
+
+    public static <T> Set<T> multiReadSet(Set<T> s) {
+	return new MultiReadSet<T>(s);
+    }
+    
+    public static <T> Collection<T> multiReadCollection(Collection<T> c){
+	return new MultiReadCollection<T>(c);
+    }
+    
+    static class MultiReadCollection<E> implements Collection<E>, Serializable {
+	private static final long serialVersionUID = 1L;
+
+	final Collection<E> c;  // Backing Collection
+	final Object mutex;     // Object on which to synchronize
+	final ReadWriteLock rwlock;
+	final Lock rl;
+	final Lock wl;
+
+	MultiReadCollection(Collection<E> c) {
+            if (c==null) {
+		throw new NullPointerException();
+	    }
+	    this.c = c;
+            mutex = this;
+	    rwlock = new ReentrantReadWriteLock();
+	    rl = rwlock.readLock();
+	    wl = rwlock.writeLock();
+        }
+
+	Lock getReadLock(){
+	    return rl;
+	}
+	
+	Lock getWriteLock(){
+	    return rl;
+	}
+	
+	public int size() {
+	    rl.lock();
+	    try {
+		return c.size();
+	    }
+	    finally {
+		rl.unlock();
+	    }
+        }
+	public boolean isEmpty() {
+	    rl.lock();
+	    try {
+		return c.isEmpty();
+	    }
+	    finally {
+		rl.unlock();
+	    }
+        }
+	public boolean contains(Object o) {
+	    rl.lock();
+	    try {
+		return c.contains(o);
+	    }
+	    finally {
+		rl.unlock();
+	    }
+        }
+	public Object[] toArray() {
+	    rl.lock();
+	    try {
+		return c.toArray();
+	    }
+	    finally {
+		rl.unlock();
+	    }
+        }
+	public <T> T[] toArray(T[] a) {
+	    rl.lock();
+	    try {
+		return c.toArray(a);
+	    }
+	    finally {
+		rl.unlock();
+	    }
+        }
+
+	public Iterator<E> iterator() {
+	    rl.lock();
+	    try {
+		return new CollectionIterator<E>(this);
+	    }
+	    finally {
+		rl.unlock();
+	    }
+        }
+
+	public boolean add(E e) {
+	    wl.lock();
+	    try{
+		return c.add(e);
+	    }finally{
+		wl.unlock();
+	    }
+        }
+	public boolean remove(Object o) {
+	    wl.lock();
+	    try{
+		return c.remove(o);
+	    }finally{
+		wl.unlock();
+	    }
+        }
+
+	public boolean containsAll(Collection<?> coll) {
+	    rl.lock();
+	    try{
+		return c.containsAll(coll);
+	    }finally{
+		rl.unlock();
+	    }
+        }
+	public boolean addAll(Collection<? extends E> coll) {
+	    wl.lock();
+	    try{
+		return c.addAll(coll);
+	    }finally{
+		wl.unlock();
+	    }
+        }
+	public boolean removeAll(Collection<?> coll) {
+	    wl.lock();
+	    try{
+		return c.removeAll(coll);
+	    }finally{
+		wl.unlock();
+	    }
+        }
+	public boolean retainAll(Collection<?> coll) {
+	    wl.lock();
+	    try{
+		return c.retainAll(coll);
+	    }finally{
+		wl.unlock();
+	    }
+        }
+	public void clear() {
+	    wl.lock();
+	    try{
+		c.clear();
+	    }finally{
+		wl.unlock();
+	    }
+        }
+	@Override
+	public String toString() {
+	    wl.lock();
+	    try{
+		return c.toString();
+	    }finally{
+		wl.unlock();
+	    }
+        }
+        private void writeObject(ObjectOutputStream s) throws IOException {
+	    rl.lock();
+	    try{
+		s.defaultWriteObject();
+	    }finally{
+		rl.unlock();
+	    }
+        }
+    }
+    
+    static class CollectionIterator<E> implements Iterator<E> {
+	final MultiReadCollection col;
+	final Iterator<E> iter;
+	volatile E element;
+	CollectionIterator(MultiReadCollection<E> c){
+	    col = c;
+	    Collection<E> copy = new ArrayList<E>(c.size());
+	    copy.addAll(c);
+	    iter = copy.iterator();   
+	}
+
+	public boolean hasNext() {
+		return iter.hasNext();
+	}
+
+	public E next() {
+		element = iter.next();
+		return element;
+	}
+
+	public void remove() {
+	    col.remove(element);
+	}
+	
+    }
+    
+       static class MultiReadSet<E>
+	  extends MultiReadCollection<E>
+	  implements Set<E> {
+	private static final long serialVersionUID = 1L;
+
+	MultiReadSet(Set<E> s) {
+            super(s);
+        }
+
+	@Override
+	public boolean equals(Object o) {
+	    rl.lock();
+	    try{
+		return c.equals(o);
+	    }finally{
+		rl.unlock();
+	    }
+        }
+	@Override
+	public int hashCode() {
+	    rl.lock();
+	    try{
+		return c.hashCode();
+	    }finally{
+		rl.unlock();
+	    }
+        }
+    }
+}

Propchange: incubator/river/jtsk/skunk/pepe/src/org/apache/river/imp/util/ConcurrentCollections.java
------------------------------------------------------------------------------
    svn:eol-style = native