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;
+ }
+
+ }
+
+}