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 2012/01/17 13:45:56 UTC

svn commit: r1232399 - in /river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river: api/security/ impl/util/

Author: peter_firmstone
Date: Tue Jan 17 12:45:56 2012
New Revision: 1232399

URL: http://svn.apache.org/viewvc?rev=1232399&view=rev
Log:
sun.security.provider.PolicyFile has issues with PrivilegedAction's when DelegateCombinerSecurityManager and Security are on the call stack (picked up in the privileged context), this can cause a infinitely circular call stack, back to the policy as it attempts to retrieve the permissions for the DelegateCombinerSecurityManager and net.jini.security.Security ProtectionDomain, until a StackOverflowError is thrown.

Modified checked context to ignore the ProtectionDomain for DelegatCombinerSecurityManager and net.jini.security.Security.

Consider moving SecurityManager into jsk-policy.jar

Modified:
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceGrant.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DefaultPolicyParser.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DelegateCombinerSecurityManager.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrant.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilder.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PrincipalGrant.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/RC.java
    river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceMap.java

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceGrant.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceGrant.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceGrant.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceGrant.java Tue Jan 17 12:45:56 2012
@@ -20,9 +20,11 @@ package org.apache.river.api.security;
 
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
+import java.security.AccessController;
 import java.security.CodeSource;
 import java.security.Permission;
 import java.security.Principal;
+import java.security.PrivilegedAction;
 
 /**
  *
@@ -39,7 +41,7 @@ class CodeSourceGrant extends Certificat
         super( cs != null? cs.getCertificates(): null, pals, perm);
         this.cs = cs != null? normalizeCodeSource(cs) : null;
         int hash = 3;
-        hash = 67 * hash + (this.cs != null ? this.cs.hashCode() : 0);
+        hash = 67 * hash + (this.cs != null ? this.cs.hashCode() : 0); // This may cause network or file access.
         hash = 67 * hash + (super.hashCode());
         hashCode = hash;
     }
@@ -54,15 +56,23 @@ class CodeSourceGrant extends Certificat
         if (o == null) return false;
         if (o == this) return true;
 	if (o.hashCode() != this.hashCode()) return false;
+        Boolean result = Boolean.FALSE;
         if (o instanceof CodeSourceGrant){
-            CodeSourceGrant c = (CodeSourceGrant) o;
             if ( !super.equals(o)) return false;
-	    if ( cs == c.cs) return true;
-	    if ( cs != null ) {
-		if (cs.equals(c.cs)) return true;
-	    }
+            final CodeSourceGrant c = (CodeSourceGrant) o;
+            if ( cs == c.cs) return true;
+            result = AccessController.doPrivileged(
+                new PrivilegedAction<Boolean>(){
+                    public Boolean run(){
+                        if ( cs != null ) {
+                            if (cs.equals(c.cs)) return Boolean.TRUE;
+                        }
+                        return Boolean.FALSE;
+                    }
+                }
+            );
         }
-        return false;
+        return result.booleanValue();
     }
     
     @Override
@@ -89,14 +99,23 @@ class CodeSourceGrant extends Certificat
      * imply() method.
      */
     @Override
-    public boolean implies(CodeSource codeSource, Principal[] p) {
+    public boolean implies(final CodeSource codeSource, Principal[] p) {
         if ( !implies(p)) return false;
         // sun.security.provider.PolicyFile compatibility for null CodeSource.
         // see com.sun.jini.test.spec.policyprovider.dynamicPolicyProvider.GrantPrincipal test.
         if ( codeSource == null ) return false; 
 	if ( cs == null || nullCS.equals(cs)) return true;
-	return cs.implies(normalizeCodeSource(codeSource));
-        }
+        Boolean result = AccessController.doPrivileged(new PrivilegedAction<Boolean>(){
+
+            @Override
+            public Boolean run() {
+                Boolean outcome = cs.implies(normalizeCodeSource(codeSource)) ? Boolean.TRUE : Boolean.FALSE;
+                return outcome;
+            }
+            
+        });
+	return result;
+    }
 
     @Override
     public PermissionGrantBuilder getBuilderTemplate() {

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/CodeSourceSetGrant.java Tue Jan 17 12:45:56 2012
@@ -20,9 +20,11 @@ package org.apache.river.api.security;
 
 import java.io.InvalidObjectException;
 import java.io.ObjectInputStream;
+import java.security.AccessController;
 import java.security.CodeSource;
 import java.security.Permission;
 import java.security.Principal;
+import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
@@ -65,15 +67,24 @@ class CodeSourceSetGrant extends Certifi
         if (o == null) return false;
         if (o == this) return true;
 	if (o.hashCode() != this.hashCode()) return false;
+        Boolean result = Boolean.FALSE;
         if (o instanceof CodeSourceSetGrant){
-            CodeSourceSetGrant c = (CodeSourceSetGrant) o;
+            final CodeSourceSetGrant c = (CodeSourceSetGrant) o;
             if ( !super.equals(o)) return false;
-	    if ( cs == c.cs) return true;
-	    if ( cs != null ) {
-		if (cs.equals(c.cs)) return true;
-	    }
+            result = AccessController.doPrivileged( 
+                new PrivilegedAction<Boolean>(){
+                    @Override
+                    public Boolean run() {
+                        if ( cs == c.cs) return Boolean.TRUE;
+                        if ( cs != null ) {
+                            if (cs.equals(c.cs)) return Boolean.TRUE;
+                        }
+                        return Boolean.FALSE;
+                    }
+                }
+            );
         }
-        return false;
+        return result.booleanValue();
     }
     
     @Override
@@ -106,14 +117,22 @@ class CodeSourceSetGrant extends Certifi
         // see com.sun.jini.test.spec.policyprovider.dynamicPolicyProvider.GrantPrincipal test.
         if ( codeSource == null ) return false; 
 	if ( cs == null || cs.isEmpty()) return true;
-        codeSource = normalizeCodeSource(codeSource);
-        Iterator<CodeSource> it = cs.iterator();
-        while (it.hasNext()){
-            CodeSource c = it.next();
-            if (c == null ) return true;
-            if  (c.implies(codeSource)) return true;
-        }
-        return false;
+        final CodeSource normalizedCodeSource = normalizeCodeSource(codeSource);
+        Boolean result = AccessController.doPrivileged(
+            new PrivilegedAction<Boolean>(){
+                @Override
+                public Boolean run() {
+                    Iterator<CodeSource> it = cs.iterator();
+                    while (it.hasNext()){
+                        CodeSource c = it.next();
+                        if (c == null ) return Boolean.TRUE;
+                        if  (c.implies(normalizedCodeSource)) return Boolean.TRUE;
+                    }
+                    return Boolean.FALSE;
+                }
+            }
+        );
+        return result.booleanValue();
     }
 
     @Override

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DefaultPolicyParser.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DefaultPolicyParser.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DefaultPolicyParser.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/DefaultPolicyParser.java Tue Jan 17 12:45:56 2012
@@ -84,14 +84,14 @@ class DefaultPolicyParser implements Pol
      * {@link org.apache.river.imp.security.policy.util.DefaultPolicyScanner DefaultPolicyScanner} 
      * is used. 
      */
-    DefaultPolicyParser() {
+    public DefaultPolicyParser() {
         scanner = new DefaultPolicyScanner();
     }
 
     /** 
      * Extension constructor for plugging-in custom scanner.
      */
-    public DefaultPolicyParser(DefaultPolicyScanner s) {
+    DefaultPolicyParser(DefaultPolicyScanner s) {
         this.scanner = s;
     }
 
@@ -445,7 +445,7 @@ class DefaultPolicyParser implements Pol
      * @throws Exception if KeyStore is <code>null</code> 
      * or if it failed to provide a certificate  
      */
-    protected Certificate[] resolveSigners(KeyStore ks, String signers)
+    Certificate[] resolveSigners(KeyStore ks, String signers)
             throws Exception {
         if (ks == null) {
             throw new KeyStoreException(Messages.getString("security.146", //$NON-NLS-1$
@@ -472,7 +472,7 @@ class DefaultPolicyParser implements Pol
      * @throws CertificateException if found certificate is not 
      * an X509Certificate 
      */
-    protected Principal getPrincipalByAlias(KeyStore ks, String alias)
+    Principal getPrincipalByAlias(KeyStore ks, String alias)
             throws KeyStoreException, CertificateException {
 
         if (ks == null) {
@@ -504,7 +504,7 @@ class DefaultPolicyParser implements Pol
      * @param resolve flag enabling/disabling property expansion
      * @return the first successfully loaded KeyStore or <code>null</code>
      */
-    protected KeyStore initKeyStore(List<KeystoreEntry>keystores,
+    KeyStore initKeyStore(List<KeystoreEntry>keystores,
             URL base, Properties system, boolean resolve) {
         for (int i = 0; i < keystores.size(); i++) {
             try {

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=1232399&r1=1232398&r2=1232399&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 Tue Jan 17 12:45:56 2012
@@ -28,6 +28,7 @@ import java.security.PrivilegedAction;
 import java.security.ProtectionDomain;
 import java.security.SecurityPermission;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Comparator;
 import java.util.HashSet;
@@ -87,16 +88,22 @@ extends SecurityManager implements Deleg
     private final Comparator<Referrer<Permission>> permCompare;
     private final AccessControlContext SMConstructorContext;
     private final AccessControlContext SMPrivilegedContext;
+    private final ProtectionDomain privilegedDomain;
     private final ThreadLocal<SecurityContext> threadContext;
     private final ThreadLocal<Boolean> inTrustedCodeRecursiveCall;
+    private final Object lock;
+    private volatile int revocation_id;
     
     public DelegateCombinerSecurityManager(){
         super();
+        lock = new Object();
+        revocation_id = 0;
         // Get context before this becomes a SecurityManager.
         // super() checked the permission to create a SecurityManager.
         SMConstructorContext = AccessController.getContext();
         ProtectionDomain [] context = new ProtectionDomain[1];
-        context[0] = this.getClass().getProtectionDomain();
+        privilegedDomain = this.getClass().getProtectionDomain();
+        context[0] = privilegedDomain;
         SMPrivilegedContext = new AccessControlContext(context);
         dc = new DelegateDomainCombiner();
         ConcurrentMap<Referrer<AccessControlContext>, 
@@ -143,10 +150,22 @@ extends SecurityManager implements Deleg
          * This bug may cause contention between ProtectionDomain implies
          * calls, also it could be a point of attack for Denial of service,
          * since the lock used is a static class lock.  This bug has been fixed
-         * in jdk7.
+         * in jdk8(b15).
          */
     }
     
+    @Override
+    public Object getSecurityContext() {
+	Object context = null;
+        inTrustedCodeRecursiveCall.set(Boolean.TRUE);
+        try {
+            context = Security.getContext();
+        }finally {
+            inTrustedCodeRecursiveCall.set(Boolean.FALSE); // Must always happen, no matter what.
+        }
+        return context;
+    }
+    
     /**
      * Throws a <code>SecurityException</code> if the requested
      * access, specified by the given permission, is not permitted based
@@ -162,15 +181,9 @@ extends SecurityManager implements Deleg
      */
     @Override
     public void checkPermission(Permission perm) throws SecurityException {
-        Object context = null;
         Boolean call = inTrustedCodeRecursiveCall.get();
         if (call == Boolean.TRUE) return; // In Security and Policy static methods we trust.
-        inTrustedCodeRecursiveCall.set(Boolean.TRUE);
-        try {
-            context = Security.getContext();
-        }finally {
-            inTrustedCodeRecursiveCall.set(Boolean.FALSE); // Must always happen, no matter what.
-        }
+        Object context = getSecurityContext();
         checkPermission(perm, context);
     }
     
@@ -231,6 +244,9 @@ extends SecurityManager implements Deleg
             if (existed != null) checkedPerms = existed;
         }
         if (checkedPerms.contains(perm)) return; // don't need to check again.
+        // Record the current transaction_id to avoid populating cache with
+        // old successful checks.
+        int rev_id = revocation_id;
         // Cache the created AccessControlContext.
         AccessControlContext delegateContext = contextCache.get(executionContext);
         if (delegateContext == null ) {
@@ -263,7 +279,12 @@ extends SecurityManager implements Deleg
         delegateContext.checkPermission(perm); // Throws SecurityException.
         /* It's ok to cache SocketPermission if we use a comparator */
         // If we get to here, no exceptions were thrown, caller has permission.
-        checkedPerms.add(perm);
+        if ( rev_id == revocation_id) {
+            checkedPerms.add(perm);
+            // Because the revocation_id is not an atomic check, it might change
+            // after we've just added the permission, if so remove it.
+            if ( rev_id != revocation_id) checkedPerms.remove(perm);
+        }
     }
     
     /**
@@ -282,6 +303,21 @@ extends SecurityManager implements Deleg
         // the policy will prevent any being re-added, since these have already 
         // been removed from the policy.
         g.checkGuard(this);
+        synchronized (lock){
+            // Order of operation, permission check records revocation id
+            // before consulting policy, if an interleaved policy operation
+            // then revokes permission, it notifies the SecurityManager after
+            // the policy state has changed.  It is not safe to cache any
+            // permission check that commenced before the policy
+            // revocation completes.
+            // After this is incremented, it is safe to clear the cache or
+            // remove stale entries, the SecurityManager may continue to
+            // allow revoked permissions to be cached until this method
+            // completes, after which it must comply with any revocation.
+            // All threads with method local references to the new revocation 
+            // id will have consulted the policy only after its state was altered.
+            revocation_id++;
+        }
         if (perms == null){
             checked.clear();
             return;
@@ -335,14 +371,45 @@ extends SecurityManager implements Deleg
              * The AccessControlContext instance will be the new instance
              * we just created moments earlier, but with the context returned
              * by this DomainCombiner.
+             *
+             * The SecurityManager's ProtectionDomain must be removed
+             * from the Context, for the following case:
+             * 
+             * If using sun.security.provider.PolicyFile, the policy will
+             * cache it's own domain prior to it being instantiated and it
+             * may perform a PrivilegedAction when it's 
+             * getPermissions(ProtectionDomain pd) is called and the
+             * ProtectionDomain isn't in the policy cache.
+             * However, DelegateCombinerSecurityManager and
+             * net.jini.security.Security cannot cache their shared 
+             * ProtectionDomain, relying on the underlying policy instead.
+             * 
+             * When a standard java permission check
+             * is made, the AccessController picks up the domain of 
+             * DelegateCombinerSecurityManager and net.jini.security.Security,
+             * as well as that of the policy provider.  Since the policy
+             * provider will cache it's own ProtectionDomain, but not that
+             * of the SecurityManager and Security, a infinite circular call 
+             * loop will preceed until a StackOverflowError occurs.
+             * 
+             * This will be caused by PolicyFile, attempting to determine
+             * which permissions apply to the ProtectionDomain of
+             * DelegateCombinerSecurityManager and Security, then asking
+             * the SecurityManager if it has a FilePermission.
+             * 
+             * The policy provider org.apache.river.security.ConcurrentPolicyFile
+             * has no such issue, unless using CodeSource based PermissionGrant's.
              */
-            // I don't believe it's safe to modify the existing array.
-            // I think it's the same context array from the original AccessControlContext
-            // we've duplicated, so modifing it would risk contaminating the 
-            // call stack context.
-            // No defensive copying is performed.
+            int l = assignedDomains.length;
+            List<ProtectionDomain> list = new ArrayList<ProtectionDomain>(l);
+            for (int i = 0; i < l ; i++){
+                if (assignedDomains[i] != privilegedDomain){
+                    list.add(assignedDomains[i]);
+                }
+            }
+            ProtectionDomain [] context = list.toArray(new ProtectionDomain[list.size()]);
             DelegateProtectionDomain[] delegated = new DelegateProtectionDomain[1];
-            delegated[0] = new DelegateProtectionDomain(assignedDomains);
+            delegated[0] = new DelegateProtectionDomain(context);
             return delegated;
         }
     }

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrant.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrant.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrant.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrant.java Tue Jan 17 12:45:56 2012
@@ -26,11 +26,19 @@ import java.util.Collection;
 
 /**
  * PermissionGrant's are expected to be effectively immutable,
- * threadsafe and have a good hashCode implementation to perform well in
+ * thread safe and have a good hashCode implementation to perform well in
  * Collections.
  * 
  * You shouldn't pass around PermissionGrant's to just anyone as they can
- * provide an attacker with information about which Permission's may be granted.
+ * provide an attacker with information about which Permissions may be granted.
+ * 
+ * Caveat Implementor: PermissionGrant's cannot perform privileged actions, 
+ * whilst being used by the policy to make policy decisions, any privileged 
+ * actions should performed prior to creating a PermissionGrant.  
+ * Only PermissionGrant's belonging to the same ProtectionDomain as the
+ * active Policy can perform PrivilegedAction's, since the Policy caches it's 
+ * own domain Permissions during initialisation, it doesn't consult
+ * PermissionGrant's after.
  * 
  * @author Peter Firmstone
  */

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilder.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilder.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilder.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PermissionGrantBuilder.java Tue Jan 17 12:45:56 2012
@@ -53,10 +53,10 @@ public abstract class PermissionGrantBui
      * the CodeSource.  This has been provided for strict compatibility
      * with the standard Java Policy, where a DNS lookup may be performed
      * to determine if CodeSource.implies(CodeSource).  In addition, to
-     * resolve a File URL, will require disk access.
+     * resolve a File URL, it will require disk access.
      * 
-     * This is very bad for Policy performance, so it's use should be
-     * kept to an absolute minimum, it's use is discouraged.
+     * This is very bad for Policy performance, it's use is discouraged,
+     * so much so, it may removed.
      * 
      * @deprecated use URI instead.
      */

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PrincipalGrant.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PrincipalGrant.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PrincipalGrant.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/api/security/PrincipalGrant.java Tue Jan 17 12:45:56 2012
@@ -187,29 +187,29 @@ class PrincipalGrant implements Permissi
     }
       
     /**
-     * Utility Method, really belongs somewhere else, but most subclasses use it.
+     * Utility Method, really belongs somewhere else, but CodeSource subclasses use it.
      * @param codeSource
      * @return
      */
     @Deprecated
     CodeSource normalizeCodeSource(CodeSource codeSource) {
         if (codeSource == null ) return null;
-        URI codeSourceURL = null;
+        URI codeSourceURI = null;
         try {
-            codeSourceURL = PolicyUtils.normalizeURL(codeSource.getLocation());
+            codeSourceURI = PolicyUtils.normalizeURL(codeSource.getLocation());
         } catch (URISyntaxException ex) {
             ex.printStackTrace(System.err);
         }
         CodeSource result = codeSource;
         try {
-            if ( codeSourceURL != null && codeSourceURL.toURL() != codeSource.getLocation()) {
+            if ( codeSourceURI != null && codeSourceURI.toURL() != codeSource.getLocation()) {
                 // URL was normalized - recreate codeSource with new URL
                 CodeSigner[] signers = codeSource.getCodeSigners();
                 if (signers == null) {
-                    result = new CodeSource(codeSourceURL.toURL(), codeSource
+                    result = new CodeSource(codeSourceURI.toURL(), codeSource
                             .getCertificates());
                 } else {
-                    result = new CodeSource(codeSourceURL.toURL(), signers);
+                    result = new CodeSource(codeSourceURI.toURL(), signers);
                 }
             }
         } catch (MalformedURLException ex) {

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/RC.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/RC.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/RC.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/RC.java Tue Jan 17 12:45:56 2012
@@ -19,7 +19,6 @@
 package org.apache.river.impl.util;
 
 import java.lang.ref.Reference;
-import java.lang.Comparable;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Comparator;
@@ -132,6 +131,8 @@ import java.util.concurrent.ConcurrentNa
  * strongly referenced, then changed to the correct reference type.  This
  * will still occur, even if the Collection is immutable.
  * </p><p>
+ * Map's don't currently support Serialization.
+ * </p><p>
  * RC stands for Reference Collection and is abbreviated due to the length of
  * generic parameter arguments typically required.
  * </p>

Modified: river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceMap.java?rev=1232399&r1=1232398&r2=1232399&view=diff
==============================================================================
--- river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceMap.java (original)
+++ river/jtsk/skunk/peterConcurrentPolicy/src/org/apache/river/impl/util/ReferenceMap.java Tue Jan 17 12:45:56 2012
@@ -18,7 +18,6 @@
 
 package org.apache.river.impl.util;
 
-import java.lang.ref.Reference;
 import java.lang.ref.ReferenceQueue;
 import java.util.AbstractMap;
 import java.util.Collection;