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 2013/11/30 13:23:20 UTC

svn commit: r1546722 - in /river/jtsk/skunk/qa_refactor/trunk/src: com/sun/jini/fiddler/ com/sun/jini/landlord/ com/sun/jini/lease/ com/sun/jini/norm/ com/sun/jini/reggie/ net/jini/core/lease/ org/apache/river/api/net/ org/apache/river/api/util/ org/ap...

Author: peter_firmstone
Date: Sat Nov 30 12:23:20 2013
New Revision: 1546722

URL: http://svn.apache.org/r1546722
Log:
Fix concurrency issue with AbstractLease subclasses.

Created a new AbstractLeaseMap implementation that doesn't share internal state with subclasses.

Added:
    river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/util/ID.java
    river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/impl/lease/
    river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/impl/lease/AbstractLeaseMap.java
Modified:
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLease.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLeaseMap.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/ConstrainableLandlordLeaseMap.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLease.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLeaseMap.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLease.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLeaseMap.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ClientLeaseWrapper.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableEventLease.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableServiceLease.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLease.java
    river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLeaseMap.java
    river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/Lease.java
    river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMap.java
    river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMapException.java
    river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLease.java Sat Nov 30 12:23:20 2013
@@ -37,6 +37,7 @@ import java.io.InvalidObjectException;
 import java.io.IOException;
 import java.io.ObjectInputStream;
 import java.rmi.RemoteException;
+import org.apache.river.api.util.ID;
 
 /**
  * When the Fiddler implementation of the lookup discovery service grants
@@ -51,7 +52,7 @@ import java.rmi.RemoteException;
  *
  */
 class FiddlerLease extends AbstractLease 
-                   implements ReferentUuid
+                   implements ReferentUuid, ID<Uuid>
 {
 
     private static final long serialVersionUID = 2L;
@@ -179,7 +180,7 @@ class FiddlerLease extends AbstractLease
      *
      * @see net.jini.core.lease.Lease#createLeaseMap
      */
-    public LeaseMap createLeaseMap(long duration) {
+    public LeaseMap<FiddlerLease,Long> createLeaseMap(long duration) {
         return FiddlerLeaseMap.createLeaseMap(this, duration);
     }
 
@@ -259,19 +260,6 @@ class FiddlerLease extends AbstractLease
     }
 
     /**
-     * Replaces the current value of the <code>expiration</code> field 
-     * (defined in the <code>AbstractLease</code> super class) with the
-     * value contained in the input parameter. The value contained in the
-     * <code>expiration</code> field represents the absolute (non-relative)
-     * time (in milliseconds) at which the current lease will expire.
-     *
-     * @param expiration the new value of the <code>expiration</code> field
-     */
-    void setExpiration(long expiration) {
-        this.expiration = expiration;
-    }
-
-    /**
      * This method allows the entity to which the current lease is granted
      * (the lease holder) to indicate that it is no longer interested
      * in the resources provided to the entity by the lookup discovery
@@ -420,6 +408,14 @@ class FiddlerLease extends AbstractLease
                                          +"deserialize FiddlerLease instance");
     }//end readObjectNoData
 
+    public Uuid identity() {
+        return leaseID;
+    }
+
+    void setExpiration(long expiration) {
+        this.expiration = expiration;
+    }
+
     /** The constrainable version of the class <code>FiddlerLease</code>. 
      *  <p>
      *  When a client obtains an instance of this proxy class, the client
@@ -491,7 +487,7 @@ class FiddlerLease extends AbstractLease
      * @since 2.0
      */
     static final class ConstrainableFiddlerLease extends FiddlerLease
-                                                 implements RemoteMethodControl
+                                                 implements RemoteMethodControl, ID<Uuid>
     {
         static final long serialVersionUID = 2L;
 
@@ -683,6 +679,12 @@ class FiddlerLease extends AbstractLease
                                                         methodMapArray);
         }//end readObject
 
+        public void setExpiration(long expiration) {
+            synchronized (this) {
+                this.expiration = expiration;
+            }
+        }
+
     }//end class ConstrainableFiddlerLease
 
 }//end class FiddlerLease

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLeaseMap.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLeaseMap.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/fiddler/FiddlerLeaseMap.java Sat Nov 30 12:23:20 2013
@@ -17,22 +17,21 @@
  */
 package com.sun.jini.fiddler;
 
-import com.sun.jini.lease.AbstractLeaseMap;
 import com.sun.jini.proxy.ConstrainableProxyUtil;
-
-import net.jini.id.Uuid;
-
+import java.lang.reflect.Method;
+import java.rmi.RemoteException;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
 import net.jini.core.constraint.MethodConstraints;
 import net.jini.core.constraint.RemoteMethodControl;
 import net.jini.core.lease.Lease;
 import net.jini.core.lease.LeaseMap;
 import net.jini.core.lease.LeaseMapException;
-
-import java.lang.reflect.Method;
-import java.rmi.RemoteException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Iterator;
+import net.jini.id.Uuid;
+import org.apache.river.impl.lease.AbstractLeaseMap;
 
 /**
  * When clients request a registration with the Fiddler implementation of
@@ -52,7 +51,7 @@ import java.util.Iterator;
  * @author Sun Microsystems, Inc.
  *
  */
-class FiddlerLeaseMap extends AbstractLeaseMap {
+class FiddlerLeaseMap extends AbstractLeaseMap<FiddlerLease> {
 
     /**
      * The reference to the back-end server of the lookup discovery service
@@ -117,9 +116,10 @@ class FiddlerLeaseMap extends AbstractLe
      *                 is the "mapped" value corresponding to the lease key.
      */
     private FiddlerLeaseMap(Fiddler server, FiddlerLease lease, long duration){
-        super(lease, duration);
+        super();
         this.server = server;
         this.serverID = lease.getServerID();
+        put(lease, duration);
     }//end constructor
 
     /**
@@ -166,37 +166,44 @@ class FiddlerLeaseMap extends AbstractLe
      *         may or may not have been renewed successfully.
      */
     public void renewAll() throws LeaseMapException, RemoteException {
-        int size = map.size();
-        if (size == 0) {
-            return;
+        if (isEmpty()) return;
+        List<FiddlerLease> keys = new LinkedList<FiddlerLease>();
+        List<Uuid> registrationIDs = new LinkedList<Uuid>();
+        List<Uuid> leaseIDs = new LinkedList<Uuid>();
+        List<Long> durations = new LinkedList<Long>();
+        Iterator<Entry<FiddlerLease,Long>> it = entrySet().iterator();
+        while (it.hasNext()){
+            Entry<FiddlerLease,Long> e = it.next();
+            FiddlerLease ls = e.getKey();
+            keys.add(ls);
+            registrationIDs.add(ls.getRegistrationID());
+            leaseIDs.add(ls.getLeaseID());
+            durations.add(e.getValue());
         }
-        Uuid[] registrationIDs = new Uuid[size];
-        Uuid[] leaseIDs = new Uuid[size];
-        long[] durations = new long[size];
+        long [] dur = new long[durations.size()];
         int i = 0;
-        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); i++) {
-            Map.Entry e = (Map.Entry)iter.next();
-            FiddlerLease ls = (FiddlerLease)e.getKey();
-            registrationIDs[i] = ls.getRegistrationID();
-            leaseIDs[i] = ls.getLeaseID();
-            durations[i] = ((Long)e.getValue()).longValue();
+        for (Iterator<Long> durIt = durations.iterator(); durIt.hasNext(); i++){
+            dur[i] = durIt.next().intValue();
         }
-        FiddlerRenewResults results = server.renewLeases(registrationIDs,
-                                                         leaseIDs,
-                                                         durations);
+        FiddlerRenewResults results = server.renewLeases(
+                registrationIDs.toArray(new Uuid[registrationIDs.size()]),
+                leaseIDs.toArray(new Uuid[leaseIDs.size()]),
+                dur
+                );
         long now = System.currentTimeMillis();
-        HashMap emap = (results.exceptions != null) ?
-                         new HashMap(2 * results.exceptions.length + 1) : null;
+        HashMap<Lease,Exception> emap = (results.exceptions != null) ?
+                         new HashMap<Lease,Exception>(2 * results.exceptions.length + 1) : null;
         i = 0;
         int j = 0;
-        for (Iterator iter = map.entrySet().iterator(); iter.hasNext(); i++) {
-            Map.Entry e = (Map.Entry)iter.next();
+        for (Iterator<FiddlerLease> iter = keys.iterator(); iter.hasNext(); i++) {
+            FiddlerLease e = iter.next();
             long duration = results.durations[i];
             if (duration >= 0) {
-                ((FiddlerLease)e.getKey()).setExpiration(duration + now);
+                // Mutation of volatile field
+                e.setExpiration(duration + now);
             } else {
-                emap.put(e.getKey(), results.exceptions[j++]);
-                iter.remove();
+                emap.put(e, results.exceptions[j++]);
+                remove(e);
             }
         }
         if (emap != null) {
@@ -223,30 +230,32 @@ class FiddlerLeaseMap extends AbstractLe
      *         may or may not have been cancelled successfully.
      */
     public void cancelAll() throws LeaseMapException, RemoteException {
-        int size = map.size();
-        if (size == 0) {
-            return;
-        }
-        Uuid[] registrationIDs = new Uuid[size];
-        Uuid[] leaseIDs = new Uuid[size];
+        if( isEmpty()) return;
+        List<FiddlerLease> leases = new LinkedList<FiddlerLease>();
+        List<Uuid> registrationIDs = new LinkedList<Uuid>();
+        List<Uuid> leaseIDs = new LinkedList<Uuid>();
         int i = 0;
-        for (Iterator iter = map.keySet().iterator(); iter.hasNext(); i++) {
-            FiddlerLease ls = (FiddlerLease)iter.next();
-            registrationIDs[i] = ls.getRegistrationID();
-            leaseIDs[i] = ls.getLeaseID();
+        for (Iterator<FiddlerLease> iter = keySet().iterator(); iter.hasNext(); i++) {
+            FiddlerLease ls = iter.next();
+            leases.add(ls);
+            registrationIDs.add(ls.getRegistrationID());
+            leaseIDs.add(ls.getLeaseID());
         }
-        Exception[] exceptions = server.cancelLeases(registrationIDs,leaseIDs);
+        Exception[] exceptions = server.cancelLeases(
+                registrationIDs.toArray(new Uuid[registrationIDs.size()]),
+                leaseIDs.toArray(new Uuid[leaseIDs.size()])
+                );
         if (exceptions == null) {
             return;
         }
         i = 0;
-        HashMap emap = new HashMap(13);
-        for (Iterator iter = map.keySet().iterator(); iter.hasNext(); i++) {
-            FiddlerLease ls = (FiddlerLease)iter.next();
+        Map<Lease,Exception> emap = new HashMap<Lease,Exception>(13);
+        for (Iterator<FiddlerLease> iter = leases.iterator(); iter.hasNext(); i++) {
+            FiddlerLease ls = iter.next();
             Exception ex = exceptions[i];
             if (ex != null) {
                 emap.put(ls, ex);
-                iter.remove();
+                remove(ls);
             }
         }
         throw new LeaseMapException("lease cancellation failures", emap);

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/ConstrainableLandlordLeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/ConstrainableLandlordLeaseMap.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/ConstrainableLandlordLeaseMap.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/ConstrainableLandlordLeaseMap.java Sat Nov 30 12:23:20 2013
@@ -56,12 +56,18 @@ final public class ConstrainableLandlord
     ConstrainableLandlordLeaseMap(Landlord landlord, Uuid landlordUuid, 
 				  LandlordLease lease, long duration) 
     {
-	super(landlord, landlordUuid, lease, duration);
-	if (!(landlord instanceof RemoteMethodControl))
+	super(chLandlord(landlord), landlordUuid, lease, duration);
+	
+    }
+    
+    private static Landlord chLandlord(Landlord landlord) throws ClassCastException {
+        if (!(landlord instanceof RemoteMethodControl))
 	    throw new ClassCastException("landlord must implement " +
 					 "RemoteMethodControl");
+        return landlord;
     }
 
+
     // doc inherited from super
     public boolean canContainKey(Object key) {
 	if (!super.canContainKey(key))

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLease.java Sat Nov 30 12:23:20 2013
@@ -30,6 +30,7 @@ import net.jini.id.Uuid;
 import net.jini.id.ReferentUuid;
 import net.jini.id.ReferentUuids;
 import com.sun.jini.lease.AbstractLease;
+import org.apache.river.api.util.ID;
 
 /**
  * Basic implementation of <code>net.jini.core.lease.Lease</code> that works
@@ -40,7 +41,7 @@ import com.sun.jini.lease.AbstractLease;
  * @see Landlord
  * @since 2.0
  */
-public class LandlordLease extends AbstractLease implements ReferentUuid {
+public class LandlordLease extends AbstractLease implements ReferentUuid, ID<Uuid> {
     static final long serialVersionUID = 2L;
 
     /**
@@ -167,13 +168,11 @@ public class LandlordLease extends Abstr
 
     /** Set the expiration. */
     void setExpiration(long expiration) {
-        synchronized (this){
             this.expiration = expiration;
-        }
     }
 
     // inherit doc comment
-    public LeaseMap createLeaseMap(long duration) {
+    public LeaseMap<? extends Lease,Long> createLeaseMap(long duration) {
 	return new LandlordLeaseMap(landlord, landlordUuid, this, duration);
     }
 
@@ -212,4 +211,9 @@ public class LandlordLease extends Abstr
 	throw new 
 	    InvalidObjectException("LandlordLease should always have data");
     }
+
+    @Override
+    public Uuid identity() {
+        return cookie;
+    }
 }

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLeaseMap.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLeaseMap.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/landlord/LandlordLeaseMap.java Sat Nov 30 12:23:20 2013
@@ -17,16 +17,18 @@
  */
 package com.sun.jini.landlord;
 
-import com.sun.jini.lease.AbstractLeaseMap;
 import java.rmi.RemoteException;
 import java.util.Map;
 import java.util.Iterator;
 import java.util.HashMap;
 import java.util.ConcurrentModificationException;
+import java.util.LinkedList;
+import java.util.List;
 import net.jini.core.lease.Lease;
 import net.jini.core.lease.LeaseMapException;
 import net.jini.id.Uuid;
 import net.jini.id.ReferentUuid;
+import org.apache.river.impl.lease.AbstractLeaseMap;
 
 /**
  * Implementation of <code>LeaseMap</code> for <code>LandlordLease</code>.
@@ -69,16 +71,32 @@ public class LandlordLeaseMap extends Ab
     LandlordLeaseMap(Landlord landlord, Uuid landlordUuid, Lease lease,
 		     long duration) 
     {
-	super(new HashMap(), lease, duration);
+        // Constructor Exception attack not possible, exceptions thrown 
+        // prior to super object creation.
+	this(checkLandlord(landlord), checkLandlordUuid(landlordUuid), checkLease(lease));
+        put(lease, duration); // Guaranteed not to throw an exception.
+    }
+    
+    static Lease checkLease(Lease lease) throws ClassCastException{
         if (!(lease instanceof LandlordLease)) throw 
                 new ClassCastException("Lease must be of type LandlordLease");
-	if (landlord == null)
-	    throw new NullPointerException("Landlord must be non-null");
-
-	if (landlordUuid == null)
+        return lease;
+    }
+    
+    static Uuid checkLandlordUuid(Uuid landlordUuid) throws NullPointerException{
+        if (landlordUuid == null)
 	    throw new NullPointerException("landlordUuid must be non-null");
-
-	this.landlord = landlord;
+        return landlordUuid;
+    }
+    
+    static Landlord checkLandlord( Landlord landlord) throws NullPointerException{
+        if (landlord == null)
+	    throw new NullPointerException("Landlord must be non-null");
+        return landlord;
+    }
+    
+    private LandlordLeaseMap(Landlord landlord, Uuid landlordUuid, Lease lease){
+        this.landlord = landlord;
 	this.landlordUuid = landlordUuid;
     }
 
@@ -94,23 +112,24 @@ public class LandlordLeaseMap extends Ab
     // inherit doc comment
     public void cancelAll() throws LeaseMapException, RemoteException {
         final Map rslt;
-	Uuid[] cookies;
-        LandlordLease[] leases;
-        synchronized (mapLock){
-            cookies = new Uuid[size()];
-            leases = new LandlordLease[cookies.length];
-            Iterator it = keySet().iterator();
-            for (int i = 0; it.hasNext(); i++) {
-                LandlordLease lease = (LandlordLease) it.next();
-                leases[i] = lease;
-                cookies[i] = lease.cookie();
-            }
-            rslt = landlord.cancelAll(cookies);
+	List<Uuid> cookies;
+        List<LandlordLease> leases;
+        cookies = new LinkedList<Uuid>();
+        leases = new LinkedList<LandlordLease>();
+        Iterator<LandlordLease> it = keySet().iterator();
+        for (int i = 0; it.hasNext(); i++) {
+            LandlordLease lease = (LandlordLease) it.next();
+            leases.add(lease);
+            cookies.add(lease.cookie());
         }
+        
+        Uuid[] cookiesA = cookies.toArray(new Uuid[cookies.size()]);
+        rslt = landlord.cancelAll(cookiesA);
 	if (rslt == null) {
 	    // Everything worked out, normal return
 	    return;
 	} else {
+            LandlordLease[] leasesA = leases.toArray(new LandlordLease[leases.size()]);
 	    // Some the leases could not be canceled, generate a
 	    // LeaseMapException
 	    
@@ -118,13 +137,14 @@ public class LandlordLeaseMap extends Ab
 	    // lease->exception map
 
 	    int origSize = rslt.size();
-	    for (int i = 0; i < cookies.length; i++) {
-		Object exception = rslt.remove(cookies[i]); 
+            int len = cookiesA.length;
+	    for (int i = 0; i < len; i++) {
+		Object exception = rslt.remove(cookiesA[i]); 
 		// remove harmless if not in map 
 
 		if (exception != null) {	     // if it was in map
-		    rslt.put(leases[i], exception);  // put back as lease
-		    remove(leases[i]);		     // remove from this map
+		    rslt.put(leasesA[i], exception);  // put back as lease
+		    remove(leasesA[i]);		     // remove from this map
 		}
 	    }
 
@@ -139,43 +159,47 @@ public class LandlordLeaseMap extends Ab
 
     // inherit doc comment
     public void renewAll() throws LeaseMapException, RemoteException {
-        Uuid[] cookies;
-	long[] extensions;
-	LandlordLease[] leases;
-        synchronized (mapLock){
-            cookies = new Uuid[size()];
-            extensions = new long[cookies.length];
-            leases = new LandlordLease[cookies.length];
-            Iterator it = keySet().iterator();
-            for (int i = 0; it.hasNext(); i++) {
-                LandlordLease lease = (LandlordLease) it.next();
-                leases[i] = lease;
-                cookies[i] = lease.cookie();
-                extensions[i] = ((Long) get(lease)).longValue();
-            }
+        List<Uuid> cookies;
+	List<Long> extensions;
+	List<LandlordLease> leases;
+        cookies = new LinkedList<Uuid>();
+        extensions = new LinkedList<Long>();
+        leases = new LinkedList<LandlordLease>();
+        Iterator it = keySet().iterator();
+        for (int i = 0; it.hasNext(); i++) {
+            LandlordLease lease = (LandlordLease) it.next();
+            leases.add(lease);
+            cookies.add(lease.cookie());
+            extensions.add(get(lease));
         }
+        long[] extensionsA = new long[extensions.size()];
+        Iterator<Long> ite = extensions.iterator();
+        for ( int i = 0; ite.hasNext(); i++){
+            extensionsA[i] = ite.next().longValue();
+        }
+        Uuid [] cookiesA = cookies.toArray(new Uuid[cookies.size()]);
+        LandlordLease [] leasesA = leases.toArray(new LandlordLease[leases.size()]);
 	long now = System.currentTimeMillis();
-	Landlord.RenewResults results = 
-	    landlord.renewAll(cookies, extensions);
-
+	Landlord.RenewResults results = landlord.renewAll(cookiesA, extensionsA);
 	Map bad = null;
 	int d = 0;
-	for (int i = 0; i < cookies.length; i++) {
+        int len = cookiesA.length;
+	for (int i = 0; i < len; i++) {
 	    if (results.granted[i] != -1) {
 		long newExp = now + results.granted[i];
 		if (newExp < 0) // Overflow, set to Long.MAX_VALUE
 		    newExp = Long.MAX_VALUE;
 		    
-		leases[i].setExpiration(newExp);
+		leasesA[i].setExpiration(newExp);
 	    } else {
 		if (bad == null) {
 		    bad = new HashMap(results.denied.length +
 				      results.denied.length / 2);
 		}
-		Object badTime = remove(leases[i]);   // remove from this map
+		Object badTime = remove(leasesA[i]);   // remove from this map
 		if (badTime == null)		      // better be in there
 		    throw new ConcurrentModificationException();
-		bad.put(leases[i], results.denied[d++]);// add to "bad" map
+		bad.put(leasesA[i], results.denied[d++]);// add to "bad" map
 	    }
 	}
 

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLease.java Sat Nov 30 12:23:20 2013
@@ -26,6 +26,8 @@ import java.rmi.RemoteException;
 import net.jini.core.lease.Lease;
 import net.jini.core.lease.LeaseDeniedException;
 import net.jini.core.lease.UnknownLeaseException;
+import net.jini.id.Uuid;
+import org.apache.river.api.util.ID;
 
 /**
  * A base class for implementing lease objects.  This class takes care of
@@ -43,14 +45,18 @@ public abstract class AbstractLease impl
 
     /**
      * The lease expiration, in local absolute time.
+     * 
+     * This field has been made volatile to ensure visibility, since
+     * synchronized access isn't guaranteed to be performed
+     * by overriding classes.
      */
-    protected transient long expiration;
+    protected volatile transient long expiration;
     /**
      * Serialization format for the expiration.
      *
      * @serial
      */
-    protected int serialFormat = Lease.DURATION;
+    protected volatile int serialFormat = Lease.DURATION;
 
     /** Construct a relative-format lease. */
     protected AbstractLease(long expiration) {
@@ -58,12 +64,12 @@ public abstract class AbstractLease impl
     }
 
     /** Return the lease expiration. */
-    public synchronized long getExpiration() {
+    public long getExpiration() {
 	return expiration;
     }
 
     /** Return the serialization format for the expiration. */
-    public synchronized int getSerialFormat() {
+    public int getSerialFormat() {
 	return serialFormat;
     }
 
@@ -71,9 +77,7 @@ public abstract class AbstractLease impl
     public void setSerialFormat(int format) {
 	if (format != Lease.DURATION && format != Lease.ABSOLUTE)
 	    throw new IllegalArgumentException("invalid serial format");
-	synchronized (this) {
-	    serialFormat = format;
-	}
+        serialFormat = format;
     }
 
     /** Renew the lease for a duration relative to now. */
@@ -83,11 +87,8 @@ public abstract class AbstractLease impl
 	long exp = doRenew(duration) + System.currentTimeMillis();
 	// We added two positive numbers, so if the result is negative
 	// we must have overflowed, so use Long.MAX_VALUE
-	if (exp < 0) 
-	    exp = Long.MAX_VALUE;
-	synchronized (this) {
-	    expiration = exp;
-	}
+	if (exp < 0) exp = Long.MAX_VALUE;
+        expiration = exp;
     }
 
     /**
@@ -104,10 +105,8 @@ public abstract class AbstractLease impl
     private void writeObject(ObjectOutputStream stream) throws IOException {
 	int format;
 	long val;
-	synchronized (this) {
 	    format = serialFormat;
 	    val = expiration;
-	}
 	if (format == Lease.DURATION) {
 	    long exp = val;
 	    val -= System.currentTimeMillis();
@@ -126,7 +125,7 @@ public abstract class AbstractLease impl
      *
      * @throws InvalidObjectException unconditionally
      */
-    private void readObjectNoData() throws InvalidObjectException {
+    private synchronized void readObjectNoData() throws InvalidObjectException {
 	throw new InvalidObjectException("no data in stream");
     }
 

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLeaseMap.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLeaseMap.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/lease/AbstractLeaseMap.java Sat Nov 30 12:23:20 2013
@@ -40,7 +40,7 @@ import net.jini.core.lease.LeaseMapExcep
  * @author Sun Microsystems, Inc.
  *
  */
-public abstract class AbstractLeaseMap implements LeaseMap, ConcurrentMap {
+public abstract class AbstractLeaseMap implements LeaseMap {
     /**
      * Map from Lease to Long(duration), where all leases have the same
      * destination.
@@ -183,216 +183,6 @@ public abstract class AbstractLeaseMap i
 	return map.hashCode();
     }
 
-    @Override
-    public Object putIfAbsent(final Object key, final Object value) {
-        checkKey(key);
-        checkValue(value);
-        if (map instanceof ConcurrentMap){
-            ConcurrentMap m = (ConcurrentMap) map;
-            return m.putIfAbsent(key, value);
-        } else {
-            synchronized (mapLock){
-                Set entries;
-                entries = map.entrySet();
-                Map.Entry entry = new Map.Entry(){
-
-                    @Override
-                    public Object getKey() {
-                        return key;
-                    }
-
-                    @Override
-                    public Object getValue() {
-                        return value;
-                    }
-
-                    @Override
-                    public Object setValue(Object value) {
-                        throw new UnsupportedOperationException("Not supported.");
-                    }
-                    
-                    public boolean equals(Object o){
-                        if (!(o instanceof Map.Entry)) return false;
-                        Map.Entry e2 = (Map.Entry) o;
-                        Map.Entry e1 = this;
-                        return (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
-                         (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue()));
-                    }
-                    
-                    public int hashCode(){
-                        Map.Entry e = this;
-                        return (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
-                        (e.getValue()==null ? 0 : e.getValue().hashCode());
-                    }
-                    
-                };
-                if (entries.contains(entry)){
-                    // Not absent return long.
-                    return value;
-                } else if ( map.containsKey(key)) {
-                    // Might contain null value;
-                    Object result = map.get(key);
-                    if (result == null) map.put(key, value);
-                    // If result is not null it is returned and no put was made
-                    // or if it is null, the key value pair was added and null value 
-                    // is retruned.
-                    return result;
-                } else {
-                    map.put(key, value);
-                    return null;
-                }
-                
-            }
-        }
-    }
-
-    @Override
-    public boolean remove(final Object key, final Object value) {
-        if (map instanceof ConcurrentMap){
-            return ((ConcurrentMap) map).remove(key, value);
-        } else {
-            Set entries;
-                entries = map.entrySet();
-                Map.Entry entry = new Map.Entry(){
-
-                    @Override
-                    public Object getKey() {
-                        return key;
-                    }
-
-                    @Override
-                    public Object getValue() {
-                        return value;
-                    }
-
-                    @Override
-                    public Object setValue(Object value) {
-                        throw new UnsupportedOperationException("Not supported.");
-                    }
-                    
-                    public boolean equals(Object o){
-                        if (!(o instanceof Map.Entry)) return false;
-                        Map.Entry e2 = (Map.Entry) o;
-                        Map.Entry e1 = this;
-                        return (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
-                         (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue()));
-                    }
-                    
-                    public int hashCode(){
-                        Map.Entry e = this;
-                        return (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
-                        (e.getValue()==null ? 0 : e.getValue().hashCode());
-                    }
-                };
-                return entries.remove(entry);
-        }
-    }
-
-    @Override
-    public boolean replace(final Object key, final Object oldValue, Object newValue) {
-        checkKey(key);
-        checkValue(newValue);
-        if (map instanceof ConcurrentMap){
-            return ((ConcurrentMap)map).replace(key, oldValue, newValue);
-        } else {
-            synchronized (mapLock){
-            Set entries;
-                entries = map.entrySet();
-                Map.Entry entry = new Map.Entry(){
-
-                    @Override
-                    public Object getKey() {
-                        return key;
-                    }
-
-                    @Override
-                    public Object getValue() {
-                        return oldValue;
-                    }
-
-                    @Override
-                    public Object setValue(Object value) {
-                        throw new UnsupportedOperationException("Not supported.");
-                    }
-                    
-                    public boolean equals(Object o){
-                        if (!(o instanceof Map.Entry)) return false;
-                        Map.Entry e2 = (Map.Entry) o;
-                        Map.Entry e1 = this;
-                        return (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
-                         (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue()));
-                    }
-                    
-                    public int hashCode(){
-                        Map.Entry e = this;
-                        return (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
-                        (e.getValue()==null ? 0 : e.getValue().hashCode());
-                    }
-                    
-                };
-                if (entries.contains(entry)){
-                    Object result = map.put(key, newValue);
-                    assert result.equals(oldValue);
-                    return true;
-                } else  {
-                    return false;
-                }
-            }
-        }
-    }
-
-    @Override
-    public Object replace(final Object key, final Object value) {
-        checkKey(key);
-        checkValue(value);
-        if (map instanceof ConcurrentMap){
-            return ((ConcurrentMap)map).replace(key, value);
-        } else {
-            synchronized (mapLock){
-                Set entries;
-                entries = map.entrySet();
-                Map.Entry entry = new Map.Entry(){
-
-                    @Override
-                    public Object getKey() {
-                        return key;
-                    }
-
-                    @Override
-                    public Object getValue() {
-                        return value;
-                    }
-
-                    @Override
-                    public Object setValue(Object value) {
-                        throw new UnsupportedOperationException("Not supported.");
-                    }
-                    
-                    public boolean equals(Object o){
-                        if (!(o instanceof Map.Entry)) return false;
-                        Map.Entry e2 = (Map.Entry) o;
-                        Map.Entry e1 = this;
-                        return (e1.getKey()==null ? e2.getKey()==null : e1.getKey().equals(e2.getKey()))  &&
-                         (e1.getValue()==null ? e2.getValue()==null : e1.getValue().equals(e2.getValue()));
-                    }
-                    
-                    public int hashCode(){
-                        Map.Entry e = this;
-                        return (e.getKey()==null ? 0 : e.getKey().hashCode()) ^
-                        (e.getValue()==null ? 0 : e.getValue().hashCode());
-                    }
-                    
-                };
-                if (entries.contains(entry)){
-                    Object result = map.put(key, value);
-                    return result;
-                } else  {
-                    return null;
-                }
-            }
-        }
-    }
-
     /**
      * We use an AbstractSet to minimize the number of places where
      * we have to wrap objects inside new classes.  This could be

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ClientLeaseWrapper.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ClientLeaseWrapper.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ClientLeaseWrapper.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/norm/ClientLeaseWrapper.java Sat Nov 30 12:23:20 2013
@@ -524,7 +524,7 @@ class ClientLeaseWrapper implements Leas
     }
 
     // Inherit java doc from super type
-    public LeaseMap createLeaseMap(long duration) {
+    public LeaseMap<Lease, Long> createLeaseMap(long duration) {
 	if (isDeformed()) {
 	    return new DeformedClientLeaseMapWrapper(this, duration);
 	} else {

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableEventLease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableEventLease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableEventLease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableEventLease.java Sat Nov 30 12:23:20 2013
@@ -79,7 +79,7 @@ final class ConstrainableEventLease
     /**
      * Creates a constraint-aware lease map.
      */
-    public LeaseMap createLeaseMap(long duration) {
+    public LeaseMap<? extends Lease,Long> createLeaseMap(long duration) {
 	return new ConstrainableRegistrarLeaseMap(this, duration);
     }
 

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableServiceLease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableServiceLease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableServiceLease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/ConstrainableServiceLease.java Sat Nov 30 12:23:20 2013
@@ -79,7 +79,7 @@ final class ConstrainableServiceLease
     /**
      * Creates a constraint-aware lease map.
      */
-    public LeaseMap createLeaseMap(long duration) {
+    public LeaseMap<? extends Lease,Long> createLeaseMap(long duration) {
 	return new ConstrainableRegistrarLeaseMap(this, duration);
     }
 

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLease.java Sat Nov 30 12:23:20 2013
@@ -29,6 +29,7 @@ import net.jini.core.lookup.ServiceID;
 import net.jini.id.ReferentUuid;
 import net.jini.id.ReferentUuids;
 import net.jini.id.Uuid;
+import org.apache.river.api.util.ID;
 
 /**
  * The base class for lease proxies.
@@ -36,7 +37,7 @@ import net.jini.id.Uuid;
  * @author Sun Microsystems, Inc.
  *
  */
-abstract class RegistrarLease extends AbstractLease implements ReferentUuid {
+abstract class RegistrarLease extends AbstractLease implements ReferentUuid, ID<Uuid> {
 
     private static final long serialVersionUID = 2L;
 
@@ -70,7 +71,7 @@ abstract class RegistrarLease extends Ab
     }
 
     /** Creates a lease map. */
-    public LeaseMap createLeaseMap(long duration) {
+    public LeaseMap<? extends Lease,Long> createLeaseMap(long duration) {
 	return new RegistrarLeaseMap(this, duration);
     }
 
@@ -122,6 +123,10 @@ abstract class RegistrarLease extends Ab
     ServiceID getRegistrarID() {
 	return registrarID;
     }
+    
+    public Uuid identity(){
+        return leaseID;
+    }
 
     /** Returns the service ID, or the event ID as a Long. */
     abstract Object getRegID();
@@ -129,11 +134,6 @@ abstract class RegistrarLease extends Ab
     /** Returns the type of the lease. */
     abstract String getLeaseType();
 
-    /** Sets the expiration. */
-    void setExpiration(long expiration) {
-	this.expiration = expiration;
-    }
-
     /**
      * Writes the default serializable field values for this instance, followed
      * by the registrar's service ID encoded as specified by the
@@ -168,4 +168,8 @@ abstract class RegistrarLease extends Ab
     private void readObjectNoData() throws ObjectStreamException {
 	throw new InvalidObjectException("no data");
     }
+
+    void setExpiration(long expiration) {
+        this.expiration = expiration;
+    }
 }

Modified: river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLeaseMap.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLeaseMap.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/com/sun/jini/reggie/RegistrarLeaseMap.java Sat Nov 30 12:23:20 2013
@@ -17,15 +17,17 @@
  */
 package com.sun.jini.reggie;
 
-import com.sun.jini.lease.AbstractLeaseMap;
 import java.rmi.RemoteException;
 import java.util.HashMap;
 import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
 import java.util.Map;
 import net.jini.core.lease.Lease;
 import net.jini.core.lease.LeaseMapException;
 import net.jini.core.lookup.ServiceID;
 import net.jini.id.Uuid;
+import org.apache.river.impl.lease.AbstractLeaseMap;
 
 /**
  * The LeaseMap implementation class for registrar leases.  Clients only see
@@ -34,7 +36,7 @@ import net.jini.id.Uuid;
  * @author Sun Microsystems, Inc.
  *
  */
-class RegistrarLeaseMap extends AbstractLeaseMap {
+class RegistrarLeaseMap extends AbstractLeaseMap<RegistrarLease> {
 
     private static final long serialVersionUID = 2L;
 
@@ -58,9 +60,10 @@ class RegistrarLeaseMap extends Abstract
 
     /** Constructor used by ConstrainableRegistrarLeaseMap */
     RegistrarLeaseMap(Registrar server, RegistrarLease lease, long duration) {
-	super(new HashMap(), lease, duration);
+	super();
 	this.server = server;
 	registrarID = lease.getRegistrarID();
+        put(lease, Long.valueOf(duration));
     }
 
     /** Any RegistrarLease from the same server can be in the map */
@@ -71,69 +74,82 @@ class RegistrarLeaseMap extends Abstract
 
     // This method's javadoc is inherited from an interface of this class
     public void renewAll() throws LeaseMapException, RemoteException {
-        synchronized (mapLock){
-            int size = map.size();
-            if (size == 0) return;
-            Object[] regIDs = new Object[size];
-            Uuid[] leaseIDs = new Uuid[size];
-            long[] durations = new long[size];
-            int i = 0;
-            for (Iterator<Map.Entry<RegistrarLease,Long>> iter = map.entrySet().iterator(); iter.hasNext(); i++) {
-                Map.Entry<RegistrarLease,Long> e = iter.next();
-                RegistrarLease ls = e.getKey();
-                regIDs[i] = ls.getRegID();
-                leaseIDs[i] = ls.getReferentUuid();
-                durations[i] = (e.getValue()).longValue();
-            }
-            RenewResults results = server.renewLeases(regIDs, leaseIDs, durations);
-            long now = System.currentTimeMillis();
-            HashMap<Lease,Exception> emap = (results.exceptions != null) ?
-                           new HashMap<Lease,Exception>(2 * results.exceptions.length + 1) : null;
-            i = 0;
-            int j = 0;
-            for (Iterator<Map.Entry<RegistrarLease,Long>> iter = map.entrySet().iterator(); iter.hasNext(); i++) {
-                Map.Entry<RegistrarLease,Long> e = iter.next();
-                long duration = results.durations[i];
-                if (duration >= 0) {
-                    e.getKey().setExpiration(duration + now);
-                } else {
-                    emap.put(e.getKey(), results.exceptions[j++]);
-                    iter.remove();
-                }
+        if (isEmpty()) return;
+        List<RegistrarLease> leases = new LinkedList<RegistrarLease>();
+        List<Object> regIDS = new LinkedList<Object>();
+        List<Uuid> leaseIDS = new LinkedList<Uuid>();
+        List<Long> dur = new LinkedList<Long>();
+        
+        Iterator<Map.Entry<RegistrarLease,Long>> itera = entrySet().iterator();
+        while ( itera.hasNext()) {
+            Map.Entry<RegistrarLease,Long> e = itera.next();
+            RegistrarLease lease = e.getKey();
+            leases.add(lease);
+            regIDS.add(lease.getRegID());
+            leaseIDS.add(lease.getReferentUuid());
+            dur.add(e.getValue());
+        }
+        Object[] regIDs = regIDS.toArray(new Object[regIDS.size()]);
+        Uuid[] leaseIDs = leaseIDS.toArray(new Uuid [leaseIDS.size()]);
+        long[] durations = new long[dur.size()];
+        Iterator<Long> it = dur.iterator();
+        int i = 0;
+        while (it.hasNext()){
+            durations [i] = it.next();
+            i++;
+        }
+        
+        //TODO finish below, watch out for results.
+        RenewResults results = server.renewLeases(regIDs, leaseIDs, durations);
+        long now = System.currentTimeMillis();
+        Map<Lease,Exception> emap = (results.exceptions != null) ?
+                       new HashMap<Lease,Exception>(2 * results.exceptions.length + 1) : null;
+        i = 0;
+        int j = 0;
+        for (Iterator<RegistrarLease> iter = leases.iterator(); iter.hasNext(); i++) {
+            RegistrarLease e = iter.next();
+            long duration = results.durations[i];
+            if (duration >= 0) {
+                e.setExpiration(duration + now);
+            } else {
+                emap.put(e, results.exceptions[j++]);
+                remove(e);
             }
-            if (emap != null)
-                throw new LeaseMapException("lease renewal failures", emap);
         }
+        if (emap != null)
+            throw new LeaseMapException("lease renewal failures", emap);
     }
 
     // This method's javadoc is inherited from an interface of this class
+    @SuppressWarnings("unchecked")
     public void cancelAll() throws LeaseMapException, RemoteException {
-        synchronized (mapLock){
-            int size = map.size();
-            if (size == 0)
-                return;
-            Object[] regIDs = new Object[size];
-            Uuid[] leaseIDs = new Uuid[size];
-            int i = 0;
-            for (Iterator iter = map.keySet().iterator(); iter.hasNext(); i++) {
-                RegistrarLease ls = (RegistrarLease)iter.next();
-                regIDs[i] = ls.getRegID();
-                leaseIDs[i] = ls.getReferentUuid();
-            }
-            Exception[] exceptions = server.cancelLeases(regIDs, leaseIDs);
-            if (exceptions == null)
-                return;
-            i = 0;
-            HashMap emap = new HashMap(13);
-            for (Iterator iter = map.keySet().iterator(); iter.hasNext(); i++) {
-                RegistrarLease ls = (RegistrarLease)iter.next();
-                Exception ex = exceptions[i];
-                if (ex != null) {
-                    emap.put(ls, ex);
-                    iter.remove();
-                }
+        // finish by copying above.
+        if (isEmpty()) return;
+        List<RegistrarLease> leases = new LinkedList<RegistrarLease>();
+        List regIDs = new LinkedList();
+        List<Uuid> leaseIDs = new LinkedList<Uuid>();
+        int i = 0;
+        for (Iterator<RegistrarLease> iter = keySet().iterator(); iter.hasNext(); i++) {
+            RegistrarLease ls = iter.next();
+            leases.add(ls);
+            regIDs.add(ls.getRegID());
+            leaseIDs.add(ls.getReferentUuid());
+        }
+        Exception[] exceptions = server.cancelLeases(
+                regIDs.toArray(), 
+                leaseIDs.toArray(new Uuid[leaseIDs.size()])
+                );
+        if (exceptions == null) return;
+        i = 0;
+        Map<Lease,Exception> emap = new HashMap<Lease,Exception>(exceptions.length);
+        for (Iterator<RegistrarLease> iter = leases.iterator(); iter.hasNext(); i++) {
+            Lease ls = (Lease)iter.next();
+            Exception ex = exceptions[i];
+            if (ex != null) {
+                emap.put(ls, ex);
+                remove(ls);
             }
-            throw new LeaseMapException("lease cancellation failures", emap);
         }
+        throw new LeaseMapException("lease cancellation failures", emap);
     }
 }

Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/Lease.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/Lease.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/Lease.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/Lease.java Sat Nov 30 12:23:20 2013
@@ -56,14 +56,14 @@ public interface Lease {
      * object from one address space to another (via an RMI call) where
      * it cannot be assumed that the address spaces have synchronized clocks.
      */
-    int DURATION = 1;
+    final int DURATION = 1;
 
     /**
      * The serialized form of the lease will contain the time of expiration
      * stored as an absolute time, represented in terms of milliseconds since
      * the beginning of the epoch.
      */
-    int ABSOLUTE = 2;
+    final int ABSOLUTE = 2;
 
     /**
      * Returns a <code>long</code> that indicates the time that the
@@ -138,7 +138,7 @@ public interface Lease {
      *
      * @return the created <tt>LeaseMap</tt> object
      */
-    LeaseMap createLeaseMap(long duration);
+    LeaseMap<? extends Lease, Long> createLeaseMap(long duration);
 
     /**
      * Returns a boolean indicating whether or not the lease given as a

Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMap.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMap.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMap.java Sat Nov 30 12:23:20 2013
@@ -26,11 +26,13 @@ import java.rmi.RemoteException;
  * an IllegalArgumentException is thrown if a key is not a Lease or a value
  * is not a Long.  Null keys and values are not supported.
  *
+ * @param <K> 
+ * @param <V> 
  * @author Sun Microsystems, Inc.
  *
  * @since 1.0
  */
-public interface LeaseMap extends java.util.Map {
+public interface LeaseMap<K,V> extends java.util.Map<K,V> {
     /**
      * Returns true if the given object is a Lease which can be renewed
      * and cancelled in a batch with other leases in the map.  Whether

Modified: river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMapException.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMapException.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMapException.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/net/jini/core/lease/LeaseMapException.java Sat Nov 30 12:23:20 2013
@@ -141,9 +141,9 @@ public class LeaseMapException extends L
         StringBuilder sb = new StringBuilder(1024);
         sb.append(super.getMessage());
         sb.append(ret);
-        Iterator<Map.Entry<Lease,Exception>> it = exceptionMap.entrySet().iterator();
+        Iterator<Entry<Lease,Exception>> it = exceptionMap.entrySet().iterator();
         while (it.hasNext()){
-            Entry<Lease,Exception> entry = it.next();
+            Entry<? extends Lease,Exception> entry = it.next();
             sb.append(lease);
             sb.append(entry.getKey());
             sb.append(exception);

Modified: river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java?rev=1546722&r1=1546721&r2=1546722&view=diff
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java (original)
+++ river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/net/RFC3986URLClassLoader.java Sat Nov 30 12:23:20 2013
@@ -814,6 +814,7 @@ public class RFC3986URLClassLoader exten
      * @param url
      *            the URL which is to add.
      */
+    @Override
     protected void addURL(URL url) {
         try {
             originalUrls.add(url);
@@ -904,43 +905,43 @@ public class RFC3986URLClassLoader exten
      *            the code source object whose permissions have to be known.
      * @return the list of permissions according to the code source object.
      */
-    @Override
-    protected PermissionCollection getPermissions(final CodeSource codesource) {
-        PermissionCollection pc = super.getPermissions(codesource);
-        URL u = codesource.getLocation();
-        if (u.getProtocol().equals("jar")) { //$NON-NLS-1$
-            try {
-                // Create a URL for the resource the jar refers to
-                u = ((JarURLConnection) u.openConnection()).getJarFileURL();
-            } catch (IOException e) {
-                // This should never occur. If it does continue using the jar
-                // URL
-            }
-        }
-        if (u.getProtocol().equals("file")) { //$NON-NLS-1$
-            String path = u.getFile();
-            String host = u.getHost();
-            if (host != null && host.length() > 0) {
-                path = "//" + host + path; //$NON-NLS-1$
-            }
-
-            if (File.separatorChar != '/') {
-                path = path.replace('/', File.separatorChar);
-            }
-            if (isDirectory(u)) {
-                pc.add(new FilePermission(path + "-", "read")); //$NON-NLS-1$ //$NON-NLS-2$
-            } else {
-                pc.add(new FilePermission(path, "read")); //$NON-NLS-1$
-            }
-        } else {
-            String host = u.getHost();
-            if (host.length() == 0) {
-                host = "localhost"; //$NON-NLS-1$
-            }
-            pc.add(new SocketPermission(host, "connect, accept")); //$NON-NLS-1$
-        }
-        return pc;
-    }
+//    @Override
+//    protected PermissionCollection getPermissions(final CodeSource codesource) {
+//        PermissionCollection pc = super.getPermissions(codesource);
+//        URL u = codesource.getLocation();
+//        if (u.getProtocol().equals("jar")) { //$NON-NLS-1$
+//            try {
+//                // Create a URL for the resource the jar refers to
+//                u = ((JarURLConnection) u.openConnection()).getJarFileURL();
+//            } catch (IOException e) {
+//                // This should never occur. If it does continue using the jar
+//                // URL
+//            }
+//        }
+//        if (u.getProtocol().equals("file")) { //$NON-NLS-1$
+//            String path = u.getFile();
+//            String host = u.getHost();
+//            if (host != null && host.length() > 0) {
+//                path = "//" + host + path; //$NON-NLS-1$
+//            }
+//
+//            if (File.separatorChar != '/') {
+//                path = path.replace('/', File.separatorChar);
+//            }
+//            if (isDirectory(u)) {
+//                pc.add(new FilePermission(path + "-", "read")); //$NON-NLS-1$ //$NON-NLS-2$
+//            } else {
+//                pc.add(new FilePermission(path, "read")); //$NON-NLS-1$
+//            }
+//        } else {
+//            String host = u.getHost();
+//            if (host.length() == 0) {
+//                host = "localhost"; //$NON-NLS-1$
+//            }
+//            pc.add(new SocketPermission(host, "connect, accept")); //$NON-NLS-1$
+//        }
+//        return pc;
+//    }
 
     /**
      * Returns the search list of this {@code URLClassLoader}.

Added: river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/util/ID.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/util/ID.java?rev=1546722&view=auto
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/util/ID.java (added)
+++ river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/api/util/ID.java Sat Nov 30 12:23:20 2013
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.river.api.util;
+
+/**
+ * A mix in interface that provides an identity to be used as a key in Collections.
+ * 
+ * @param <T> Object identity.
+ * @author peter
+ */
+public interface ID<T> {
+    
+    /**
+     * @return object representing identity, usually a Uuid.
+     */
+    public T identity();
+}

Added: river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/impl/lease/AbstractLeaseMap.java
URL: http://svn.apache.org/viewvc/river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/impl/lease/AbstractLeaseMap.java?rev=1546722&view=auto
==============================================================================
--- river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/impl/lease/AbstractLeaseMap.java (added)
+++ river/jtsk/skunk/qa_refactor/trunk/src/org/apache/river/impl/lease/AbstractLeaseMap.java Sat Nov 30 12:23:20 2013
@@ -0,0 +1,264 @@
+/*
+ * 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.lease;
+
+import au.net.zeus.collection.RC;
+import au.net.zeus.collection.Ref;
+import au.net.zeus.collection.Referrer;
+import java.util.AbstractMap;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.concurrent.ConcurrentSkipListSet;
+import net.jini.core.lease.Lease;
+import net.jini.core.lease.LeaseMap;
+import net.jini.id.Uuid;
+import org.apache.river.api.util.ID;
+
+/**
+ * AbstractLeaseMap is intended to work around some minor design warts in the 
+ * {@link Lease} interface:
+ * 
+ * In the real world, when a Lease is renewed, a new Lease contract document
+ * is issued, however when an electronic Lease is renewed the Lease expiry
+ * date is changed and the record of the previous Lease is lost.  Ideally the
+ * renew method would return a new Lease.
+ * 
+ * Current Lease implementations rely on a {@link Uuid} to represents the lease,
+ * the expiry date is not included the equals or hashCode calculations.  For this
+ * reason, two Lease objects, one expired and one valid, may be equal, this
+ * is undesirable.
+ * 
+ * The Lease interface doesn't specify a contract for equals or hashCode,
+ * all Lease implementations are also mutable, previous implementations
+ * of {@link LeaseMap} used Leases as keys.
+ * 
+ * AbstractLeaseMap uses only the {@link ID}, usually a {@link Uuid}
+ * provided by a Lease for internal map keys, if {@link ID} is not implemented
+ * then the Lease itself is used as the key.
+ * 
+ * Both Lease keys and Long values are actually stored internally as values
+ * referred to by ID keys, allowing Lease implementations to either not override
+ * hashCode and equals object methods or allow implementations that more
+ * accurately model reality.
+ * 
+ * This implementation is thread safe, concurrent and doesn't require external 
+ * synchronization.
+ * 
+ * @param <K> 
+ * @author peter
+ */
+public abstract class AbstractLeaseMap<K extends Lease> extends AbstractMap<K,Long> 
+                              implements LeaseMap<K,Long> {
+    
+    private final ConcurrentMap<Object,K> leaseMap;
+    private final ConcurrentMap<Object,Long> durationMap;
+    private final Set<Entry<K,Long>> set;
+    
+    /**
+     * Constructor for subclasses.
+     */
+    protected AbstractLeaseMap(){
+        leaseMap = RC.concurrentMap(
+                new ConcurrentHashMap<Referrer<Object>,Referrer<K>>(),
+                Ref.WEAK, Ref.STRONG, 10000, 10000);
+        durationMap = RC.concurrentMap(
+                new ConcurrentHashMap<Referrer<Object>,Referrer<Long>>(),
+                Ref.WEAK, Ref.STRONG, 10000, 10000);
+        set = new ConcurrentSkipListSet<Entry<K,Long>>();
+    }
+
+    @Override
+    public Set<Entry<K,Long>> entrySet() {
+        return set;
+    }
+    
+    void checkKey(Object key) throws IllegalArgumentException {
+        if (!canContainKey(key)) throw new IllegalArgumentException("Key not valid for this LeaseMap");
+    }
+    
+    void checkValue(Object value) throws IllegalArgumentException {
+        if (!(value instanceof Long)) throw new IllegalArgumentException("Value not valid for this LeaseMap, must be Long");
+    }
+    
+    public boolean containsValue(Object value){
+        checkValue(value);
+        return durationMap.containsValue(value);
+    }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * Determines whether the ID of the key matches the ID of another key
+     * in the map.
+     * 
+     * @param key
+     * @return 
+     */
+    public boolean containsKey(Object key){
+        checkKey(key);
+        return set.contains(new LeaseEntry<K>(getIdentity(key), null, null, null));
+    }
+    
+    public Long get(Object key){
+        checkKey(key);
+        return durationMap.get(getIdentity(key));
+    }
+    
+    /**
+     * {@inheritDoc}
+     * 
+     * This implementation will place a new key value pair association in the map,
+     * or it will replace both the key and the value if an equivalent association
+     * currently exists in the map.
+     * 
+     * @param key
+     * @param value
+     * @return 
+     */
+    public Long put(K key, Long value) {
+        checkKey(key);
+        Object identity = getIdentity(key);
+        LeaseEntry<K> entry = new LeaseEntry<K>(identity, leaseMap, durationMap, set);
+        if (entry.isNew(key, value)){
+            return null;
+        } else { // existing identity, replace Lease and duration.
+            leaseMap.replace(identity, key);
+            return durationMap.replace(identity, value);
+        }
+    }
+    
+    public Long remove(Object key){
+        checkKey(key);
+        LeaseEntry<K> entry = new LeaseEntry<K>(getIdentity(key), null, durationMap, null);
+        if (set.remove(entry)) return entry.getValue();
+        return null;
+    }
+    
+    private Object getIdentity(Object key){
+        if (key instanceof ID) {
+                return((ID) key).identity();
+            } else {
+                return key;
+            } // Allows for support of legacy lease implementations where equals is based on Uuid.
+    }
+
+    /**
+     * The logic behind this Entry is that the identity which maintains strong
+     * references to the key and value will not be added to the set or leaseMap
+     * if it's already present.
+     */
+    private static class LeaseEntry<K extends Lease> implements Entry<K,Long>, Comparable<LeaseEntry<K>> {
+        
+        private final ConcurrentMap<Object,K> leaseMap;
+        private final ConcurrentMap<Object,Long> durationMap;
+        private final Set<Entry<K,Long>> set;
+        private final Object identity;
+        private volatile K key;
+        private volatile Long value;
+        
+                
+        
+        LeaseEntry(Object identity, ConcurrentMap<Object,K> leaseMap, ConcurrentMap<Object,Long> durationMap, Set<Entry<K,Long>> set){
+            if (identity == null) throw new NullPointerException("Identity cannot be null");
+            this.set = set;
+            this.leaseMap = leaseMap;
+            this.durationMap = durationMap;
+            this.identity = identity;
+        }
+        
+        boolean isNew(K key, Long value){
+            if (set.add(this)){
+                Object exists = leaseMap.putIfAbsent(identity, key);
+                Object valExists = durationMap.putIfAbsent(identity, value);
+                // If exists, there's a problem if identity is not the same object
+                // we are forced to remove it, because key and value may not be 
+                // strongly referenced by our identity and risk being garbage collected.
+                if (exists != null || valExists != null){
+                    this.key = key;
+                    this.value = value;
+                    try {
+                        leaseMap.remove(identity);
+                        durationMap.remove(identity);
+                        leaseMap.put(identity, key);
+                        durationMap.put(identity, value);
+                    } finally {
+                        this.key = null;
+                        this.value = null;
+                    }
+                }
+                return true;
+            }
+            return false;
+        }
+
+        @Override
+        public K getKey() {
+            K key = this.key;
+            if (key != null) return key;
+            return leaseMap.get(identity);
+        }
+
+        @Override
+        public Long getValue() {
+            Long value = this.value;
+            if (value != null) return value;
+            return durationMap.get(identity);
+        }
+
+        @Override
+        public Long setValue(Long value) {
+            return durationMap.replace(identity, value);
+        }
+
+        @Override
+        public int hashCode() {
+            return identity.hashCode();
+        }
+        
+        public boolean equals(Object o){
+            if (!(o instanceof LeaseEntry)) return false;
+            LeaseEntry that = (LeaseEntry) o;
+            return this.identity.equals(that.identity);
+        }
+
+        public int compareTo(LeaseEntry<K> o) {
+            if (identity instanceof Uuid && o.identity instanceof Uuid){
+                long mine = ((Uuid) identity).getLeastSignificantBits();
+                long his = ((Uuid) o.identity).getLeastSignificantBits();
+                if ( mine < his) return -1;
+                if ( mine > his) return 1;
+                if ( mine == his){
+                    mine = ((Uuid) identity).getMostSignificantBits();
+                    his = ((Uuid) o.identity).getMostSignificantBits();
+                    if ( mine < his) return -1;
+                    if ( mine > his) return 1;
+                    return 0;
+                }
+            }
+            int myHash = hashCode();
+            int hisHash = o.hashCode();
+            if (myHash < hisHash) return -1;
+            if (myHash > hisHash) return 1;
+            return 0;
+        }
+    
+    }
+ 
+}