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/09/21 15:35:30 UTC

svn commit: r1173631 [1/2] - in /river/jtsk/skunk/peterConcurrentPolicy: src/com/sun/jini/collection/ src/com/sun/jini/thread/ src/net/jini/loader/pref/ src/net/jini/security/ src/net/jini/security/policy/ src/org/apache/river/api/delegates/ src/org/ap...

Author: peter_firmstone
Date: Wed Sep 21 13:35:29 2011
New Revision: 1173631

URL: http://svn.apache.org/viewvc?rev=1173631&view=rev
Log:
Reference Collection Utilities

Modified:
    river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/collection/WeakKeyReference.java
    river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/thread/ThreadPool.java
    river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/loader/pref/PreferredClassLoader.java
    river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/Security.java
    river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java
    river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/DynamicPolicyProvider.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateReflectionSecurityManager.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/dos/IsolatedExecutor.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/Messages.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentCollections.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentSoftMap.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentWeakIdentityMap.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentWeakMap.java
    river/jtsk/skunk/peterConcurrentPolicy/test/src/net/jini/security/policy/ConcurrentPolicyFileTest.java
    river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/api/security/PermissionGrantTest.java
    river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/impl/security/dos/IsolateTest.java
    river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/impl/security/policy/util/PolicyEntryTest.java
    river/jtsk/skunk/peterConcurrentPolicy/test/src/org/apache/river/impl/security/policy/util/PolicyUtilsTest.java

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/collection/WeakKeyReference.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/collection/WeakKeyReference.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/collection/WeakKeyReference.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/collection/WeakKeyReference.java Wed Sep 21 13:35:29 2011
@@ -79,12 +79,8 @@ public class WeakKeyReference extends We
      * </ul>
      */
     public boolean equals(Object other) {
-	if (other == null)
-	    return false;
-	if (this == other)
-	    return true;
-	if (!(other instanceof WeakKeyReference))
-	    return false;
+	if (this == other) return true;
+	if (!(other instanceof WeakKeyReference))  return false;
 	Object thisRef = get();
 	Object otherRef = ((WeakKeyReference) other).get();
 	if (thisRef == null || otherRef == null) // if null it's not *anything*

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/thread/ThreadPool.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/thread/ThreadPool.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/thread/ThreadPool.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/com/sun/jini/thread/ThreadPool.java Wed Sep 21 13:35:29 2011
@@ -56,7 +56,7 @@ import java.util.logging.Logger;
  *
  * @author	Sun Microsystems, Inc.
  **/
-final class ThreadPool implements Executor {
+final class ThreadPool implements Executor, java.util.concurrent.Executor {
 
     /** how long a thread waits in the idle state before passing away */
     private static final long idleTimeout =		// default 5 minutes
@@ -101,6 +101,10 @@ final class ThreadPool implements Execut
 	t.start();
     }
 
+    public void execute(Runnable command) {
+        execute(command, "com.sun.jini.thread.ThreadPool");
+    }
+
     /**
      * Task simply encapsulates a task's Runnable object with its name.
      */

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/loader/pref/PreferredClassLoader.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/loader/pref/PreferredClassLoader.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/loader/pref/PreferredClassLoader.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/loader/pref/PreferredClassLoader.java Wed Sep 21 13:35:29 2011
@@ -1155,9 +1155,9 @@ public class PreferredClassLoader extend
 	 * Create an AccessControlContext that consists of a single
 	 * protection domain with only the permissions calculated above.
          * Comment added 7th May 2010 by Peter Firmstone:
-         * This calls the pre java 1.4 constructor which causes the
+         * This did call the pre java 1.4 constructor which causes the
          * ProtectionDomain to not consult the Policy, this
-         * has the effect of not allowing Dynamic Permission changes to be
+         * had the effect of not allowing Dynamic Permission changes to be
          * effected by the Policy.  It doesn't affect the existing
          * DynamicPolicy implementation as it returns the Permissions
          * allowing the ProtectionDomain domain combiner to combine

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/Security.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/Security.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/Security.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/Security.java Wed Sep 21 13:35:29 2011
@@ -51,7 +51,6 @@ import javax.security.auth.Subject;
 import javax.security.auth.SubjectDomainCombiner;
 import net.jini.security.policy.DynamicPolicy;
 import net.jini.security.policy.SecurityContextSource;
-import org.apache.river.impl.util.ConcurrentWeakIdentityMap;
 
 /**
  * Provides methods for executing actions with privileges enabled, for

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/net/jini/security/policy/ConcurrentPolicyFile.java Wed Sep 21 13:35:29 2011
@@ -27,8 +27,10 @@
 package net.jini.security.policy;
 
 import java.io.File;
+import java.lang.ref.Reference;
 import java.net.URL;
 import java.security.AccessController;
+import java.security.AllPermission;
 import java.security.CodeSource;
 import java.security.Permission;
 import java.security.PermissionCollection;
@@ -39,25 +41,23 @@ import java.security.PrivilegedException
 import java.security.ProtectionDomain;
 import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Properties;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.locks.Lock;
 import java.util.concurrent.locks.ReadWriteLock;
 import java.util.concurrent.locks.ReentrantReadWriteLock;
-import java.util.logging.Level;
-import java.util.logging.Logger;
 import net.jini.security.ConcurrentPermissions;
 import org.apache.river.api.security.PermissionGrant;
 import org.apache.river.impl.security.policy.util.DefaultPolicyParser;
 import org.apache.river.impl.security.policy.util.PolicyParser;
 import org.apache.river.impl.security.policy.util.PolicyUtils;
-import org.apache.river.impl.util.ConcurrentCollections;
-import org.apache.river.impl.util.ConcurrentWeakIdentityMap;
+import org.apache.river.impl.util.Ref;
+import org.apache.river.impl.util.RC;
 
 
 /**
@@ -200,7 +200,7 @@ public class ConcurrentPolicyFile extend
      * Default constructor, equivalent to
      * <code>ConcurrentPolicyFile(new DefaultPolicyParser())</code>.
      */
-    public ConcurrentPolicyFile() {
+    public ConcurrentPolicyFile() throws PolicyInitializationException {
         this(new DefaultPolicyParser());
     }
 
@@ -208,16 +208,37 @@ public class ConcurrentPolicyFile extend
      * Extension constructor for plugging-in a custom parser.
      * @param dpr 
      */
-    public ConcurrentPolicyFile(PolicyParser dpr) {
+    protected ConcurrentPolicyFile(PolicyParser dpr) throws PolicyInitializationException {
         parser = dpr;
         ReadWriteLock rwl = new ReentrantReadWriteLock();
         rl = rwl.readLock();
         wl = rwl.writeLock();
         grants = new HashSet<PermissionGrant>(120);
-        cache = new ConcurrentWeakIdentityMap<Object, Collection<Permission>>(120);
-        impliesCache = 
-            new ConcurrentWeakIdentityMap<ProtectionDomain,PermissionCollection>(80);
-        refresh();
+        ConcurrentMap<Reference<Object>, Reference<Collection<Permission>>> cacheInternal 
+                = new ConcurrentHashMap<Reference<Object>, Reference<Collection<Permission>>>(120);
+        cache = RC.concurrentMap(cacheInternal, Ref.WEAK_IDENTITY, Ref.SOFT);
+        ConcurrentMap<Reference<ProtectionDomain>, Reference<PermissionCollection>> impInternal
+                = new ConcurrentHashMap<Reference<ProtectionDomain>, Reference<PermissionCollection>>(80);
+        impliesCache = RC.concurrentMap(impInternal, Ref.WEAK_IDENTITY, Ref.SOFT);
+        /*
+         * The bootstrap policy makes implies decisions until this constructor
+         * has returned.  We don't need to lock.
+         */
+        try {
+            initialize();
+            ensureDependenciesResolved();
+        } catch (SecurityException e){
+            throw new PolicyInitializationException("PolicyInitialization failed", e);
+    }
+    }
+
+    private void ensureDependenciesResolved() {
+        // Investigate bug 4911907, do we need to do anything?
+        // From the work around above, we might not need to do anything.
+        // But these actions prevent the JVM from delaying classloading
+        // of required classes.
+        ProtectionDomain own = this.getClass().getProtectionDomain();
+        implies(own, new AllPermission());
     }
 
     /**
@@ -329,19 +350,27 @@ public class ConcurrentPolicyFile extend
      */
     @Override
     public void refresh() {
-        Set<PermissionGrant> fresh = Collections.emptySet();
-        wl.lock();
+        if ( !wl.tryLock() ) return; // If another thread has the lock, policy is undergoing an update.
         try {
-            fresh = AccessController.doPrivileged( 
+            initialize();
+        } finally {
+            wl.unlock();
+        }
+    }
+    
+    private void initialize(){
+        try {
+            Set<PermissionGrant> fresh = AccessController.doPrivileged( 
                 new PrivilegedExceptionAction<Set<PermissionGrant>>(){
-                    public Set<PermissionGrant> run() throws Exception {
+                    public Set<PermissionGrant> run() throws SecurityException {
                         Set<PermissionGrant> fresh = new HashSet<PermissionGrant>(120);
                         Properties system = System.getProperties();
                         system.setProperty("/", File.separator); //$NON-NLS-1$
                         URL[] policyLocations = PolicyUtils.getPolicyURLs(system,
                                                           JAVA_SECURITY_POLICY,
                                                           POLICY_URL_PREFIX);
-                        for (int i = 0; i < policyLocations.length; i++) {
+                        int l = policyLocations.length;
+                        for (int i = 0; i < l; i++) {
                             //TODO debug log
 //                                System.err.println("Parsing policy file: " + policyLocations[i]);
                             try {
@@ -350,12 +379,14 @@ public class ConcurrentPolicyFile extend
                                     grants.addAll(pc); 
                                 fresh.addAll(pc);
                             } catch (Exception e){
-                                // TODO log warning
-//                                System.err.println("Ignoring policy file: " 
-//                                                 + policyLocations[i] + ". Reason:\n"+ e);
+                                // It's best to let a SecurityException bubble up
+                                // in case there is a problem with our policy configuration
+                                // or implementation.
+                                if ( e instanceof SecurityException ) throw (SecurityException) e;
+                                e.printStackTrace(System.out);
+                                // ignore.
                             }
                         } 
-//                            System.err.println(fresh.toString());
                         return fresh;
                     }
                 }
@@ -368,9 +399,7 @@ public class ConcurrentPolicyFile extend
             cache.clear(); // Clear the cache.
             impliesCache.clear();
         }catch (PrivilegedActionException e){
-            System.err.println(e);
-        } finally {
-            wl.unlock();
+            e.printStackTrace(System.err);
         }
     }
     

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=1173631&r1=1173630&r2=1173631&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 Wed Sep 21 13:35:29 2011
@@ -1,8 +1,25 @@
-
+/*
+ * 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 net.jini.security.policy;
 
 import java.io.IOException;
+import java.lang.ref.Reference;
 import java.rmi.RemoteException;
 import org.apache.river.api.security.DelegateSecurityManager;
 import java.security.AccessController;
@@ -26,6 +43,7 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
@@ -36,8 +54,9 @@ import org.apache.river.api.security.pol
 import org.apache.river.api.security.RevokePermission;
 import org.apache.river.api.security.policy.RevokeableDynamicPolicy;
 import org.apache.river.impl.security.policy.util.PolicyUtils;
-import org.apache.river.impl.util.ConcurrentCollections;
-import org.apache.river.impl.util.ConcurrentWeakIdentityMap;
+import org.apache.river.impl.util.CollectionsConcurrent;
+import org.apache.river.impl.util.RC;
+import org.apache.river.impl.util.Ref;
 
 /**
  * Security policy provider that supports dynamic granting of permissions at
@@ -236,12 +255,27 @@ public class DynamicPolicyProvider exten
 	    throw new PolicyInitializationException(
 		"unable to construct base policy", e);
 	}
-        dynamicPolicyGrants = ConcurrentCollections.multiReadCollection(
+        dynamicPolicyGrants = CollectionsConcurrent.multiReadCollection(
                 new ArrayList<PermissionGrant>(120));
         
 	remotePolicyGrants = new PermissionGrant[0];
-        cache = new ConcurrentWeakIdentityMap<ProtectionDomain, PermissionCollection>(120);
-	grantCache = new ConcurrentWeakIdentityMap<PermissionGrant, Permission[]>(60);
+        /*
+         * By using a Softly referenced PermissionCollection, if the
+         * JVM suffers from low memory, the cache will be cleared, even
+         * when the ProtectionDomain is still strongly reachable, this will
+         * slow down the performance of Dynamic Grant based permissions.
+         * 
+         * This configuration has been chosen because a ProtectionDomain
+         * may never be garbage collected even after a smart proxy is no longer
+         * referenced, in the case where the client hangs onto objects
+         * recieved from it.
+         */
+        ConcurrentMap<Reference<ProtectionDomain>, Reference<PermissionCollection>> internal 
+                = new ConcurrentHashMap<Reference<ProtectionDomain>,Reference<PermissionCollection>>(120);
+        cache = RC.concurrentMap(internal, Ref.WEAK_IDENTITY, Ref.SOFT);
+        ConcurrentMap<Reference<PermissionGrant>, Reference<Permission[]>> gInternal
+                = new ConcurrentHashMap<Reference<PermissionGrant>, Reference<Permission[]>>(60);
+	grantCache = RC.concurrentMap(gInternal, Ref.WEAK, Ref.STRONG);
         loggable = logger.isLoggable(Level.FINEST);
 	grantLock = new Object();
 	revokePermission = new RevokePermission();
@@ -278,11 +312,15 @@ public class DynamicPolicyProvider exten
      */
     public DynamicPolicyProvider(Policy basePolicy){
         this.basePolicy = basePolicy;
-        dynamicPolicyGrants = ConcurrentCollections.multiReadCollection(
+        dynamicPolicyGrants = CollectionsConcurrent.multiReadCollection(
                 new ArrayList<PermissionGrant>(120));
 	remotePolicyGrants = new PermissionGrant[0];
-        cache = new ConcurrentWeakIdentityMap<ProtectionDomain, PermissionCollection>(120);
-	grantCache = new ConcurrentWeakIdentityMap<PermissionGrant, Permission[]>(60);
+        ConcurrentMap<Reference<ProtectionDomain>, Reference<PermissionCollection>> internal 
+                = new ConcurrentHashMap<Reference<ProtectionDomain>,Reference<PermissionCollection>>(120);
+        cache = RC.concurrentMap(internal, Ref.WEAK_IDENTITY, Ref.SOFT);
+        ConcurrentMap<Reference<PermissionGrant>, Reference<Permission[]>> gInternal
+                = new ConcurrentHashMap<Reference<PermissionGrant>, Reference<Permission[]>>(60);
+	grantCache = RC.concurrentMap(gInternal, Ref.WEAK, Ref.STRONG);
         loggable = logger.isLoggable(Level.FINEST);
 	grantLock = new Object();
 	revokePermission = new RevokePermission();

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/delegates/DelegatePermission.java Wed Sep 21 13:35:29 2011
@@ -23,6 +23,7 @@ import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
 import java.io.ObjectOutputStream;
 import java.io.Serializable;
+import java.lang.ref.Reference;
 import java.security.Permission;
 import java.security.PermissionCollection;
 import java.security.Permissions;
@@ -30,9 +31,11 @@ import java.util.Collections;
 import java.util.Enumeration;
 import java.util.HashSet;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import org.apache.river.api.security.DelegateSecurityManager;
-import org.apache.river.impl.util.ConcurrentWeakMap;
+import org.apache.river.impl.util.RC;
+import org.apache.river.impl.util.Ref;
 
 /**
  * A DelegatePermission represents any another Permission, called the candidate.
@@ -86,7 +89,11 @@ public final class DelegatePermission ex
      * consumption.
      */
     private static final ConcurrentMap<Permission,DelegatePermission> instances 
-	    = new ConcurrentWeakMap<Permission,DelegatePermission>();
+	    = RC.concurrentMap(
+                new ConcurrentHashMap<Reference<Permission>, 
+                Reference<DelegatePermission>>(120),
+                Ref.WEAK, Ref.SOFT
+            );
     /**
      * Factory method to obtain a DelegatePermission
      * @param p Permission to be represented.

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=1173631&r1=1173630&r2=1173631&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 Wed Sep 21 13:35:29 2011
@@ -18,6 +18,7 @@
 
 package org.apache.river.api.security;
 
+import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
 import java.security.AccessControlContext;
 import java.security.AccessController;
@@ -31,11 +32,12 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
 import org.apache.river.api.delegates.DelegatePermission;
-import org.apache.river.impl.util.ConcurrentCollections;
-import org.apache.river.impl.util.ConcurrentWeakIdentityMap;
-import org.apache.river.impl.util.ConcurrentWeakMap;
+import org.apache.river.impl.util.CollectionsConcurrent;
+import org.apache.river.impl.util.RC;
+import org.apache.river.impl.util.Ref;
 
 /**
  * DelegateCombinerSecurityManager, is intended to be a high performance
@@ -57,8 +59,15 @@ extends SecurityManager implements Deleg
     public DelegateCombinerSecurityManager(){
         super();
         dc = new DelegateDomainCombiner();
-        contextCache = new ConcurrentWeakMap<AccessControlContext, AccessControlContext>(100);
-        checked = new ConcurrentWeakMap<AccessControlContext, Set<Permission>>(100);
+        ConcurrentMap<Reference<AccessControlContext>, 
+                Reference<AccessControlContext>> internal = 
+                new ConcurrentHashMap<Reference<AccessControlContext>, 
+                Reference<AccessControlContext>>(100);
+        contextCache = RC.concurrentMap(internal, Ref.SOFT, Ref.STRONG);
+        ConcurrentMap<Reference<AccessControlContext>, Reference<Set<Permission>>> refmap 
+                = new ConcurrentHashMap<Reference<AccessControlContext>, 
+                Reference<Set<Permission>>>(100);
+        checked = RC.concurrentMap(refmap, Ref.SOFT, Ref.STRONG);
         g = new RevokePermission();
         action = new Action();
     }
@@ -71,7 +80,8 @@ extends SecurityManager implements Deleg
         // Checks if Permission has already been checked for this context.
         Set<Permission> checkedPerms = checked.get(executionContext);
         if (checkedPerms == null){
-            checkedPerms = ConcurrentCollections.multiReadSet(new HashSet<Permission>(96));
+            Set<Reference<Permission>> internal = new HashSet<Reference<Permission>>(96);
+            checkedPerms = CollectionsConcurrent.multiReadSet(RC.set(internal, Ref.SOFT));
             Set<Permission> existed = checked.putIfAbsent(executionContext, checkedPerms);
             if (existed != null) checkedPerms = existed;
         }
@@ -157,7 +167,9 @@ extends SecurityManager implements Deleg
         // create any more than abolutely necessary.
         private final ConcurrentMap<ProtectionDomain,DelegateProtectionDomain> cache;
         private DelegateDomainCombiner (){
-            cache = new ConcurrentWeakIdentityMap<ProtectionDomain,DelegateProtectionDomain>(120);
+            ConcurrentMap<Reference<ProtectionDomain>,Reference<DelegateProtectionDomain>> internal = 
+                    new ConcurrentHashMap<Reference<ProtectionDomain>,Reference<DelegateProtectionDomain>>(120);
+            cache = RC.concurrentMap(internal, Ref.WEAK_IDENTITY, Ref.STRONG);
         }
 
         public ProtectionDomain[] combine(ProtectionDomain[] currentDomains, ProtectionDomain[] assignedDomains) {

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateReflectionSecurityManager.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateReflectionSecurityManager.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateReflectionSecurityManager.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateReflectionSecurityManager.java Wed Sep 21 13:35:29 2011
@@ -18,6 +18,7 @@
 
 package org.apache.river.api.security;
 
+import java.lang.ref.Reference;
 import org.apache.river.api.delegates.DelegatePermission;
 import java.lang.reflect.Field;
 import java.security.AccessControlContext;
@@ -34,9 +35,9 @@ import java.util.concurrent.ConcurrentHa
 import java.util.concurrent.ConcurrentMap;
 import java.util.logging.Level;
 import java.util.logging.Logger;
-import org.apache.river.impl.util.ConcurrentCollections;
-import org.apache.river.impl.util.ConcurrentSoftMap;
-import org.apache.river.impl.util.ConcurrentWeakMap;
+import org.apache.river.impl.util.CollectionsConcurrent;
+import org.apache.river.impl.util.RC;
+import org.apache.river.impl.util.Ref;
 
 /**
  * The DelegateReflectionSecurityManager provides cached permission check results and
@@ -78,11 +79,15 @@ public class DelegateReflectionSecurityM
      * contains.
      */ 
     
+    @SuppressWarnings("unchecked")
     public DelegateReflectionSecurityManager(){
 	/* This checks adequate permission is held */
 	super();
-	/* Previous checks */
-	checks = new ConcurrentSoftMap<AccessControlContext,ExecutionContextChecks>(40);
+	/* Previous checks - softly referenced */
+        ConcurrentMap<Reference<AccessControlContext>,Reference<ExecutionContextChecks>> internal 
+                = new ConcurrentHashMap<Reference<AccessControlContext>,Reference<ExecutionContextChecks>>(40);
+//        ConcurrentMap internal = new ConcurrentHashMap(40);
+	checks = RC.concurrentMap(internal, Ref.SOFT, Ref.STRONG);
 	/* This lock guards revocation, although if Permission has already
 	 * been removed from the policy then this lock isn't really necessary
 	 */ 
@@ -220,7 +225,7 @@ public class DelegateReflectionSecurityM
 	    }
 	    // If we get to here then we have permission.
 	    if (perms == null ){
-		perms = ConcurrentCollections.multiReadSet(new HashSet<Permission>());
+		perms = CollectionsConcurrent.multiReadSet(new HashSet<Permission>());
 		Set<Permission> existed = passed.putIfAbsent(perm.getClass(), perms);
 		if ( existed != null ){
 		    perms = existed;

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/dos/IsolatedExecutor.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/dos/IsolatedExecutor.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/dos/IsolatedExecutor.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/dos/IsolatedExecutor.java Wed Sep 21 13:35:29 2011
@@ -18,33 +18,92 @@
 
 package org.apache.river.impl.security.dos;
 
+import java.lang.ref.Reference;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.concurrent.BlockingQueue;
 import java.util.concurrent.Callable;
+import java.util.concurrent.CancellationException;
 import java.util.concurrent.ExecutionException;
 import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
+import java.util.concurrent.Future;
+import java.util.concurrent.RejectedExecutionHandler;
+import java.util.concurrent.SynchronousQueue;
 import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.concurrent.ThreadPoolExecutor.AbortPolicy;
 import java.util.concurrent.TimeUnit;
 import java.util.concurrent.TimeoutException;
+import java.util.concurrent.locks.Lock;
+import java.util.concurrent.locks.ReadWriteLock;
+import java.util.concurrent.locks.ReentrantReadWriteLock;
+import org.apache.river.impl.util.Ref;
+import org.apache.river.impl.util.RC;
 
 /**
  * Performs Callable tasks in an isolated thread, which is terminated
- * if any Errors are experienced.  This may take some time to terminate the thread
- * as it is not forcibly stopped.  The thread priority is minimal and a daemon
- * thread so it would take a number of unterminated threads to cause problems.
+ * if any Errors occur.   The daemon thread priority is minimal.
  * 
  * The caller can give up on the execution of the task by setting a timeout.
  * 
- * @param T 
+ * @param <T> 
  * @author peter
  */
-public class IsolatedExecutor<T> {
-    private volatile ExecutorService isolateExecutor;
-    private volatile Throwable thrown;
+public class IsolatedExecutor<T> implements ExecutorService {
+    /*
+     * We could optionally make this multithreaded, however once an Error
+     * occurs we'd still need to shut down.
+     */
     
+    private Lock exRl;
+    private Lock exWl;
+    private ExecutorService isolateExecutor;
+    private volatile State state;
+    private volatile byte [] free;
+    private final BlockingQueue queue;
+    private final RejectedExecutionHandler policy;
+    private final ThreadFactory factory;
+    private final ExecutorService nullExec;
+    private volatile List<Runnable> failedTasks;
+
     public IsolatedExecutor()
     {
-        thrown = null;
-	isolateExecutor = Executors.newSingleThreadExecutor(new Factory(this));
+        /* This Executor is single threaded, but that thread is replaced
+         * if idle for extended periods.
+         * SynchronousQueue has zero capacity, so it cannot create memory problems.
+         */
+        queue = new SynchronousQueue<Runnable>();
+        ReadWriteLock rwl = new ReentrantReadWriteLock();
+        exRl = rwl.readLock();
+        exWl = rwl.writeLock();
+        state = State.RUNNING;
+        policy = new AbortPolicy();
+        factory = new Factory();
+        failedTasks = RC.list(new ArrayList<Reference<Runnable>>(),Ref.SOFT);
+        nullExec = new NullExecutor(); // Can't create one lazily if memory low.
+	isolateExecutor = new Executor(0, 1,
+                                      60L, TimeUnit.SECONDS,
+                                      queue,
+                                      factory,
+                                      policy);
+    }
+    
+    private ExecutorService getExecutor(){
+        exRl.lock();
+        try {
+            if (getIsolateExecutor() != null) return getIsolateExecutor();
+        } finally { exRl.unlock(); }
+        exWl.lock();
+        try {
+            if (getIsolateExecutor() != null) return getIsolateExecutor();
+            setIsolateExecutor(new Executor(0, 1,
+                                               60L, TimeUnit.SECONDS,
+                                               queue,
+                                               factory,
+                                               policy));
+            return getIsolateExecutor();
+        } finally {  exWl.unlock(); }
     }
     
     /**
@@ -61,54 +120,225 @@ public class IsolatedExecutor<T> {
      * @throws java.util.concurrent.ExecutionException
      */
     public T process(Callable<T> task, long timeout, TimeUnit timeUnit) throws 
-            IsolationException, ExecutionException, InterruptedException, 
-            TimeoutException {
-        if ( thrown != null){
-            throw new IsolationException ("Isolate has" +
-                  "experienced an error during processing and " +
-                  "cannot perform further " +
-                  "tasks", thrown);
-        }
-        return isolateExecutor.submit(task).get(timeout, timeUnit);
-    }
-    
-    private void terminate(Throwable e){
-	thrown = e;
-	isolateExecutor.shutdownNow();	
-    }
-    
-    private static class Factory implements ThreadFactory{
-	private static final ThreadGroup tg = new ThreadGroup("Isolated");
-	{
-	    tg.setDaemon(true);
-	    tg.setMaxPriority(4);
+            ExecutionException, InterruptedException, TimeoutException {
+        Future<T> result = getIsolateExecutor().submit(task);
+        return result.get(timeout, timeUnit);
+        }
+    
+    public void shutdown(){
+        state = State.SHUTDOWN;
+        getIsolateExecutor().shutdown();
+    }
+    
+    public List<Runnable> shutdownNow(){
+        state = State.SHUTDOWN;
+        return getIsolateExecutor().shutdownNow();
+    }
+    
+    public boolean isShutdown(){
+        return getIsolateExecutor().isShutdown();
 	}
-	private final IsolatedExecutor isolate;
-	Factory(IsolatedExecutor uri){
-	    isolate = uri;
+
+    public boolean isTerminated() {
+        return getIsolateExecutor().isTerminated();
 	}
 
+    public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+        return getIsolateExecutor().awaitTermination(timeout, unit);
+    }
+    
+    public <T> Future<T> submit(Callable<T> task) {
+        return getIsolateExecutor().submit(task);
+    }
+
+    public <T> Future<T> submit(Runnable task, T result) {
+        return getIsolateExecutor().submit(task, result);
+    }
+
+    public Future<?> submit(Runnable task) {
+        return getIsolateExecutor().submit(task);
+    }
+
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
+        return getIsolateExecutor().invokeAll(tasks);
+    }
+
+    public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
+        return getIsolateExecutor().invokeAll(tasks, timeout, unit);
+    }
+
+    public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
+        return getIsolateExecutor().invokeAny(tasks);
+    }
+
+    public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+        return getIsolateExecutor().invokeAny(tasks, timeout, unit);
+    }
+
+    public void execute(Runnable command) {
+        getIsolateExecutor().execute(command);
+    }
+
+    /**
+     * @return the isolateExecutor
+     */
+    public ExecutorService getIsolateExecutor() {
+        return isolateExecutor;
+    }
+
+    /**
+     * @param isolateExecutor the isolateExecutor to set
+     */
+    public void setIsolateExecutor(ExecutorService isolateExecutor) {
+        this.isolateExecutor = isolateExecutor;
+    }
+    
+    private class Factory implements ThreadFactory{
+        ThreadGroup group;
+	Factory(){
+            group = new ThreadGroup("Isolated");
+            group.setDaemon(true);
+            group.setMaxPriority(Thread.MIN_PRIORITY);
+        }
+        /*
+         * Because we're only single threaded, if the existing
+         * Thread exits, the ThreadGroup is destroyed.
+         */
 	public Thread newThread(Runnable r) {
-	    Thread t = new Thread(tg, r);
-	    t.setUncaughtExceptionHandler(new ExceptionHandler(isolate));
+            // Try to limit the stack size of created Threads; hint to jvm.
+	    Thread t = new Thread(group, r, "Isolated", 131072L);
+	    t.setUncaughtExceptionHandler(new ExceptionHandler());
+            free = new byte[1024]; // assign some memory
+            free[0] = 1; // ensure it gets allocated by jit.
 	    return t;
 	}	
     }
     
-    private static class ExceptionHandler implements Thread.UncaughtExceptionHandler{
-	private final IsolatedExecutor isolate;
+    private class ExceptionHandler implements Thread.UncaughtExceptionHandler{
 	
-	ExceptionHandler(IsolatedExecutor uri){
-	    isolate = uri;
+	ExceptionHandler(){
 	}
 
 	public void uncaughtException(Thread t, Throwable e) {
-	    // For all other Exceptions we let the ExecutorService handle it.
-	    if ( e instanceof Error){
-		// Do we want to take different actions based on the error?
-		isolate.terminate(e);
+	    // This is only useful for logging, the jvm ignores any exceptions
+            // thrown.
+            System.out.println("Thread ExceptionHandler called for Isolate: \n");
+            System.out.println(t);
+            System.out.println(Thread.currentThread());
 	    }
 	}
 	
+    private enum State {
+        SHUTDOWN, TERMINATED, RUNNING
+    }
+    
+    private class NullExecutor implements ExecutorService {
+
+        public void shutdown() {
+            // Do nothing
+}
+
+        public List<Runnable> shutdownNow() {
+            return failedTasks;
+        }
+
+        public boolean isShutdown() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public boolean isTerminated() {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public <T> Future<T> submit(Callable<T> task) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public <T> Future<T> submit(Runnable task, T result) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public Future<?> submit(Runnable task) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks) throws InterruptedException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public <T> List<Future<T>> invokeAll(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public <T> T invokeAny(Collection<? extends Callable<T>> tasks) throws InterruptedException, ExecutionException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public <T> T invokeAny(Collection<? extends Callable<T>> tasks, long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+
+        public void execute(Runnable command) {
+            throw new UnsupportedOperationException("Not supported yet.");
+        }
+        
+    }
+    
+    private class Executor extends ThreadPoolExecutor{
+        Executor(int corePoolSize,
+                              int maximumPoolSize,
+                              long keepAliveTime,
+                              TimeUnit unit,
+                              BlockingQueue<Runnable> workQueue,
+                              ThreadFactory threadFactory,
+                              RejectedExecutionHandler handler){
+            super( corePoolSize, maximumPoolSize, keepAliveTime, unit, workQueue,
+                    threadFactory, handler);
+        }
+        
+        @Override
+        protected void afterExecute(Runnable r, Throwable t) {
+            super.afterExecute(r, t);
+            if (t == null && r instanceof Future<?>) {
+                try {
+                    ((Future<?>) r).get();
+                } catch (CancellationException ce) {
+                    t = ce;
+                } catch (ExecutionException ee) {
+                    t = ee.getCause();
+                } catch (InterruptedException ie) {
+                    // Don't need to interrupt thread, the Executor will do it.
+                    shutdownNow();// Ensure the interrupt isn't cleared.
+                } finally {
+                    //TODO: Implement a shutdown hook for the jvm for other Error's.
+                    /*
+                     * Even though ThreadPoolExecutor only catches a RuntimeException,
+                     * a FutureTask catches a Throwable, so we can get an Error
+                     * cause, wrapped in an ExecutionException.
+                     */
+                     if ( t instanceof OutOfMemoryError || t instanceof StackOverflowError ){
+                        /* Do we want to take different actions based on the error?
+                         * OutOfMemoryError doesn't mean the jvm is completely devoid
+                         * of memory, it indicates that there wasn't enough
+                         * memory to create the last object.
+                         */
+                        free = null; // Free some memory to allow recovery.
+                        System.gc();
+                        shutdownNow(); // Interrupt all threads in Executor.
+                        /* It might be tempting to throw ThreadDeath, it's not required,
+                         * instead we just let the thread stack overflow, or run until
+                         * no more objects can be created in the jvm.  The low
+                         * thread priority ensure that performance isn't impacted
+                         * by endless loops, however large memory consumption
+                         * will impact performance.
+                         */
+                    }
+                }
+            }          
+        }
     }
 }

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyParser.java Wed Sep 21 13:35:29 2011
@@ -141,7 +141,8 @@ public class DefaultPolicyParser impleme
                 }
             }
             catch (Exception e) {
-                // TODO: log warning
+                if ( e instanceof SecurityException ) throw (SecurityException) e;
+                e.printStackTrace(System.out);
             }
         }
 
@@ -183,23 +184,26 @@ public class DefaultPolicyParser impleme
      */
     protected PermissionGrant resolveGrant(DefaultPolicyScanner.GrantEntry ge,
             KeyStore ks, Properties system, boolean resolve) throws Exception {
-
+        /*
+         * Do we return multiple grants or do we allow a codebase array 
+         * in a permission grant?
+         */
         URL codebase = null;
         Certificate[] signers = null;
         Set<Principal>principals = new HashSet<Principal>();
         Set<Permission>permissions = new HashSet<Permission>();
-        if (ge.codebase != null) {
-            codebase = new URL(resolve ? PolicyUtils.expandURL(ge.codebase,
-                    system) : ge.codebase);
+        if (ge.getCodebase(null) != null) {
+            codebase = new URL(resolve ? PolicyUtils.expandURL(ge.getCodebase(system),
+                    system) : ge.getCodebase(null));
         }
-        if (ge.signers != null) {
+        if (ge.getSigners() != null) {
             if (resolve) {
-                ge.signers = PolicyUtils.expand(ge.signers, system);
+                ge.setSigners(PolicyUtils.expand(ge.getSigners(), system));
             }
-            signers = resolveSigners(ks, ge.signers);
+            signers = resolveSigners(ks, ge.getSigners());
         }
-        if (ge.principals != null) {
-            for (Iterator<PrincipalEntry> iter = ge.principals.iterator(); iter.hasNext();) {
+        if (ge.getPrincipals(null) != null) {
+            for (Iterator<PrincipalEntry> iter = ge.getPrincipals(system).iterator(); iter.hasNext();) {
                 DefaultPolicyScanner.PrincipalEntry pe = iter
                         .next();
                 if (resolve) {
@@ -212,8 +216,8 @@ public class DefaultPolicyParser impleme
                 }
             }
         }
-        if (ge.permissions != null) {
-            for (Iterator<PermissionEntry> iter = ge.permissions.iterator(); iter.hasNext();) {
+        if (ge.getPermissions() != null) {
+            for (Iterator<PermissionEntry> iter = ge.getPermissions().iterator(); iter.hasNext();) {
                 DefaultPolicyScanner.PermissionEntry pe = iter
                         .next();
                 try {
@@ -221,6 +225,7 @@ public class DefaultPolicyParser impleme
                             resolve));
                 }
                 catch (Exception e) {
+                    if ( e instanceof SecurityException ) throw (SecurityException) e;
                     // TODO: log warning
                 }
             }
@@ -328,9 +333,9 @@ public class DefaultPolicyParser impleme
 
             if ("self".equals(protocol)) { //$NON-NLS-1$
                 //need expanding to list of principals in grant clause 
-                if (ge.principals != null && ge.principals.size() != 0) {
+                if (ge.getPrincipals(null) != null && ge.getPrincipals(null).size() != 0) {
                     StringBuilder sb = new StringBuilder();
-                    for (Iterator<PrincipalEntry> iter = ge.principals.iterator(); iter
+                    for (Iterator<PrincipalEntry> iter = ge.getPrincipals(null).iterator(); iter
                             .hasNext();) {
                         DefaultPolicyScanner.PrincipalEntry pr = iter
                                 .next();
@@ -341,6 +346,7 @@ public class DefaultPolicyParser impleme
                                         pr.name)));
                             }
                             catch (Exception e) {
+                                if ( e instanceof SecurityException ) throw (SecurityException) e;
                                 throw new PolicyUtils.ExpansionFailedException(
                                         Messages.getString("security.143", pr.name), e); //$NON-NLS-1$
                             }
@@ -360,6 +366,7 @@ public class DefaultPolicyParser impleme
                     return pc2str(getPrincipalByAlias(ks, data));
                 }
                 catch (Exception e) {
+                    if ( e instanceof SecurityException ) throw (SecurityException) e;
                     throw new PolicyUtils.ExpansionFailedException(
                             Messages.getString("security.143", data), e); //$NON-NLS-1$
                 }
@@ -477,6 +484,8 @@ public class DefaultPolicyParser impleme
                 return ks;
             }
             catch (Exception e) {
+                if ( e instanceof SecurityException ) throw (SecurityException) e;
+                e.printStackTrace(System.err);
                 // TODO: log warning
             }
         }

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/DefaultPolicyScanner.java Wed Sep 21 13:35:29 2011
@@ -25,9 +25,21 @@ package org.apache.river.impl.security.p
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StreamTokenizer;
+import java.util.ArrayList;
 import java.util.Collection;
+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.Properties;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.TreeSet;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import org.apache.river.impl.security.policy.util.PolicyUtils.ExpansionFailedException;
 
 
 /**
@@ -209,13 +221,13 @@ public class DefaultPolicyScanner {
             case StreamTokenizer.TT_WORD:
                 if (Util.equalsIgnoreCase("signedby", st.sval)) { //$NON-NLS-1$
                     if (st.nextToken() == '"') {
-                        ge.signers = st.sval;
+                        ge.setSigners(st.sval);
                     } else {
                         handleUnexpectedToken(st, Messages.getString("security.8B")); //$NON-NLS-1$
                     }
                 } else if (Util.equalsIgnoreCase("codebase", st.sval)) { //$NON-NLS-1$
                     if (st.nextToken() == '"') {
-                        ge.codebase = st.sval;
+                        ge.setCodebase(st.sval);
                     } else {
                         handleUnexpectedToken(st, Messages.getString("security.8C")); //$NON-NLS-1$
                     }
@@ -230,7 +242,7 @@ public class DefaultPolicyScanner {
                 break;
 
             case '{':
-                ge.permissions = readPermissionEntries(st);
+                ge.setPermissions(readPermissionEntries(st));
                 break parsing;
 
             default: // handle token in the main loop
@@ -393,6 +405,229 @@ public class DefaultPolicyScanner {
                 composeStatus(st)));
     }
 
+    private SortedSet<Segment> segment(String s, Properties p) throws ExpansionFailedException{
+        final String ARRAY_START_MARK = "${{";
+        final String ARRAY_END_MARK = "}}";
+        final String ARRAY_SEPARATOR = ":";
+        final String START_MARK = "${"; //$NON-NLS-1$
+        final String END_MARK = "}"; //$NON-NLS-1$
+        SortedSet<Segment> stringSegments = new TreeSet<Segment>();
+        Segment primary = new Segment(s, null);
+        Collection<Segment> segments 
+                = primary.divideAndReplace(ARRAY_START_MARK, ARRAY_END_MARK,
+                ARRAY_SEPARATOR, p);
+        Iterator<Segment> i = segments.iterator();
+        while (i.hasNext()){
+            stringSegments.addAll(i.next().divideAndReplace(
+                    START_MARK, END_MARK, null, p));
+        }
+        return stringSegments;
+    }
+    
+    protected final Collection<String> expandPolicyProperties(String s, Properties p){
+        Collection<StringBuilder> cache = new ArrayList<StringBuilder>();
+        final String ARRAY_START_MARK = "${{";
+        final String ARRAY_END_MARK = "}}";
+        final String ARRAY_SEPARATOR = ":";
+        final String START_MARK = "${"; //$NON-NLS-1$
+        final String END_MARK = "}"; //$NON-NLS-1$
+        // Check for array's first, for every array, we must clone and create
+        // a new string, with the array substituted.  If there are multiple
+        // arrays, then we must clone for each.
+        // It would be more efficient to use a pattern match to avoid
+        // mutiple processing.
+        Collection<Key> keys = getKeys(p, s, ARRAY_START_MARK, ARRAY_END_MARK);
+        Iterator<Key> i = keys.iterator();
+        int uniqueStrings = 1;
+        while (i.hasNext()){
+            Key k = i.next();
+            while (k != null){
+                short valueCount = k.valueCount(ARRAY_SEPARATOR);
+                uniqueStrings = valueCount * uniqueStrings;
+            }
+        }
+        if ( uniqueStrings < 0 ) throw new IllegalStateException("integer overflow");
+        Collection<String> result = new ArrayList<String>(uniqueStrings);
+        // Now we must replace each key with a value such that we have
+        // X unique stings where:
+        // X = key1.valueCount() * key2.valueCount() ... * keyn.valueCount()
+        Key[] keyArray = keys.toArray(new Key[keys.size()]);
+        StringBuilder sb = new StringBuilder(); // Key builder
+        int lastKey = keyArray.length;
+        for ( int u = 0; u < uniqueStrings ; u++ ){
+            if ( lastKey > 1){
+                for ( int k = 0; k < lastKey; k++ ){
+                    if (keyArray[k] == null) continue;
+                    // Key builder (for building keys) we use for matching.
+                    sb.append(ARRAY_START_MARK)
+                        .append(keyArray[k].toString())
+                        .append(ARRAY_END_MARK);
+                    String primaryKey = sb.toString();
+                    sb.delete(0, sb.length()); // Clear the builder for next use.
+                    Collection<String> values = 
+                            keyArray[k].expandValues(ARRAY_SEPARATOR);
+                    String[] value = values.toArray(new String[values.size()]);
+                    int lastValue = value.length;
+                    for ( int v = 0; v < lastValue; v++ ){
+                        if (value[v] == null) continue;
+                        // Now replace all keys in the string with a value.
+                        // for the primary key's value, do this until we have 
+                        // exhausted the other key's values.
+                        // Add each new string to the cache.
+                        StringBuilder line = new StringBuilder(64 + s.length()); //extra space for values.
+                        boolean primaryKeyIsReplaced = false;
+                        line.append(s);
+                        for ( int kN = 0; kN < lastKey; kN++){
+                            if ( kN == k || keyArray[kN] == null ) continue; // ignore self.
+                            sb.append(ARRAY_START_MARK)
+                                .append(keyArray[kN].toString())
+                                .append(ARRAY_END_MARK);
+                            String secondaryKey = sb.toString();
+                            sb.delete(0, sb.length()); // Clear the builder for next use.
+                            // We are now ready to create our unique string.
+                            // each key value must be combined with each
+                            // value from each other key.
+                            Iterator<String> kNvalues = keyArray[kN]
+                                    .expandValues(ARRAY_SEPARATOR).iterator();
+                            while (kNvalues.hasNext()){
+                                // In all honesty, we have a problem now if
+                                // there is more than one identical key, how
+                                // do we ensure we replace only the correct
+                                // position in the string?
+                                // Ans: Replace them in order of occurance in the
+                                // key array.
+                                if (k < kN){ // replace k first.
+                                    // We must create a new line for every
+                                    // value. the above iterator won't work.
+                                } else { // replace kN first.
+                                    
+                                }
+                            }
+                        }
+                    }
+                }
+            }         
+        }
+
+        return result;
+    }
+    
+ 
+    protected static Collection<String> expandStringValues(String value, String separator){
+        Collection<String> result = new ArrayList<String>();
+        StringBuilder b = new StringBuilder(value);
+        int sep = b.indexOf(separator);
+        final int start = 0;
+        while (sep > 0){
+            String sub = b.substring(start, sep + 1);
+            b.delete(start, sep +1);
+            sep = b.indexOf(separator);
+            result.add(sub);
+        }
+        return result;
+    }
+    
+    protected final Collection<Key> getKeys(Properties p, String keys, 
+            String START_MARK, String END_MARK)
+    {
+        Collection<Key> result = new ArrayList<Key>();
+        final int START_OFFSET = START_MARK.length();
+        final int END_OFFSET = END_MARK.length();
+        int start = keys.indexOf(START_MARK);
+        while (start >= 0){
+            int end = keys.indexOf(END_MARK, start);
+            if (end >= 0) {
+                String key = (keys.substring(start + START_OFFSET, end));
+                result.add(new Key(p,key));
+                start = keys.indexOf(START_MARK, end + END_OFFSET);
+            }
+        }
+        return result;
+    }
+    
+    
+//    protected final String getNextKey(String s, String START_MARK,
+//            String END_MARK, int from)
+//    {
+//        final int START_OFFSET = START_MARK.length();
+//        int start = s.indexOf(START_MARK, from);
+//        if (start >= 0){
+//            int end = s.indexOf(END_MARK , start + START_OFFSET);
+//            if (end >= 0) {
+//                String key = s.substring(start + START_OFFSET, end);
+//                return key;
+//            }
+//        }
+//        return "";
+//    }    
+    
+    /*
+     * A string is made up of string segments and key's, if we create an array
+     * which has string segments and keys represented by array elements, we
+     * can use a string builder for every possible combination and simply build
+     * each possible combination.  Also by finding the array key's first, 
+     * we can then find simpler key's that don't contain arrays in the segment
+     * and replace those immediately.
+     * 
+     * The array key's 
+     */
+    public final static class Key {
+        
+        public static final Key nullKey = new Key();
+        private final String key;
+        private final String value;
+        private Collection<String> values;
+        private String separator;
+        
+        public Key(Properties p, String key){
+            this.key = key;
+            String v = p.getProperty(key);
+            value = v == null ? "" : v;
+            values = null;
+            separator = null;
+        }
+        
+        private Key(){
+            key = "";
+            value = "";
+        }
+        
+        public final String getValue(){
+            return value;
+        }
+        
+        public short valueCount(String separator){
+            short result;
+            if (values != null 
+                && this.separator != null 
+                && this.separator.equals(separator)
+               ) result = (short) values.size();
+            values = expandStringValues(value, separator);
+            result = (short) values.size();
+            if (result < 0) throw new IllegalStateException("short overflow");
+            return result;
+        }
+        
+        public Collection<String> expandValues(String separator){
+            if (values != null 
+                && this.separator != null 
+                && this.separator.equals(separator)
+               ) return values;            
+            values = expandStringValues(value, separator);
+            return values;
+        }
+        
+        @Override
+        public final String toString(){
+            return key;
+        }
+        
+        public final boolean isNull(){
+            if (key.isEmpty()) return true;
+            return false;
+        }
+    }
+
     /**
      * Compound token representing <i>keystore </i> clause. See policy format
      * {@link org.apache.river.imp.security.policy.se.ConcurrentPolicyFile description}for details.
@@ -426,33 +661,111 @@ public class DefaultPolicyScanner {
          * The signers part of grant clause. This is a comma-separated list of
          * certificate aliases.
          */
-        public String signers;
+        private String signers;
 
         /**
          * The codebase part of grant clause. This is an URL from which code
-         * originates.
+         * originates.  Comma separate list allowed?
+         */
+        private String codebase;
+
+        /**
+         * If there is an array string of codebases, use this field instead.
          */
-        public String codebase;
+        private Collection<String> codebases;
 
         /**
          * Collection of PrincipalEntries of grant clause.
          */
-        public Collection<PrincipalEntry> principals;
+        private Collection<PrincipalEntry> principals;
 
         /**
          * Collection of PermissionEntries of grant clause.
          */
-        public Collection<PermissionEntry> permissions;
+        private Collection<PermissionEntry> permissions;
 
         /**
          * Adds specified element to the <code>principals</code> collection.
          * If collection does not exist yet, creates a new one.
          */
         public void addPrincipal(PrincipalEntry pe) {
-            if (principals == null) {
-                principals = new HashSet<PrincipalEntry>();
+            if (getPrincipals(null) == null) {
+                setPrincipals(new HashSet<PrincipalEntry>());
             }
-            principals.add(pe);
+            getPrincipals(null).add(pe);
+        }
+
+        /**
+         * @return the signers
+         */
+        public String getSigners() {
+            return signers;
+    }
+
+    /**
+         * @param signers the signers to set
+         */
+        public void setSigners(String signers) {
+            this.signers = signers;
+        }
+
+        /**
+         * @return the codebase
+         */
+        public String getCodebase(Properties system) {
+            if (system == null) return codebase;
+            try {
+                return PolicyUtils.expand(codebase, system);
+            } catch (ExpansionFailedException ex) {
+                Logger.getLogger(DefaultPolicyScanner.class.getName()).log(Level.SEVERE, null, ex);
+                return codebase;
+            }
+        }
+
+        /**
+         * Set the the codebase string.
+         * @param codebase the codebase to set
+         */
+        public void setCodebase(String codebase) {
+            this.codebase = codebase;
+        }
+
+        /**
+         * Check this first?  Or just get this and iterate?
+         * @return the codebases
+         */
+        public Collection<String> getCodebases(Properties system) {
+            
+            
+            return codebases;
+        }
+
+        /**
+         * @return the principals
+         */
+        public Collection<PrincipalEntry> getPrincipals(Properties system) {
+            return principals;
+        }
+
+        /**
+         * @param principals the principals to set
+         */
+        public void setPrincipals(Collection<PrincipalEntry> principals) {
+            this.principals = principals;
+        }
+
+        /**
+         * @return the permissions
+         */
+        public Collection<PermissionEntry> getPermissions() {
+            return permissions;
+        }
+
+        /**
+         * @param permissions the permissions to set
+         */
+        public void setPermissions(Collection<PermissionEntry> permissions) {
+            this.permissions = permissions;
         }
 
     }

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=1173631&r1=1173630&r2=1173631&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 Wed Sep 21 13:35:29 2011
@@ -242,7 +242,7 @@ public class Messages {
         // Attempt to load the messages.
         try {
             bundle = setLocale(Locale.getDefault(),
-                    "org.apache.harmony.security.internal.nls.messages"); //$NON-NLS-1$
+                    "org.apache.river.security.policy.util.messages"); //$NON-NLS-1$
         } catch (Throwable e) {
             e.printStackTrace();
         }

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/security/policy/util/PolicyUtils.java Wed Sep 21 13:35:29 2011
@@ -24,8 +24,10 @@
 package org.apache.river.impl.security.policy.util;
 
 import java.io.File;
+import java.io.IOException;
 import java.io.InputStream;
 import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.net.URL;
@@ -74,7 +76,7 @@ public class PolicyUtils {
         /** 
          * Returns InputStream from the target URL.
          */
-        public InputStream run() throws Exception {
+        public InputStream run() throws IOException {
             return location.openStream();
         }
     }
@@ -144,18 +146,28 @@ public class PolicyUtils {
      */
     public static String expand(String str, Properties properties)
             throws ExpansionFailedException {
+        final String ARRAY_START_MARK = "${{";
+        final String ARRAY_END_MARK = "}}";
         final String START_MARK = "${"; //$NON-NLS-1$
         final String END_MARK = "}"; //$NON-NLS-1$
-        final int START_OFFSET = START_MARK.length();
-        final int END_OFFSET = END_MARK.length();
 
+        if ( str.indexOf(ARRAY_START_MARK) > 0) {
+            return process(str, properties, ARRAY_START_MARK, ARRAY_END_MARK);
+        }
+        return process(str, properties, START_MARK, END_MARK);
+    }
+    
+    private static String process(String str, Properties p, String START_MARK,
+            String END_MARK) throws ExpansionFailedException{
         StringBuilder result = new StringBuilder(str);
+        final int START_OFFSET = START_MARK.length();
+        final int END_OFFSET = END_MARK.length();
         int start = result.indexOf(START_MARK);
         while (start >= 0) {
             int end = result.indexOf(END_MARK, start);
             if (end >= 0) {
                 String key = result.substring(start + START_OFFSET, end);
-                String value = properties.getProperty(key);
+                String value = p.getProperty(key);
                 if (value != null) {
                     result.replace(start, end + END_OFFSET, value);
                     start += value.length();
@@ -202,6 +214,7 @@ public class PolicyUtils {
                     return codebase.toURI().normalize().toURL();
                 }
             } catch (Exception e) {
+                if ( e instanceof SecurityException ) throw (SecurityException) e;
                 // Ignore
             }
         }
@@ -378,8 +391,8 @@ public class PolicyUtils {
                     if (dynamicURL == null) {
                         dynamicURL = new URL(location);
                     }
-                }
-                catch (Exception e) {
+                } catch (Exception e) {
+                    if ( e instanceof SecurityException ) throw (SecurityException) e;
                     // TODO: log error
                     System.err.println("Error detecting system policy location: "+e);
                 }
@@ -402,6 +415,7 @@ public class PolicyUtils {
                     }
                 }
                 catch (Exception e) {
+                    if ( e instanceof SecurityException ) throw (SecurityException) e;
                     // TODO: log error
                     System.err.println("Error detecting security policy location: "+e);
                 }
@@ -502,7 +516,10 @@ public class PolicyUtils {
      * @throws Exception any exception thrown by Constructor.newInstance()
      */
     public static Permission instantiatePermission(Class<?> targetType,
-            String targetName, String targetActions) throws Exception {
+            String targetName, String targetActions)
+            throws InstantiationException, IllegalAccessException, 
+            IllegalArgumentException, InvocationTargetException 
+    {
 
         // let's guess the best order for trying constructors
         Class[][] argTypes = null;

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentCollections.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentCollections.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentCollections.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentCollections.java Wed Sep 21 13:35:29 2011
@@ -1,262 +0,0 @@
-/*
- * 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.impl.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();
-	    }
-        }
-    }
-}

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentSoftMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentSoftMap.java?rev=1173631&r1=1173630&r2=1173631&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentSoftMap.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ConcurrentSoftMap.java Wed Sep 21 13:35:29 2011
@@ -1,230 +0,0 @@
-/*
- * 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.impl.util;
-
-
-import java.lang.ref.ReferenceQueue;
-import java.lang.ref.SoftReference;
-import java.util.Collection;
-import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.ConcurrentMap;
-
-/**
- * A Sofly referenced hash map, safe for concurrent threads.
- * 
- * Based on an underlying ConcurrentHashMap, it doesn't accept null keys.
- *
- * Key's must not be mutated, soing so will cause strange results.
- *
- * @param K - key
- * @param V - value
- * @author Peter Firmstone.
- *
- * @since 2.3
- */
-public class ConcurrentSoftMap<K, V> implements ConcurrentMap<K, V> {
-    // ConcurrentHashMap must be protected from null values;
-    private final ConcurrentHashMap<Key, V> map;
-    private final ReferenceQueue queue;
-    
-    public ConcurrentSoftMap(int initialCapacity, float loadFactor, int concurrencyLevel ){
-	map = new ConcurrentHashMap<Key, V>(initialCapacity, loadFactor, concurrencyLevel);
-	queue = new ReferenceQueue();
-    }
-    
-    public ConcurrentSoftMap(int initialCapacity, float loadFactor){
-	this(initialCapacity, loadFactor, 16);
-    }
-    
-    public ConcurrentSoftMap(int initialCapacity ){
-	this(initialCapacity, 0.75F, 16);
-    }
-    
-    public ConcurrentSoftMap(){
-	this(16, 0.75F, 16);
-    }
-    
-    /**
-     * Associates value with given key, returning value previously associated
-     * with key, or null if none.
-     * @param key - Key
-     * @param value - Value
-     * @return previous value or null
-     */
-    public V put(K key, V value) {
-	processQueue();
-        if (key == null){return null;}
-	return map.put(Key.create(key, queue), value);
-    }
-
-    /**
-     * Returns value associated with given key, or null if none.
-     */
-    public V get(Object key) {
-	processQueue();
-        if (key == null) { return null;}
-	return map.get(Key.create(key, null));
-    }
-
-    /**
-     * Removes association for given key, returning value previously associated
-     * with key, or null if none.
-     */
-    public V remove(Object key) {
-	processQueue();
-        if (key == null) {return null;}
-	return map.remove(Key.create(key, null));
-    }
-
-    /**
-     * Returns collection containing all values currently held in this map.
-     */
-    public Collection<V> values() {
-	processQueue();
-	return map.values();
-    }
-
-    /**
-     * Removes all associations from this map.
-     */
-    public void clear() {
-	processQueue();
-	map.clear();
-    }
-
-    private void processQueue() {
-	Key k;
-	while ((k = (Key) queue.poll()) != null) {
-	    map.remove(k);
-	}
-    }
-
-    private static class Key<T> extends SoftReference<T> {
-	private final int hash;
-
-        @SuppressWarnings("unchecked")
-	static Key create(Object k, ReferenceQueue q) {
-            //if (k == null) {return null;} // Perhaps this is incorrect
-	    if (q == null) {return new Key(k);}
-	    return new Key(k, q);	  
-	}
-	
-	private Key(T k) {
-	    super(k);
-	    hash = k.hashCode();
-	}
-
-	private Key(T k, ReferenceQueue<? super T> q) {
-	    super(k, q);
-	    hash = k.hashCode();
-	}
-
-        @Override
-	public boolean equals(Object o) {
-	    if (this == o) return true;
-	    // Don't worry about hashcode because they're already equal.
-	    if (!(o instanceof Key)) return false;    
-	    Object k1 = get(), k2 = ((Key) o).get();
-	    return (k1 != null && k1.equals(k2));
-	}
-
-        @Override
-	public int hashCode() {
-	    return hash;
-	}
-    }
-
-    public int size() {
-        processQueue();
-        return map.size();
-    }
-
-    public boolean isEmpty() {
-        processQueue();
-        return map.isEmpty();
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean containsKey(Object key) {
-        processQueue();
-        if (key == null) {return false;}
-        return map.containsKey(new Key(key));
-    }
-
-    public boolean containsValue(Object value) {
-        processQueue();
-        if (value == null) {return false;}
-        return map.containsValue(value);
-    }
-    
-    /**
-     * Unsupported method
-     * @param m
-     */
-    public void putAll(Map<? extends K, ? extends V> m) {
-        throw new UnsupportedOperationException("Not supported yet.");
-    }
-    
-    @SuppressWarnings("unchecked")
-    public Set<K> keySet() {
-        processQueue();
-        Enumeration<Key> keys = map.keys(); //Defensive copy by ConcurrentHashMap
-        Set<K> keySet = new HashSet<K>();
-        while (keys.hasMoreElements()){
-            keySet.add( (K) keys.nextElement().get());
-        }
-        return keySet;
-    }
-    
-    /**
-     * Unsupported method
-     * @return
-     */
-    public Set<Map.Entry<K, V>> entrySet() {
-        throw new UnsupportedOperationException("Not supported yet, ever?");
-    }
-
-    @SuppressWarnings("unchecked")
-    public V putIfAbsent(K key, V value) {
-        processQueue();  //may be a slight delay before atomic putIfAbsent
-        return map.putIfAbsent(new Key(key), value);       
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean remove(Object key, Object value) {
-        return map.remove(new Key(key), value);
-    }
-
-    @SuppressWarnings("unchecked")
-    public boolean replace(K key, V oldValue, V newValue) {
-        processQueue();
-        return map.replace(new Key(key), oldValue, newValue);
-    }
-
-    @SuppressWarnings("unchecked")
-    public V replace(K key, V value) {
-        processQueue();
-        return map.replace(new Key(key), value);
-    }
-}