summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2007-11-15 06:55:46 (EST)
committerEike Stepper2007-11-15 06:55:46 (EST)
commit857e69c545d283e0b6044d8a8f2afcbe12bc410b (patch)
tree507f34b5b622fcbad1034c17c64a8737a69c6510
parent3f34d804d76ac5f648400c38452d4c04681e5a19 (diff)
downloadcdo-857e69c545d283e0b6044d8a8f2afcbe12bc410b.zip
cdo-857e69c545d283e0b6044d8a8f2afcbe12bc410b.tar.gz
cdo-857e69c545d283e0b6044d8a8f2afcbe12bc410b.tar.bz2
[209490] Put purging mechanism in CDOViewIMpl::objects to avoid OutOfMemory
https://bugs.eclipse.org/bugs/show_bug.cgi?id=209490
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/PackageManagerDialog.java7
-rw-r--r--plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/views/CDOViewHistory.java9
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOClusterOfFetchRule.java11
-rw-r--r--plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOFetchFeatureInfo.java11
-rw-r--r--plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF1
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/collection/HistoryElement.java12
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/ManagedContainer.java5
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/delegate/ContainerMap.java33
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/factory/FactoryKey.java5
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/MapEntry.java74
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedPhantomReference.java38
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedReference.java44
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedSoftReference.java44
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedStrongReference.java57
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedWeakReference.java44
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceType.java19
-rw-r--r--plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java430
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/Channel.java5
18 files changed, 814 insertions, 35 deletions
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/PackageManagerDialog.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/PackageManagerDialog.java
index 71ff5a9..3e5fa8e 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/PackageManagerDialog.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/dialogs/PackageManagerDialog.java
@@ -383,10 +383,15 @@ public class PackageManagerDialog extends TitleAreaDialog
@Override
public boolean equals(Object obj)
{
+ if (obj == this)
+ {
+ return true;
+ }
+
if (obj instanceof Content)
{
Content that = (Content)obj;
- return ObjectUtil.equals(this.packageURI, that.packageURI);
+ return ObjectUtil.equals(packageURI, that.packageURI);
}
return false;
diff --git a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/views/CDOViewHistory.java b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/views/CDOViewHistory.java
index e804d40..5f8061a 100644
--- a/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/views/CDOViewHistory.java
+++ b/plugins/org.eclipse.emf.cdo.ui/src/org/eclipse/emf/cdo/internal/ui/views/CDOViewHistory.java
@@ -15,13 +15,13 @@ import org.eclipse.emf.cdo.CDOViewResourcesEvent;
import org.eclipse.emf.cdo.eresource.CDOResource;
import org.eclipse.emf.cdo.ui.CDOViewHistoryEvent;
+import org.eclipse.emf.ecore.resource.Resource;
+
import org.eclipse.net4j.internal.util.event.Event;
import org.eclipse.net4j.internal.util.event.Notifier;
import org.eclipse.net4j.util.event.IEvent;
import org.eclipse.net4j.util.event.IListener;
-import org.eclipse.emf.ecore.resource.Resource;
-
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Set;
@@ -189,6 +189,11 @@ public final class CDOViewHistory extends Notifier
@Override
public boolean equals(Object obj)
{
+ if (obj == this)
+ {
+ return true;
+ }
+
if (obj instanceof Entry)
{
Entry that = (Entry)obj;
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOClusterOfFetchRule.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOClusterOfFetchRule.java
index 30d2774..803d30c 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOClusterOfFetchRule.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOClusterOfFetchRule.java
@@ -57,11 +57,16 @@ public class CDOClusterOfFetchRule
}
@Override
- public boolean equals(Object object)
+ public boolean equals(Object obj)
{
- if (object instanceof CDOClusterOfFetchRule)
+ if (obj == this)
{
- CDOClusterOfFetchRule featureInfo = (CDOClusterOfFetchRule)object;
+ return true;
+ }
+
+ if (obj instanceof CDOClusterOfFetchRule)
+ {
+ CDOClusterOfFetchRule featureInfo = (CDOClusterOfFetchRule)obj;
return featureInfo.rootClass == rootClass && featureInfo.rootFeature == rootFeature;
}
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOFetchFeatureInfo.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOFetchFeatureInfo.java
index bb37200..7d71f4f 100644
--- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOFetchFeatureInfo.java
+++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/analyzer/CDOFetchFeatureInfo.java
@@ -109,11 +109,16 @@ public class CDOFetchFeatureInfo
}
@Override
- public boolean equals(Object object)
+ public boolean equals(Object obj)
{
- if (object instanceof CDOFetchFeatureInfo)
+ if (obj == this)
{
- CDOFetchFeatureInfo featureInfo = (CDOFetchFeatureInfo)object;
+ return true;
+ }
+
+ if (obj instanceof CDOFetchFeatureInfo)
+ {
+ CDOFetchFeatureInfo featureInfo = (CDOFetchFeatureInfo)obj;
return featureInfo.cdoClass == cdoClass && featureInfo.cdoFeature == cdoFeature;
}
diff --git a/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF b/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
index 020cc78..01f9780 100644
--- a/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
+++ b/plugins/org.eclipse.net4j.util/META-INF/MANIFEST.MF
@@ -45,6 +45,7 @@ Export-Package: org.eclipse.net4j.internal.util.cache;version="0.8.0",
org.eclipse.net4j.util.om.monitor;version="0.8.0",
org.eclipse.net4j.util.om.pref;version="0.8.0",
org.eclipse.net4j.util.om.trace;version="0.8.0",
+ org.eclipse.net4j.util.ref;version="0.8.0",
org.eclipse.net4j.util.registry;version="0.8.0",
org.eclipse.net4j.util.security;version="0.8.0",
org.eclipse.net4j.util.transaction;version="0.8.0"
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/collection/HistoryElement.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/collection/HistoryElement.java
index cafccb5..8e1d18b 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/collection/HistoryElement.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/collection/HistoryElement.java
@@ -10,6 +10,7 @@
**************************************************************************/
package org.eclipse.net4j.internal.util.collection;
+import org.eclipse.net4j.util.ObjectUtil;
import org.eclipse.net4j.util.collection.IHistory;
import org.eclipse.net4j.util.collection.IHistoryElement;
@@ -46,10 +47,15 @@ public class HistoryElement<T> implements IHistoryElement<T>
@Override
public boolean equals(Object obj)
{
- if (obj instanceof HistoryElement)
+ if (obj == this)
{
- HistoryElement<T> that = (HistoryElement<T>)obj;
- return this.history.equals(that.history) && this.data.equals(that.data);
+ return true;
+ }
+
+ if (obj instanceof IHistoryElement)
+ {
+ IHistoryElement<T> that = (IHistoryElement<T>)obj;
+ return ObjectUtil.equals(history, that.getHistory()) && ObjectUtil.equals(data, that.getData());
}
return false;
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/ManagedContainer.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/ManagedContainer.java
index 4aa5300..014d306 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/ManagedContainer.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/ManagedContainer.java
@@ -502,6 +502,11 @@ public class ManagedContainer extends Lifecycle implements IManagedContainer
@Override
public boolean equals(Object obj)
{
+ if (obj == this)
+ {
+ return true;
+ }
+
if (obj instanceof ElementKey)
{
ElementKey key = (ElementKey)obj;
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/delegate/ContainerMap.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/delegate/ContainerMap.java
index dffc19f..281fd53 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/delegate/ContainerMap.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/container/delegate/ContainerMap.java
@@ -11,6 +11,7 @@
package org.eclipse.net4j.internal.util.container.delegate;
import org.eclipse.net4j.internal.util.container.ContainerEvent;
+import org.eclipse.net4j.util.collection.MapEntry;
import org.eclipse.net4j.util.container.IContainerDelta;
import org.eclipse.net4j.util.container.delegate.IContainerMap;
@@ -82,10 +83,10 @@ public class ContainerMap<K, V> extends AbstractDelegator<Map.Entry<K, V>> imple
V removed = getDelegate().put(key, value);
if (removed != null)
{
- event.addDelta(new MapEntry<K, V>(key, removed), IContainerDelta.Kind.REMOVED);
+ event.addDelta(new ContainerMapEntry<K, V>(key, removed), IContainerDelta.Kind.REMOVED);
}
- event.addDelta(new MapEntry<K, V>(key, value), IContainerDelta.Kind.ADDED);
+ event.addDelta(new ContainerMapEntry<K, V>(key, value), IContainerDelta.Kind.ADDED);
fireEvent(event);
return removed;
}
@@ -105,10 +106,10 @@ public class ContainerMap<K, V> extends AbstractDelegator<Map.Entry<K, V>> imple
V removed = getDelegate().put(key, value);
if (removed != null)
{
- event.addDelta(new MapEntry<K, V>(key, removed), IContainerDelta.Kind.REMOVED);
+ event.addDelta(new ContainerMapEntry<K, V>(key, removed), IContainerDelta.Kind.REMOVED);
}
- event.addDelta(new MapEntry<K, V>(key, value), IContainerDelta.Kind.ADDED);
+ event.addDelta(new ContainerMapEntry<K, V>(key, value), IContainerDelta.Kind.ADDED);
}
dispatchEvent(event);
@@ -122,7 +123,7 @@ public class ContainerMap<K, V> extends AbstractDelegator<Map.Entry<K, V>> imple
V removed = getDelegate().remove(key);
if (removed != null)
{
- fireRemovedEvent(new MapEntry<Object, V>(key, removed));
+ fireRemovedEvent(new ContainerMapEntry<Object, V>(key, removed));
}
return removed;
@@ -179,28 +180,14 @@ public class ContainerMap<K, V> extends AbstractDelegator<Map.Entry<K, V>> imple
/**
* @author Eike Stepper
*/
- private static final class MapEntry<K, V> implements Map.Entry<K, V>
+ private static final class ContainerMapEntry<K, V> extends MapEntry<K, V>
{
- private K key;
-
- private V value;
-
- private MapEntry(K key, V value)
- {
- this.key = key;
- this.value = value;
- }
-
- public K getKey()
- {
- return key;
- }
-
- public V getValue()
+ public ContainerMapEntry(K key, V value)
{
- return value;
+ super(key, value);
}
+ @Override
public V setValue(V value)
{
throw new UnsupportedOperationException();
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/factory/FactoryKey.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/factory/FactoryKey.java
index c803199..4b26ea9 100644
--- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/factory/FactoryKey.java
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/internal/util/factory/FactoryKey.java
@@ -47,6 +47,11 @@ public final class FactoryKey implements IFactoryKey, Serializable, Comparable<F
@Override
public boolean equals(Object obj)
{
+ if (obj == this)
+ {
+ return true;
+ }
+
if (obj instanceof FactoryKey)
{
FactoryKey key = (FactoryKey)obj;
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/MapEntry.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/MapEntry.java
new file mode 100644
index 0000000..e27a658
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/collection/MapEntry.java
@@ -0,0 +1,74 @@
+package org.eclipse.net4j.util.collection;
+
+import org.eclipse.net4j.util.ObjectUtil;
+
+import java.text.MessageFormat;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class MapEntry<K, V> implements Map.Entry<K, V>
+{
+ private K key;
+
+ private V value;
+
+ public MapEntry(K key, V value)
+ {
+ this.key = key;
+ this.value = value;
+ }
+
+ public MapEntry(Map.Entry<K, V> entry)
+ {
+ key = entry.getKey();
+ value = entry.getValue();
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+
+ public V getValue()
+ {
+ return value;
+ }
+
+ public V setValue(V value)
+ {
+ V oldValue = this.value;
+ this.value = value;
+ return oldValue;
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ if (obj == this)
+ {
+ return true;
+ }
+
+ if (obj instanceof Map.Entry<?, ?>)
+ {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>)obj;
+ return ObjectUtil.equals(key, entry.getKey()) && ObjectUtil.equals(value, entry.getValue());
+ }
+
+ return false;
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return ObjectUtil.hashCode(key) ^ ObjectUtil.hashCode(value);
+ }
+
+ @Override
+ public String toString()
+ {
+ return MessageFormat.format("{0}={1}", key, value);
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedPhantomReference.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedPhantomReference.java
new file mode 100644
index 0000000..d75c8fa
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedPhantomReference.java
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+import java.lang.ref.PhantomReference;
+import java.lang.ref.ReferenceQueue;
+
+/**
+ * @author Eike Stepper
+ */
+public class KeyedPhantomReference<K, T> extends PhantomReference<T> implements KeyedReference<K, T>
+{
+ private K key;
+
+ public KeyedPhantomReference(K key, T ref, ReferenceQueue<T> queue)
+ {
+ super(ref, queue);
+ this.key = key;
+ }
+
+ public ReferenceType getType()
+ {
+ return ReferenceType.PHANTOM;
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedReference.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedReference.java
new file mode 100644
index 0000000..a00723a
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedReference.java
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+import java.lang.ref.Reference;
+
+/**
+ * @see Reference
+ * @author Eike Stepper
+ */
+public interface KeyedReference<K, T>
+{
+ public ReferenceType getType();
+
+ public K getKey();
+
+ /**
+ * @see Reference#get()
+ */
+ public T get();
+
+ /**
+ * @see Reference#clear()
+ */
+ public void clear();
+
+ /**
+ * @see Reference#isEnqueued()
+ */
+ public boolean isEnqueued();
+
+ /**
+ * @see Reference#enqueue()
+ */
+ public boolean enqueue();
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedSoftReference.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedSoftReference.java
new file mode 100644
index 0000000..5552248
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedSoftReference.java
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.SoftReference;
+
+/**
+ * @author Eike Stepper
+ */
+public class KeyedSoftReference<K, T> extends SoftReference<T> implements KeyedReference<K, T>
+{
+ private K key;
+
+ public KeyedSoftReference(K key, T ref)
+ {
+ super(ref);
+ this.key = key;
+ }
+
+ public KeyedSoftReference(K key, T ref, ReferenceQueue<T> queue)
+ {
+ super(ref, queue);
+ this.key = key;
+ }
+
+ public ReferenceType getType()
+ {
+ return ReferenceType.SOFT;
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedStrongReference.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedStrongReference.java
new file mode 100644
index 0000000..33b14d3
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedStrongReference.java
@@ -0,0 +1,57 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+/**
+ * @author Eike Stepper
+ */
+public class KeyedStrongReference<K, T> implements KeyedReference<K, T>
+{
+ private K key;
+
+ private T ref;
+
+ public KeyedStrongReference(K key, T ref)
+ {
+ this.key = key;
+ this.ref = ref;
+ }
+
+ public ReferenceType getType()
+ {
+ return ReferenceType.STRONG;
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+
+ public T get()
+ {
+ return ref;
+ }
+
+ public void clear()
+ {
+ ref = null;
+ }
+
+ public boolean isEnqueued()
+ {
+ return false;
+ }
+
+ public boolean enqueue()
+ {
+ return false;
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedWeakReference.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedWeakReference.java
new file mode 100644
index 0000000..ce15b20
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/KeyedWeakReference.java
@@ -0,0 +1,44 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+
+/**
+ * @author Eike Stepper
+ */
+public class KeyedWeakReference<K, T> extends WeakReference<T> implements KeyedReference<K, T>
+{
+ private K key;
+
+ public KeyedWeakReference(K key, T ref)
+ {
+ super(ref);
+ this.key = key;
+ }
+
+ public KeyedWeakReference(K key, T ref, ReferenceQueue<T> queue)
+ {
+ super(ref, queue);
+ this.key = key;
+ }
+
+ public ReferenceType getType()
+ {
+ return ReferenceType.WEAK;
+ }
+
+ public K getKey()
+ {
+ return key;
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceType.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceType.java
new file mode 100644
index 0000000..6496bf7
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceType.java
@@ -0,0 +1,19 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+/**
+ * @author Eike Stepper
+ */
+public enum ReferenceType
+{
+ STRONG, SOFT, WEAK, PHANTOM;
+}
diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java
new file mode 100644
index 0000000..ff630db
--- /dev/null
+++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java
@@ -0,0 +1,430 @@
+/***************************************************************************
+ * Copyright (c) 2004 - 2007 Eike Stepper, Germany.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ **************************************************************************/
+package org.eclipse.net4j.util.ref;
+
+import org.eclipse.net4j.util.ObjectUtil;
+import org.eclipse.net4j.util.collection.MapEntry;
+
+import java.lang.ref.ReferenceQueue;
+import java.util.AbstractMap;
+import java.util.AbstractSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V>
+{
+ private ConcurrentMap<K, KeyedReference<K, V>> map;
+
+ private ReferenceQueue<V> queue;
+
+ private EntrySet entrySet;
+
+ public ReferenceValueMap()
+ {
+ this(new ConcurrentHashMap<K, KeyedReference<K, V>>());
+ }
+
+ public ReferenceValueMap(ConcurrentMap<K, KeyedReference<K, V>> map)
+ {
+ if (!map.isEmpty())
+ {
+ throw new IllegalArgumentException("!map.isEmpty()");
+ }
+
+ this.map = map;
+ queue = createQueue();
+ }
+
+ @Override
+ public int size()
+ {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean containsKey(Object key)
+ {
+ return map.containsKey(key);
+ }
+
+ @Override
+ public boolean containsValue(Object value)
+ {
+ if (value == null)
+ {
+ throw new IllegalArgumentException("value == null");
+ }
+
+ for (KeyedReference<K, V> ref : map.values())
+ {
+ if (ObjectUtil.equals(value, dereference(ref)))
+ {
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ @Override
+ public V get(Object key)
+ {
+ KeyedReference<K, V> ref = map.get(key);
+ return dereference(ref);
+ }
+
+ @Override
+ public V put(K key, V value)
+ {
+ try
+ {
+ KeyedReference<K, V> ref = createReference(key, value, queue);
+ KeyedReference<K, V> oldRef = map.put(key, ref);
+ return dereference(oldRef);
+ }
+ finally
+ {
+ purgeQueue();
+ }
+ }
+
+ public V putIfAbsent(K key, V value)
+ {
+ try
+ {
+ KeyedReference<K, V> ref = createReference(key, value, queue);
+ KeyedReference<K, V> oldRef = map.putIfAbsent(key, ref);
+ return dereference(oldRef);
+ }
+ finally
+ {
+ purgeQueue();
+ }
+ }
+
+ public V replace(K key, V value)
+ {
+ try
+ {
+ KeyedReference<K, V> ref = createReference(key, value, queue);
+ KeyedReference<K, V> oldRef = map.replace(key, ref);
+ return dereference(oldRef);
+ }
+ finally
+ {
+ purgeQueue();
+ }
+ }
+
+ public boolean replace(K key, V oldValue, V newValue)
+ {
+ try
+ {
+ // TODO Consider a dummy KeyedReference class for oldRef
+ KeyedReference<K, V> oldRef = createReference(key, oldValue, queue);
+ KeyedReference<K, V> newRef = createReference(key, newValue, queue);
+ return map.replace(key, oldRef, newRef);
+ }
+ finally
+ {
+ purgeQueue();
+ }
+ }
+
+ @Override
+ public V remove(Object key)
+ {
+ KeyedReference<K, V> ref = map.remove(key);
+ return dereference(ref);
+ }
+
+ public boolean remove(Object key, Object value)
+ {
+ // TODO Consider a dummy KeyedReference class for value
+ return map.remove(key, value);
+ }
+
+ @Override
+ public void clear()
+ {
+ map.clear();
+ }
+
+ @Override
+ public Set<Map.Entry<K, V>> entrySet()
+ {
+ if (entrySet == null)
+ {
+ entrySet = new EntrySet();
+ }
+
+ return entrySet;
+ }
+
+ protected ReferenceQueue<V> createQueue()
+ {
+ return new ReferenceQueue<V>();
+ }
+
+ protected void purgeQueue()
+ {
+ if (queue != null)
+ {
+ KeyedReference<K, V> ref;
+ while ((ref = (KeyedReference<K, V>)queue.poll()) != null)
+ {
+ map.remove(ref.getKey());
+ }
+ }
+ }
+
+ protected V dereference(KeyedReference<K, V> ref)
+ {
+ if (ref == null)
+ {
+ return null;
+ }
+
+ return ref.get();
+ }
+
+ protected abstract KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue);
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Strong<K, V> extends ReferenceValueMap<K, V>
+ {
+ public Strong()
+ {
+ }
+
+ public Strong(ConcurrentMap<K, KeyedReference<K, V>> map)
+ {
+ super(map);
+ }
+
+ @Override
+ protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
+ {
+ return new KeyedStrongReference<K, V>(key, value);
+ }
+
+ @Override
+ protected ReferenceQueue<V> createQueue()
+ {
+ return null;
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Soft<K, V> extends ReferenceValueMap<K, V>
+ {
+ public Soft()
+ {
+ }
+
+ public Soft(ConcurrentMap<K, KeyedReference<K, V>> map)
+ {
+ super(map);
+ }
+
+ @Override
+ protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
+ {
+ return new KeyedSoftReference<K, V>(key, value, queue);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ public static class Weak<K, V> extends ReferenceValueMap<K, V>
+ {
+ public Weak()
+ {
+ }
+
+ public Weak(ConcurrentMap<K, KeyedReference<K, V>> map)
+ {
+ super(map);
+ }
+
+ @Override
+ protected KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue)
+ {
+ return new KeyedWeakReference<K, V>(key, value, queue);
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private class EntrySet extends AbstractSet<Map.Entry<K, V>>
+ {
+ public EntrySet()
+ {
+ }
+
+ @Override
+ public int size()
+ {
+ return map.size();
+ }
+
+ @Override
+ public boolean isEmpty()
+ {
+ return map.isEmpty();
+ }
+
+ @Override
+ public boolean contains(Object object)
+ {
+ if (object == null)
+ {
+ throw new IllegalArgumentException("object == null");
+ }
+
+ if (object instanceof Map.Entry<?, ?>)
+ {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
+ Object key = entry.getKey();
+ Object value = entry.getValue();
+ return key != null && value != null && value.equals(get(key));
+ }
+
+ return false;
+ }
+
+ @Override
+ public Iterator<Map.Entry<K, V>> iterator()
+ {
+ return new EntrySetIterator();
+ }
+
+ @Override
+ public Object[] toArray()
+ {
+ Object[] a = new Object[size()];
+ int i = 0;
+ for (Map.Entry<K, V> entry : this)
+ {
+ a[i++] = entry;
+ }
+
+ return a;
+ }
+
+ @Override
+ public <T> T[] toArray(T[] a)
+ {
+ if (a == null)
+ {
+ throw new IllegalArgumentException("array == null");
+ }
+
+ int size = size();
+ if (a.length < size)
+ {
+ a = (T[])java.lang.reflect.Array.newInstance(a.getClass().getComponentType(), size);
+ }
+
+ int i = 0;
+ for (Map.Entry<K, V> entry : this)
+ {
+ a[i++] = (T)entry;
+ }
+
+ if (a.length > size)
+ {
+ a[size] = null;
+ }
+
+ return a;
+ }
+
+ @Override
+ public boolean remove(Object object)
+ {
+ if (object == null)
+ {
+ throw new IllegalArgumentException("object == null");
+ }
+
+ if (object instanceof Map.Entry<?, ?>)
+ {
+ Map.Entry<?, ?> entry = (Map.Entry<?, ?>)object;
+ return map.remove(entry.getKey(), entry.getValue());
+ }
+
+ return false;
+ }
+
+ @Override
+ public void clear()
+ {
+ map.clear();
+ }
+ }
+
+ /**
+ * @author Eike Stepper
+ */
+ private class EntrySetIterator implements Iterator<Map.Entry<K, V>>
+ {
+ private Iterator<Entry<K, KeyedReference<K, V>>> it = map.entrySet().iterator();
+
+ private K lastKey;
+
+ public EntrySetIterator()
+ {
+ }
+
+ public boolean hasNext()
+ {
+ return it.hasNext();
+ }
+
+ public Entry<K, V> next()
+ {
+ Entry<K, KeyedReference<K, V>> entry = it.next();
+ lastKey = entry.getKey();
+ V value = dereference(entry.getValue());
+ return new MapEntry<K, V>(lastKey, value);
+ }
+
+ public void remove()
+ {
+ if (lastKey == null)
+ {
+ throw new IllegalStateException("lastKey == null");
+ }
+
+ map.remove(lastKey);
+ lastKey = null;
+ }
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/Channel.java b/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/Channel.java
index 87a5d67..e19c010 100644
--- a/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/Channel.java
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/Channel.java
@@ -286,6 +286,11 @@ public class Channel extends Lifecycle implements IChannel, IBufferProvider
@Override
public boolean equals(Object obj)
{
+ if (obj == this)
+ {
+ return true;
+ }
+
if (obj instanceof IChannelID)
{
IChannelID that = (IChannelID)obj;