Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2006-10-22 07:32:35 +0000
committerEike Stepper2006-10-22 07:32:35 +0000
commit0fefd7f4fb0598420de8832acdaed52d895eb62f (patch)
treec920c6d93677f7e2e13d603b3a1fd9486b924ce0 /plugins/org.eclipse.net4j/src/org/eclipse/net4j/util
parent4b41c537099072f6d2b7fdba3cfd605666da6e96 (diff)
downloadcdo-0fefd7f4fb0598420de8832acdaed52d895eb62f.tar.gz
cdo-0fefd7f4fb0598420de8832acdaed52d895eb62f.tar.xz
cdo-0fefd7f4fb0598420de8832acdaed52d895eb62f.zip
Initial provisioning of v0.8.0
Diffstat (limited to 'plugins/org.eclipse.net4j/src/org/eclipse/net4j/util')
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Asynchronizer.java25
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Correlator.java25
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/ResultSynchronizer.java96
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Synchronizer.java30
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/SynchronizingCorrelator.java96
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Worker.java25
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/AbstractLifecycle.java115
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Activator.java13
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Deactivator.java13
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Lifecycle.java29
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleListener.java11
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleNotifier.java11
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleUtil.java165
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractCachingMap.java323
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractDelegatingMap.java192
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractCachingRegistry.java162
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java91
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java163
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/DelegatingRegistry.java115
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashCacheRegistry.java45
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java45
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java70
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryElement.java19
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferInputStream.java142
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferOutputStream.java138
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelInputStream.java69
-rw-r--r--plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelOutputStream.java30
27 files changed, 2258 insertions, 0 deletions
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Asynchronizer.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Asynchronizer.java
new file mode 100644
index 0000000000..60840f0777
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Asynchronizer.java
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.concurrent;
+
+/**
+ * @author Eike Stepper
+ */
+public class Asynchronizer
+{
+ public Asynchronizer()
+ {
+ }
+
+ public void addWork(Runnable work)
+ {
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Correlator.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Correlator.java
new file mode 100644
index 0000000000..959fbc3042
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Correlator.java
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.concurrent;
+
+/**
+ * @author Eike Stepper
+ */
+public interface Correlator<CORRELATION, VALUE>
+{
+ public boolean isCorrelated(CORRELATION correlation);
+
+ public VALUE correlate(CORRELATION correlation);
+
+ public VALUE correlateUnique(CORRELATION correlation);
+
+ public VALUE uncorrelate(CORRELATION correlation);
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/ResultSynchronizer.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/ResultSynchronizer.java
new file mode 100644
index 0000000000..a9cf6a9dec
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/ResultSynchronizer.java
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.concurrent;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Eike Stepper
+ */
+public final class ResultSynchronizer<RESULT> implements Synchronizer<RESULT>
+{
+ private RESULT result;
+
+ private Object consumerLock = new Object();
+
+ private CountDownLatch producerLatch = new CountDownLatch(1);
+
+ public ResultSynchronizer()
+ {
+ }
+
+ public RESULT get(long timeout)
+ {
+ try
+ {
+ final long stop = System.currentTimeMillis() + timeout;
+ synchronized (consumerLock)
+ {
+ while (result == null)
+ {
+ try
+ {
+ final long remaining = stop - System.currentTimeMillis();
+ if (remaining <= 0)
+ {
+ return null;
+ }
+
+ consumerLock.wait(Math.min(remaining, 100));
+ }
+ catch (InterruptedException ex)
+ {
+ return null;
+ }
+ }
+
+ return result;
+ }
+ }
+ finally
+ {
+ producerLatch.countDown();
+ }
+ }
+
+ public void put(RESULT result)
+ {
+ synchronized (consumerLock)
+ {
+ this.result = result;
+ consumerLock.notifyAll();
+ }
+ }
+
+ public boolean put(RESULT result, long timeout)
+ {
+ synchronized (consumerLock)
+ {
+ this.result = result;
+ consumerLock.notifyAll();
+ }
+
+ try
+ {
+ if (!producerLatch.await(timeout, TimeUnit.MILLISECONDS))
+ {
+ return false;
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ return false;
+ }
+
+ return true;
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Synchronizer.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Synchronizer.java
new file mode 100644
index 0000000000..b8a432aa50
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Synchronizer.java
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.concurrent;
+
+/**
+ * Synchronizes a producer and a consumer thread letting the producer pass a
+ * value to the consumer. Both producer and consumer must have access to this
+ * {@link Synchronizer} and there must only ever exist one consumer for it. Once
+ * the result value is consumed by the consumer this {@link Synchronizer} must
+ * not be reused.
+ * <p>
+ *
+ * @author Eike Stepper
+ */
+public interface Synchronizer<RESULT>
+{
+ public RESULT get(long timeout);
+
+ public void put(RESULT result);
+
+ public boolean put(RESULT result, long timeout);
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/SynchronizingCorrelator.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/SynchronizingCorrelator.java
new file mode 100644
index 0000000000..58f132fbda
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/SynchronizingCorrelator.java
@@ -0,0 +1,96 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.concurrent;
+
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+
+/**
+ * @author Eike Stepper
+ */
+public class SynchronizingCorrelator<CORRELATION, RESULT> implements
+ Correlator<CORRELATION, Synchronizer<RESULT>>
+{
+ private ConcurrentMap<CORRELATION, Synchronizer<RESULT>> map = new ConcurrentHashMap();
+
+ public boolean isCorrelated(CORRELATION correlation)
+ {
+ return map.containsKey(correlation);
+ }
+
+ public Synchronizer<RESULT> correlate(CORRELATION correlation)
+ {
+ Synchronizer<RESULT> synchronizer = map.get(correlation);
+ if (synchronizer == null)
+ {
+ synchronizer = createSynchronizer(correlation);
+ map.put(correlation, synchronizer);
+ }
+
+ return synchronizer;
+ }
+
+ public Synchronizer<RESULT> correlateUnique(CORRELATION correlation)
+ {
+ Synchronizer<RESULT> synchronizer = createSynchronizer(correlation);
+ if (map.putIfAbsent(correlation, synchronizer) != null)
+ {
+ throw new IllegalStateException("Already correlated: " + correlation);
+ }
+
+ return synchronizer;
+ }
+
+ public Synchronizer<RESULT> uncorrelate(CORRELATION correlation)
+ {
+ return map.remove(correlation);
+ }
+
+ public RESULT get(CORRELATION correlation, long timeout)
+ {
+ return correlate(correlation).get(timeout);
+ }
+
+ public void put(CORRELATION correlation, RESULT result)
+ {
+ correlate(correlation).put(result);
+ }
+
+ public boolean put(CORRELATION correlation, RESULT result, long timeout)
+ {
+ return correlate(correlation).put(result, timeout);
+ }
+
+ protected Synchronizer<RESULT> createSynchronizer(final CORRELATION correlation)
+ {
+ return new Synchronizer<RESULT>()
+ {
+ private Synchronizer<RESULT> delegate = new ResultSynchronizer<RESULT>();
+
+ public RESULT get(long timeout)
+ {
+ RESULT result = delegate.get(timeout);
+ uncorrelate(correlation);
+ return result;
+ }
+
+ public void put(RESULT result)
+ {
+ delegate.put(result);
+ }
+
+ public boolean put(RESULT result, long timeout)
+ {
+ return delegate.put(result, timeout);
+ }
+ };
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Worker.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Worker.java
new file mode 100644
index 0000000000..0a1d268b18
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/concurrent/Worker.java
@@ -0,0 +1,25 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.concurrent;
+
+/**
+ * @author Eike Stepper
+ */
+public class Worker
+{
+ public Worker()
+ {
+ }
+
+ public void addWork(Runnable work)
+ {
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/AbstractLifecycle.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/AbstractLifecycle.java
new file mode 100644
index 0000000000..1fa2d4eb0d
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/AbstractLifecycle.java
@@ -0,0 +1,115 @@
+package org.eclipse.net4j.util.lifecycle;
+
+import java.util.Queue;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class AbstractLifecycle implements Lifecycle, LifecycleNotifier
+{
+ private boolean active;
+
+ /**
+ * Don't initialize lazily to circumvent synchronization!
+ */
+ private Queue<LifecycleListener> listeners = new ConcurrentLinkedQueue();
+
+ protected AbstractLifecycle()
+ {
+ }
+
+ public final void addLifecycleListener(LifecycleListener listener)
+ {
+ listeners.add(listener);
+ }
+
+ public final void removeLifecycleListener(LifecycleListener listener)
+ {
+ listeners.remove(listener);
+ }
+
+ public final synchronized void activate() throws Exception
+ {
+ if (!active)
+ {
+ System.out.println(toString() + ": Activating");
+ onAccessBeforeActivate();
+ onActivate();
+ active = true;
+ fireLifecycleActivated();
+ }
+ }
+
+ public final synchronized Exception deactivate()
+ {
+ if (active)
+ {
+ System.out.println(toString() + ": Deactivating");
+ fireLifecycleDeactivating();
+
+ try
+ {
+ onDeactivate();
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ return ex;
+ }
+ finally
+ {
+ active = false;
+ }
+ }
+
+ return null;
+ }
+
+ public final boolean isActive()
+ {
+ return active;
+ }
+
+ protected void fireLifecycleActivated()
+ {
+ for (LifecycleListener listener : listeners)
+ {
+ try
+ {
+ listener.notifyLifecycleActivated(this);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ protected void fireLifecycleDeactivating()
+ {
+ for (LifecycleListener listener : listeners)
+ {
+ try
+ {
+ listener.notifyLifecycleDeactivating(this);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ protected void onAccessBeforeActivate() throws Exception
+ {
+ }
+
+ protected void onActivate() throws Exception
+ {
+ }
+
+ protected void onDeactivate() throws Exception
+ {
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Activator.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Activator.java
new file mode 100644
index 0000000000..9294ecb754
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Activator.java
@@ -0,0 +1,13 @@
+package org.eclipse.net4j.util.lifecycle;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Activator
+{
+ boolean propagate() default true;
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Deactivator.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Deactivator.java
new file mode 100644
index 0000000000..0781c7d0e7
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Deactivator.java
@@ -0,0 +1,13 @@
+package org.eclipse.net4j.util.lifecycle;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.RUNTIME)
+@Target(ElementType.METHOD)
+public @interface Deactivator
+{
+ boolean propagate() default true;
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Lifecycle.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Lifecycle.java
new file mode 100644
index 0000000000..1556f4c222
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/Lifecycle.java
@@ -0,0 +1,29 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.lifecycle;
+
+/**
+ * @author Eike Stepper
+ */
+public interface Lifecycle
+{
+ public void activate() throws Exception;
+
+ public Exception deactivate();
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface Introspection
+ {
+ public boolean isActive();
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleListener.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleListener.java
new file mode 100644
index 0000000000..eaa3863ff6
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleListener.java
@@ -0,0 +1,11 @@
+package org.eclipse.net4j.util.lifecycle;
+
+/**
+ * @author Eike Stepper
+ */
+public interface LifecycleListener
+{
+ public void notifyLifecycleActivated(LifecycleNotifier notifier);
+
+ public void notifyLifecycleDeactivating(LifecycleNotifier notifier);
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleNotifier.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleNotifier.java
new file mode 100644
index 0000000000..f7f72be4d6
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleNotifier.java
@@ -0,0 +1,11 @@
+package org.eclipse.net4j.util.lifecycle;
+
+/**
+ * @author Eike Stepper
+ */
+public interface LifecycleNotifier extends Lifecycle.Introspection
+{
+ public void addLifecycleListener(LifecycleListener listener);
+
+ public void removeLifecycleListener(LifecycleListener listener);
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleUtil.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleUtil.java
new file mode 100644
index 0000000000..0eeec29f9a
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/lifecycle/LifecycleUtil.java
@@ -0,0 +1,165 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.lifecycle;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+
+/**
+ * @author Eike Stepper
+ */
+public final class LifecycleUtil
+{
+ private LifecycleUtil()
+ {
+ }
+
+ public static boolean isActive(Object object)
+ {
+ if (object instanceof Lifecycle.Introspection)
+ {
+ return ((Lifecycle.Introspection)object).isActive();
+ }
+
+ return true;
+ }
+
+ public static void activate(Object object) throws Exception
+ {
+ activate(object, false);
+ }
+
+ /**
+ * @see Activator
+ */
+ public static void activate(Object object, boolean useAnnotation) throws Exception
+ {
+ if (object instanceof Lifecycle)
+ {
+ ((Lifecycle)object).activate();
+ }
+ else if (useAnnotation)
+ {
+ invokeAnnotation(object, Activator.class);
+ }
+ }
+
+ public static Exception activateSilent(Object object)
+ {
+ return activateSilent(object, false);
+ }
+
+ /**
+ * @see Activator
+ */
+ public static Exception activateSilent(Object object, boolean useAnnotation)
+ {
+ try
+ {
+ activate(object, useAnnotation);
+ return null;
+ }
+ catch (Exception ex)
+ {
+ return ex;
+ }
+ }
+
+ public static Exception deactivate(Object object)
+ {
+ return deactivate(object, false);
+ }
+
+ /**
+ * @see Deactivator
+ */
+ public static Exception deactivate(Object object, boolean useAnnotation)
+ {
+ if (object instanceof Lifecycle)
+ {
+ return ((Lifecycle)object).deactivate();
+ }
+ else if (useAnnotation)
+ {
+ invokeAnnotation(object, Deactivator.class);
+ }
+
+ return null;
+ }
+
+ public static void deactivateNoisy(Object object) throws Exception
+ {
+ deactivateNoisy(object, false);
+ }
+
+ public static void deactivateNoisy(Object object, boolean useAnnotation) throws Exception
+ {
+ Exception ex = deactivate(object, useAnnotation);
+ if (ex != null)
+ {
+ throw ex;
+ }
+ }
+
+ private static void invokeAnnotation(Object object, Class annotationClass)
+ {
+ Class c = object.getClass();
+ while (c != Object.class)
+ {
+ final Method[] methods = c.getDeclaredMethods();
+ for (Method method : methods)
+ {
+ if (method.getParameterTypes().length == 0)
+ {
+ Annotation annotation = method.getAnnotation(annotationClass);
+ if (annotation != null)
+ {
+ invokeMethod(object, method);
+ boolean propagate = annotationClass == Activator.class ? ((Activator)annotation)
+ .propagate() : ((Deactivator)annotation).propagate();
+ if (!propagate)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ c = c.getSuperclass();
+ }
+ }
+
+ private static Object invokeMethod(Object object, Method method)
+ {
+ try
+ {
+ return method.invoke(object, (Object[])null);
+ }
+ catch (IllegalAccessException iae)
+ {
+ try
+ {
+ method.setAccessible(true);
+ return method.invoke(object, (Object[])null);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+
+ return null;
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractCachingMap.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractCachingMap.java
new file mode 100644
index 0000000000..530298e41c
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractCachingMap.java
@@ -0,0 +1,323 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.map;
+
+import java.util.AbstractMap;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation note: {@link AbstractCachingMap} does not preserve the
+ * "modifyable view" contract of {@link Map#entrySet()} as well as of
+ * {@link Map#keySet()}, i.e. they are disconnected sets and modifications
+ * applied to them are not applied to their underlying
+ * {@link AbstractCachingMap}.
+ * <p>
+ *
+ * @author Eike Stepper
+ */
+public abstract class AbstractCachingMap<K, V> extends AbstractDelegatingMap<K, V>
+{
+ protected AbstractCachingMap()
+ {
+ }
+
+ protected AbstractCachingMap(Map<? extends K, ? extends V> t)
+ {
+ super(t);
+ }
+
+ public void clear()
+ {
+ cachedClear();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return cachedContainsKey(key) || delegatedContainsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return cachedContainsValue(value) || cachedContainsValue(value);
+ }
+
+ public Set<Entry<K, V>> entrySet()
+ {
+ return mergedEntrySet();
+ }
+
+ public V get(Object key)
+ {
+ V result = cachedGet(key);
+ if (result == null)
+ {
+ result = delegatedGet(key);
+ }
+
+ return result;
+ }
+
+ public boolean isEmpty()
+ {
+ return cachedIsEmpty() && delegatedIsEmpty();
+ }
+
+ public Set<K> keySet()
+ {
+ return mergedKeySet();
+ }
+
+ public V put(K key, V value)
+ {
+ return cachedPut(key, value);
+ }
+
+ public void putAll(Map<? extends K, ? extends V> t)
+ {
+ cachedPutAll(t);
+ }
+
+ public V remove(Object key)
+ {
+ return cachedRemove(key);
+ }
+
+ public int size()
+ {
+ return keySet().size();
+ }
+
+ public Collection<V> values()
+ {
+ return mergedValues();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return mergedEquals(obj);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return mergedHashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return mergedToString();
+ }
+
+ protected void cachedClear()
+ {
+ getCache().clear();
+ }
+
+ protected boolean cachedContainsKey(Object key)
+ {
+ return getCache().containsKey(key);
+ }
+
+ protected boolean cachedContainsValue(Object value)
+ {
+ return getCache().containsValue(value);
+ }
+
+ protected Set<Entry<K, V>> cachedEntrySet()
+ {
+ return getCache().entrySet();
+ }
+
+ protected V cachedGet(Object key)
+ {
+ return getCache().get(key);
+ }
+
+ protected boolean cachedIsEmpty()
+ {
+ return getCache().isEmpty();
+ }
+
+ protected Set<K> cachedKeySet()
+ {
+ return getCache().keySet();
+ }
+
+ protected V cachedPut(K key, V value)
+ {
+ return getCache().put(key, value);
+ }
+
+ protected void cachedPutAll(Map<? extends K, ? extends V> t)
+ {
+ getCache().putAll(t);
+ }
+
+ protected V cachedRemove(Object key)
+ {
+ return getCache().remove(key);
+ }
+
+ protected int cachedSize()
+ {
+ return getCache().size();
+ }
+
+ protected Collection<V> cachedValues()
+ {
+ return getCache().values();
+ }
+
+ protected boolean cachedEquals(Object obj)
+ {
+ return getCache().equals(obj);
+ }
+
+ protected int cachedHashCode()
+ {
+ return getCache().hashCode();
+ }
+
+ protected String cachedToString()
+ {
+ return getCache().toString();
+ }
+
+ protected Set<Entry<K, V>> mergedEntrySet()
+ {
+ final Map<K, V> merged = new HashMap<K, V>();
+ merged.putAll(getDelegate());
+ merged.putAll(getCache());
+ return merged.entrySet();
+ }
+
+ protected Set<K> mergedKeySet()
+ {
+ final Set<K> merged = new HashSet<K>();
+ merged.addAll(getDelegate().keySet());
+ merged.addAll(getCache().keySet());
+ return merged;
+ }
+
+ protected Collection<V> mergedValues()
+ {
+ final List<V> result = new ArrayList<V>();
+ for (K key : keySet())
+ {
+ result.add(get(key));
+ }
+
+ return result;
+ }
+
+ /**
+ * @see AbstractMap#equals(Object)
+ */
+ protected boolean mergedEquals(Object o)
+ {
+ if (o == this)
+ return true;
+
+ if (!(o instanceof Map))
+ return false;
+
+ Map<K, V> t = (Map<K, V>)o;
+ if (t.size() != size())
+ return false;
+
+ try
+ {
+ Iterator<Entry<K, V>> i = entrySet().iterator();
+ while (i.hasNext())
+ {
+ Entry<K, V> e = i.next();
+ K key = e.getKey();
+ V value = e.getValue();
+ if (value == null)
+ {
+ if (!(t.get(key) == null && t.containsKey(key)))
+ return false;
+ }
+ else
+ {
+ if (!value.equals(t.get(key)))
+ return false;
+ }
+ }
+ }
+ catch (ClassCastException unused)
+ {
+ return false;
+ }
+ catch (NullPointerException unused)
+ {
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * @see AbstractMap#hashCode()
+ */
+ protected int mergedHashCode()
+ {
+ int h = 0;
+ Iterator<Entry<K, V>> i = entrySet().iterator();
+ while (i.hasNext())
+ h += i.next().hashCode();
+ return h;
+ }
+
+ /**
+ * @see AbstractMap#toString()
+ */
+ protected String mergedToString()
+ {
+ StringBuffer buf = new StringBuffer();
+ buf.append("{");
+
+ Iterator<Entry<K, V>> i = entrySet().iterator();
+ boolean hasNext = i.hasNext();
+ while (hasNext)
+ {
+ Entry<K, V> e = i.next();
+ K key = e.getKey();
+ V value = e.getValue();
+ if (key == this)
+ buf.append("(this Map)");
+ else
+ buf.append(key);
+ buf.append("=");
+ if (value == this)
+ buf.append("(this Map)");
+ else
+ buf.append(value);
+ hasNext = i.hasNext();
+ if (hasNext)
+ buf.append(", ");
+ }
+
+ buf.append("}");
+ return buf.toString();
+ }
+
+ protected abstract Map<K, V> getCache();
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractDelegatingMap.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractDelegatingMap.java
new file mode 100644
index 0000000000..ab445ceb70
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/map/AbstractDelegatingMap.java
@@ -0,0 +1,192 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.map;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * Implementation note: {@link AbstractDelegatingMap} does not necessarily
+ * preserve the "modifyable view" contract of {@link Map#entrySet()} as well as
+ * of {@link Map#keySet()}, i.e. they might be disconnected sets and
+ * modifications applied to them might not be applied to their underlying
+ * {@link AbstractDelegatingMap}.
+ * <p>
+ *
+ * @author Eike Stepper
+ */
+public abstract class AbstractDelegatingMap<K, V> implements Map<K, V>
+{
+ protected AbstractDelegatingMap()
+ {
+ }
+
+ protected AbstractDelegatingMap(Map<? extends K, ? extends V> t)
+ {
+ putAll(t);
+ }
+
+ public void clear()
+ {
+ delegatedClear();
+ }
+
+ public boolean containsKey(Object key)
+ {
+ return delegatedContainsKey(key);
+ }
+
+ public boolean containsValue(Object value)
+ {
+ return delegatedContainsValue(value);
+ }
+
+ public Set<Entry<K, V>> entrySet()
+ {
+ return delegatedEntrySet();
+ }
+
+ public V get(Object key)
+ {
+ return delegatedGet(key);
+ }
+
+ public boolean isEmpty()
+ {
+ return delegatedIsEmpty();
+ }
+
+ public Set<K> keySet()
+ {
+ return delegatedKeySet();
+ }
+
+ public V put(K key, V value)
+ {
+ return delegatedPut(key, value);
+ }
+
+ public void putAll(Map<? extends K, ? extends V> t)
+ {
+ delegatedPutAll(t);
+ }
+
+ public V remove(Object key)
+ {
+ return delegatedRemove(key);
+ }
+
+ public int size()
+ {
+ return delegatedSize();
+ }
+
+ public Collection<V> values()
+ {
+ return delegatedValues();
+ }
+
+ @Override
+ public boolean equals(Object obj)
+ {
+ return delegatedEquals(obj);
+ }
+
+ @Override
+ public int hashCode()
+ {
+ return delegatedHashCode();
+ }
+
+ @Override
+ public String toString()
+ {
+ return delegatedToString();
+ }
+
+ protected void delegatedClear()
+ {
+ getDelegate().clear();
+ }
+
+ protected boolean delegatedContainsKey(Object key)
+ {
+ return getDelegate().containsKey(key);
+ }
+
+ protected boolean delegatedContainsValue(Object value)
+ {
+ return getDelegate().containsValue(value);
+ }
+
+ protected Set<Entry<K, V>> delegatedEntrySet()
+ {
+ return getDelegate().entrySet();
+ }
+
+ protected V delegatedGet(Object key)
+ {
+ return getDelegate().get(key);
+ }
+
+ protected boolean delegatedIsEmpty()
+ {
+ return getDelegate().isEmpty();
+ }
+
+ protected Set<K> delegatedKeySet()
+ {
+ return getDelegate().keySet();
+ }
+
+ protected V delegatedPut(K key, V value)
+ {
+ return getDelegate().put(key, value);
+ }
+
+ protected void delegatedPutAll(Map<? extends K, ? extends V> t)
+ {
+ getDelegate().putAll(t);
+ }
+
+ protected V delegatedRemove(Object key)
+ {
+ return getDelegate().remove(key);
+ }
+
+ protected int delegatedSize()
+ {
+ return getDelegate().size();
+ }
+
+ protected Collection<V> delegatedValues()
+ {
+ return getDelegate().values();
+ }
+
+ protected boolean delegatedEquals(Object obj)
+ {
+ return getDelegate().equals(obj);
+ }
+
+ protected int delegatedHashCode()
+ {
+ return getDelegate().hashCode();
+ }
+
+ protected String delegatedToString()
+ {
+ return getDelegate().toString();
+ }
+
+ protected abstract Map<K, V> getDelegate();
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractCachingRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractCachingRegistry.java
new file mode 100644
index 0000000000..c7b116fc24
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractCachingRegistry.java
@@ -0,0 +1,162 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import org.eclipse.net4j.util.registry.IRegistry.Listener.EventType;
+import org.eclipse.net4j.util.registry.IRegistryElement.Descriptor;
+
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * TODO Check if all methods of DelegatingRegistry still do what they should.
+ * TODO Remove DelegatingRegistry?
+ *
+ * @author Eike Stepper
+ */
+public abstract class AbstractCachingRegistry<ID, E extends IRegistryElement<ID>> extends
+ DelegatingRegistry<ID, E>
+{
+ public AbstractCachingRegistry(IRegistry<ID, E> delegate)
+ {
+ this(delegate, DEFAULT_RESOLVING);
+ }
+
+ public AbstractCachingRegistry(IRegistry<ID, E> delegate, boolean resolving)
+ {
+ super(delegate, resolving);
+ }
+
+ @Override
+ public synchronized void register(E element)
+ {
+ ID id = element.getID();
+ E delegatedElement = super.lookup(id, false);
+ E oldElement = getCache().put(id, element);
+
+ if (oldElement == null)
+ {
+ if (delegatedElement != null)
+ {
+ // Unhidden delegated element now becomes hidden
+ fireElementDeregistering(delegatedElement);
+ }
+ }
+ else
+ {
+ fireElementDeregistering(oldElement);
+ oldElement.dispose();
+ }
+
+ fireElementRegistered(element);
+ }
+
+ @Override
+ public synchronized void deregister(ID id)
+ {
+ E delegatedElement = super.lookup(id, false);
+ E element = getCache().remove(id);
+
+ if (element != null)
+ {
+ fireElementDeregistering(element);
+ element.dispose();
+
+ if (delegatedElement != null)
+ {
+ // Hidden delegated element now becomes unhidden
+ fireElementRegistered(delegatedElement);
+ }
+ }
+ }
+
+ /**
+ * Synchronized to support {@link #resolveElement(IRegistryElement)}
+ */
+ @Override
+ public synchronized E lookup(ID id, boolean resolve)
+ {
+ E element = getCache().get(id);
+ if (element == null)
+ {
+ if (resolve)
+ {
+ return resolveDelegatedElement(id);
+ }
+ else
+ {
+ return super.lookup(id, false);
+ }
+ }
+
+ if (resolve)
+ {
+ element = resolveElement(element);
+ }
+
+ return element;
+ }
+
+ @Override
+ public Set<ID> getElementIDs()
+ {
+ Set<ID> ids = new HashSet();
+ ids.addAll(super.getElementIDs());
+ ids.addAll(getCache().keySet());
+ return ids;
+ }
+
+ @Override
+ public synchronized void dispose()
+ {
+ for (E element : getCache().values())
+ {
+ fireElementDeregistering(element);
+ element.dispose();
+ }
+
+ getCache().clear();
+ super.dispose();
+ }
+
+ @Override
+ protected void replaceElement(ID id, E element)
+ {
+ getCache().put(id, element);
+ }
+
+ @Override
+ protected synchronized void handleDelegateEvent(EventType eventType, E element)
+ {
+ if (!getCache().containsKey(element.getID()))
+ {
+ fireRegistryEvent(eventType, element);
+ }
+ }
+
+ protected E resolveDelegatedElement(ID id)
+ {
+ synchronized (getDelegate())
+ {
+ boolean wasUnresolved = super.lookup(id, false) instanceof Descriptor;
+ E e = super.lookup(id, true);
+ if (wasUnresolved)
+ {
+ fireElementResolved(e);
+ }
+
+ return e;
+ }
+ }
+
+ protected abstract Map<ID, E> getCache();
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java
new file mode 100644
index 0000000000..e9c4fd97e6
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java
@@ -0,0 +1,91 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class AbstractMappingRegistry<ID, E extends IRegistryElement<ID>> extends
+ AbstractRegistry<ID, E>
+{
+ public AbstractMappingRegistry()
+ {
+ this(DEFAULT_RESOLVING);
+ }
+
+ public AbstractMappingRegistry(boolean resolving)
+ {
+ super(resolving);
+ }
+
+ public synchronized void register(E element)
+ {
+ E oldElement = getMap().put(element.getID(), element);
+ if (oldElement != null)
+ {
+ fireElementDeregistering(oldElement);
+ oldElement.dispose();
+ }
+
+ fireElementRegistered(element);
+ }
+
+ public synchronized void deregister(ID id)
+ {
+ E element = getMap().remove(id);
+ if (element != null)
+ {
+ fireElementDeregistering(element);
+ element.dispose();
+ }
+ }
+
+ /**
+ * Synchronized to support {@link #resolveElement(IRegistryElement)}
+ */
+ public synchronized E lookup(ID id, boolean resolve)
+ {
+ E element = getMap().get(id);
+ if (resolve)
+ {
+ element = resolveElement(element);
+ }
+
+ return element;
+ }
+
+ public Set<ID> getElementIDs()
+ {
+ return getMap().keySet();
+ }
+
+ @Override
+ public synchronized void dispose()
+ {
+ for (E element : getMap().values())
+ {
+ element.dispose();
+ }
+
+ getMap().clear();
+ }
+
+ @Override
+ protected void replaceElement(ID id, E element)
+ {
+ getMap().put(id, element);
+ }
+
+ protected abstract Map<ID, E> getMap();
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java
new file mode 100644
index 0000000000..3bba7218ef
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java
@@ -0,0 +1,163 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import org.eclipse.net4j.util.registry.IRegistry.Listener.EventType;
+import org.eclipse.net4j.util.registry.IRegistryElement.Descriptor;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+import java.util.Queue;
+import java.util.Set;
+import java.util.concurrent.ConcurrentLinkedQueue;
+
+/**
+ * @author Eike Stepper
+ */
+public abstract class AbstractRegistry<ID, E extends IRegistryElement<ID>> implements
+ IRegistry<ID, E>
+{
+ public static final boolean DEFAULT_RESOLVING = true;
+
+ private boolean resolving;
+
+ /**
+ * Don't initialize lazily to circumvent synchronization!
+ */
+ private Queue<Listener> listeners = new ConcurrentLinkedQueue();
+
+ protected AbstractRegistry()
+ {
+ this(DEFAULT_RESOLVING);
+ }
+
+ public AbstractRegistry(boolean resolving)
+ {
+ setResolving(resolving);
+ }
+
+ public void setResolving(boolean resolving)
+ {
+ this.resolving = resolving;
+ }
+
+ public final boolean isResolving()
+ {
+ return resolving;
+ }
+
+ public final boolean isResolved(ID id)
+ {
+ E element = lookup(id, false);
+ return element != null && !(element instanceof Descriptor);
+ }
+
+ public final boolean isRegistered(ID id)
+ {
+ return lookup(id, false) != null;
+ }
+
+ public int size()
+ {
+ return getElementIDs().size();
+ }
+
+ public final E lookup(ID id)
+ {
+ return lookup(id, isResolving());
+ }
+
+ public final Collection<E> getElements()
+ {
+ return getElements(isResolving());
+ }
+
+ /**
+ * Synchronized to support {@link #resolveElement(IRegistryElement)}
+ */
+ public final synchronized Collection<E> getElements(boolean resolve)
+ {
+ Set<ID> elementKeys = getElementIDs();
+ List<E> elements = new ArrayList<E>(elementKeys.size());
+ for (ID id : elementKeys)
+ {
+ elements.add(lookup(id, resolve));
+ }
+
+ return elements;
+ }
+
+ public void addListener(IRegistry.Listener<ID, E> listener)
+ {
+ listeners.add(listener);
+ }
+
+ public void removeListener(IRegistry.Listener<ID, E> listener)
+ {
+ listeners.remove(listener);
+ }
+
+ public void dispose()
+ {
+ listeners.clear();
+ }
+
+ protected void fireRegistryEvent(EventType eventType, E element)
+ {
+ for (Listener listener : listeners)
+ {
+ try
+ {
+ listener.notifyRegistryEvent(this, eventType, element);
+ }
+ catch (Exception ex)
+ {
+ ex.printStackTrace();
+ }
+ }
+ }
+
+ protected void fireElementRegistered(E element)
+ {
+ fireRegistryEvent(EventType.REGISTERED, element);
+ }
+
+ protected void fireElementDeregistering(E element)
+ {
+ fireRegistryEvent(EventType.DEREGISTERING, element);
+ }
+
+ protected void fireElementResolved(E element)
+ {
+ fireRegistryEvent(EventType.RESOLVED, element);
+ }
+
+ /**
+ * Calling thread must already synchronize on this {@link IRegistry}!
+ */
+ protected E resolveElement(E element)
+ {
+ if (element instanceof Descriptor)
+ {
+ element = (E)((Descriptor)element).resolve();
+ replaceElement(element.getID(), element);
+ fireElementResolved(element);
+ }
+
+ return element;
+ }
+
+ /**
+ * Calling thread must already synchronize on this {@link IRegistry}!
+ */
+ protected abstract void replaceElement(ID id, E element);
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/DelegatingRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/DelegatingRegistry.java
new file mode 100644
index 0000000000..9676232c58
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/DelegatingRegistry.java
@@ -0,0 +1,115 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import org.eclipse.net4j.util.registry.IRegistry.Listener.EventType;
+
+import java.util.Set;
+
+/**
+ * @author Eike Stepper
+ */
+public class DelegatingRegistry<ID, E extends IRegistryElement<ID>> extends AbstractRegistry<ID, E>
+{
+ private IRegistry<ID, E> delegate;
+
+ private Listener<ID, E> delegateListener = new Listener<ID, E>()
+ {
+ public void notifyRegistryEvent(IRegistry<ID, E> registry, EventType eventType, E element)
+ {
+ handleDelegateEvent(eventType, element);
+ }
+ };
+
+ public DelegatingRegistry(IRegistry<ID, E> delegate)
+ {
+ this(delegate, DEFAULT_RESOLVING);
+ }
+
+ public DelegatingRegistry(IRegistry<ID, E> delegate, boolean resolving)
+ {
+ super(resolving);
+ this.delegate = delegate;
+ delegate.addListener(delegateListener);
+ }
+
+ public IRegistry<ID, E> getDelegate()
+ {
+ return delegate;
+ }
+
+ public void register(E element)
+ {
+ delegatedRegister(element);
+ }
+
+ public void deregister(ID id)
+ {
+ delegatedDeregister(id);
+ }
+
+ public E lookup(ID id, boolean resolve)
+ {
+ return delegatedLookup(id, resolve);
+ }
+
+ public Set<ID> getElementIDs()
+ {
+ return delegatedGetElementIDs();
+ }
+
+ @Override
+ public void dispose()
+ {
+ delegate.removeListener(delegateListener);
+ }
+
+ protected void delegatedRegister(E element)
+ {
+ delegate.register(element);
+ }
+
+ protected void delegatedDeregister(ID id)
+ {
+ delegate.deregister(id);
+ }
+
+ protected E delegatedLookup(ID id, boolean resolve)
+ {
+ return delegate.lookup(id, resolve);
+ }
+
+ protected Set<ID> delegatedGetElementIDs()
+ {
+ return delegate.getElementIDs();
+ }
+
+ protected int delegatedSize()
+ {
+ return delegate.size();
+ }
+
+ protected void delegatedDispose()
+ {
+ delegate.dispose();
+ }
+
+ protected void handleDelegateEvent(EventType eventType, E element)
+ {
+ fireRegistryEvent(eventType, element);
+ }
+
+ @Override
+ protected void replaceElement(ID id, E element)
+ {
+ // Do nothing
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashCacheRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashCacheRegistry.java
new file mode 100644
index 0000000000..29f80d4cbc
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashCacheRegistry.java
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class HashCacheRegistry<ID, E extends IRegistryElement<ID>> extends
+ AbstractCachingRegistry<ID, E>
+{
+ private Map<ID, E> cache;
+
+ public HashCacheRegistry(IRegistry<ID, E> delegate)
+ {
+ this(delegate, DEFAULT_RESOLVING);
+ }
+
+ public HashCacheRegistry(IRegistry<ID, E> delegate, boolean resolving)
+ {
+ super(delegate, resolving);
+ cache = createCache();
+ }
+
+ @Override
+ protected Map<ID, E> getCache()
+ {
+ return cache;
+ }
+
+ protected Map<ID, E> createCache()
+ {
+ return new HashMap();
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java
new file mode 100644
index 0000000000..83b75fdaf3
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java
@@ -0,0 +1,45 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Eike Stepper
+ */
+public class HashMapRegistry<ID, E extends IRegistryElement<ID>> extends
+ AbstractMappingRegistry<ID, E>
+{
+ private Map<ID, E> map;
+
+ public HashMapRegistry()
+ {
+ this(DEFAULT_RESOLVING);
+ }
+
+ public HashMapRegistry(boolean resolving)
+ {
+ super(resolving);
+ this.map = createMap();
+ }
+
+ @Override
+ protected Map<ID, E> getMap()
+ {
+ return map;
+ }
+
+ protected Map<ID, E> createMap()
+ {
+ return new HashMap();
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java
new file mode 100644
index 0000000000..86a36a9ef5
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java
@@ -0,0 +1,70 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.registry;
+
+import java.util.Collection;
+import java.util.Set;
+
+/**
+ * Implementation note: {@link Object#equals(Object)} and
+ * {@link Object#hashCode()} are based on pointer equality.
+ * <p>
+ *
+ * @author Eike Stepper
+ */
+public interface IRegistry<ID, E extends IRegistryElement<ID>>
+{
+ public void setResolving(boolean resolving);
+
+ public boolean isResolving();
+
+ public boolean isResolved(ID id);
+
+ public boolean isRegistered(ID id);
+
+ public int size();
+
+ public void register(E element);
+
+ public void deregister(ID id);
+
+ public E lookup(ID id);
+
+ public E lookup(ID id, boolean resolve);
+
+ public Set<ID> getElementIDs();
+
+ public Collection<E> getElements();
+
+ public Collection<E> getElements(boolean resolve);
+
+ public void addListener(Listener<ID, E> listener);
+
+ public void removeListener(Listener<ID, E> listener);
+
+ public void dispose();
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface Listener<ID, E extends IRegistryElement<ID>>
+ {
+ public void notifyRegistryEvent(IRegistry<ID, E> registry, EventType eventType, E element);
+
+ /**
+ * @author Eike Stepper
+ */
+ public enum EventType
+ {
+ REGISTERED, DEREGISTERING, RESOLVED
+ }
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryElement.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryElement.java
new file mode 100644
index 0000000000..b25f11e9b6
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryElement.java
@@ -0,0 +1,19 @@
+package org.eclipse.net4j.util.registry;
+
+/**
+ * @author Eike Stepper
+ */
+public interface IRegistryElement<ID>
+{
+ public ID getID();
+
+ public void dispose();
+
+ /**
+ * @author Eike Stepper
+ */
+ public interface Descriptor<ID> extends IRegistryElement<ID>
+ {
+ public IRegistryElement<ID> resolve();
+ }
+} \ No newline at end of file
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferInputStream.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferInputStream.java
new file mode 100644
index 0000000000..4208f91e91
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferInputStream.java
@@ -0,0 +1,142 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.stream;
+
+import org.eclipse.net4j.transport.Buffer;
+import org.eclipse.net4j.transport.BufferHandler;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.concurrent.BlockingQueue;
+import java.util.concurrent.LinkedBlockingQueue;
+import java.util.concurrent.TimeUnit;
+
+/**
+ * @author Eike Stepper
+ */
+public class BufferInputStream extends InputStream implements BufferHandler
+{
+ public static final long NO_TIMEOUT = -1;
+
+ public static final long DEFAULT_MILLIS_BEFORE_TIMEOUT = NO_TIMEOUT;
+
+ public static final long DEFAULT_MILLIS_INTERRUPT_CHECK = 100;
+
+ private BlockingQueue<Buffer> buffers = new LinkedBlockingQueue<Buffer>();
+
+ private Buffer currentBuffer;
+
+ private boolean eos;
+
+ public BufferInputStream()
+ {
+ }
+
+ public void handleBuffer(Buffer buffer)
+ {
+ buffers.add(buffer);
+ }
+
+ @Override
+ public int read() throws IOException
+ {
+ if (eos && currentBuffer == null)
+ {
+ // End of sequence
+ return -1;
+ }
+
+ if (!ensureBuffer())
+ {
+ // Timeout or interrupt
+ return -1;
+ }
+
+ int result = currentBuffer.getByteBuffer().get() - Byte.MIN_VALUE;
+ if (!currentBuffer.getByteBuffer().hasRemaining())
+ {
+ currentBuffer.release();
+ currentBuffer = null;
+ }
+
+ return result;
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ buffers = null;
+ currentBuffer = null;
+ super.close();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BufferInputStream";
+ }
+
+ protected boolean ensureBuffer() throws IOException
+ {
+ try
+ {
+ final long check = getMillisInterruptCheck();
+ final long timeout = getMillisBeforeTimeout();
+
+ try
+ {
+ if (timeout == NO_TIMEOUT)
+ {
+ while (currentBuffer == null)
+ {
+ currentBuffer = buffers.poll(check, TimeUnit.MILLISECONDS);
+ }
+ }
+ else
+ {
+ final long stop = System.currentTimeMillis() + timeout;
+ while (currentBuffer == null)
+ {
+ final long remaining = stop - System.currentTimeMillis();
+ if (remaining <= 0)
+ {
+ return false;
+ }
+
+ currentBuffer = buffers.poll(Math.min(remaining, check), TimeUnit.MILLISECONDS);
+ }
+ }
+ }
+ catch (InterruptedException ex)
+ {
+ throw new IOException("Interrupted");
+ }
+
+ eos = currentBuffer.isEOS();
+ }
+ catch (RuntimeException ex)
+ {
+ // TODO Remove
+ ex.printStackTrace();
+ }
+ return true;
+ }
+
+ public long getMillisBeforeTimeout()
+ {
+ return DEFAULT_MILLIS_BEFORE_TIMEOUT;
+ }
+
+ public long getMillisInterruptCheck()
+ {
+ return DEFAULT_MILLIS_INTERRUPT_CHECK;
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferOutputStream.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferOutputStream.java
new file mode 100644
index 0000000000..ab67ac766d
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/BufferOutputStream.java
@@ -0,0 +1,138 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.stream;
+
+import org.eclipse.net4j.transport.Buffer;
+import org.eclipse.net4j.transport.BufferHandler;
+import org.eclipse.net4j.transport.BufferProvider;
+import org.eclipse.net4j.util.lifecycle.LifecycleUtil;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.ByteBuffer;
+
+/**
+ * @author Eike Stepper
+ */
+public class BufferOutputStream extends OutputStream
+{
+ public static final boolean DEFAULT_PROPAGATE_CLOSE = false;
+
+ private BufferHandler bufferHandler;
+
+ private BufferProvider bufferProvider;
+
+ private Buffer currentBuffer;
+
+ private short channelID;
+
+ public BufferOutputStream(BufferHandler bufferHandler, BufferProvider bufferProvider,
+ short channelID)
+ {
+ if (bufferHandler == null)
+ {
+ throw new IllegalArgumentException("bufferHandler == null");
+ }
+
+ if (bufferProvider == null)
+ {
+ throw new IllegalArgumentException("bufferProvider == null");
+ }
+
+ this.bufferHandler = bufferHandler;
+ this.bufferProvider = bufferProvider;
+ this.channelID = channelID;
+ }
+
+ public BufferOutputStream(BufferHandler bufferHandler, short channelID)
+ {
+ this(bufferHandler, extractBufferProvider(bufferHandler), channelID);
+ }
+
+ @Override
+ public void write(int b) throws IOException
+ {
+ ensureBuffer();
+ ByteBuffer buffer = currentBuffer.getByteBuffer();
+ buffer.put((byte)(b + Byte.MIN_VALUE));
+
+ if (!buffer.hasRemaining())
+ {
+ flush();
+ }
+ }
+
+ @Override
+ public void flush() throws IOException
+ {
+ if (currentBuffer != null)
+ {
+ bufferHandler.handleBuffer(currentBuffer);
+ currentBuffer = null;
+ }
+ }
+
+ public void flushWithEOS() throws IOException
+ {
+ ensureBuffer();
+ currentBuffer.setEOS(true);
+ flush();
+ }
+
+ @Override
+ public void close() throws IOException
+ {
+ try
+ {
+ if (isPropagateClose())
+ {
+ LifecycleUtil.deactivate(bufferHandler);
+ }
+ }
+ finally
+ {
+ bufferHandler = null;
+ bufferProvider = null;
+ currentBuffer = null;
+ super.close();
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ return "BufferOutputStream";
+ }
+
+ protected void ensureBuffer()
+ {
+ if (currentBuffer == null)
+ {
+ currentBuffer = bufferProvider.provideBuffer();
+ currentBuffer.startPutting(channelID);
+ }
+ }
+
+ protected boolean isPropagateClose()
+ {
+ return DEFAULT_PROPAGATE_CLOSE;
+ }
+
+ private static BufferProvider extractBufferProvider(BufferHandler bufferHandler)
+ {
+ if (bufferHandler instanceof BufferProvider)
+ {
+ return (BufferProvider)bufferHandler;
+ }
+
+ throw new IllegalArgumentException("Buffer handler unable to provide buffers");
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelInputStream.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelInputStream.java
new file mode 100644
index 0000000000..81cfb487f8
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelInputStream.java
@@ -0,0 +1,69 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.stream;
+
+import org.eclipse.net4j.transport.Channel;
+
+/**
+ * @author Eike Stepper
+ */
+public class ChannelInputStream extends BufferInputStream
+{
+ private Channel channel;
+
+ private long millisBeforeTimeout = DEFAULT_MILLIS_BEFORE_TIMEOUT;
+
+ private long millisInterruptCheck = DEFAULT_MILLIS_INTERRUPT_CHECK;
+
+ public ChannelInputStream(Channel channel)
+ {
+ this(channel, DEFAULT_MILLIS_BEFORE_TIMEOUT);
+ }
+
+ public ChannelInputStream(Channel channel, long millisBeforeTimeout)
+ {
+ this.channel = channel;
+ channel.setReceiveHandler(this);
+ this.millisBeforeTimeout = millisBeforeTimeout;
+ millisInterruptCheck = DEFAULT_MILLIS_INTERRUPT_CHECK;
+ }
+
+ public Channel getChannel()
+ {
+ return channel;
+ }
+
+ public long getMillisBeforeTimeout()
+ {
+ return millisBeforeTimeout;
+ }
+
+ public void setMillisBeforeTimeout(long millisBeforeTimeout)
+ {
+ this.millisBeforeTimeout = millisBeforeTimeout;
+ }
+
+ public long getMillisInterruptCheck()
+ {
+ return millisInterruptCheck;
+ }
+
+ public void setMillisInterruptCheck(long millisInterruptCheck)
+ {
+ this.millisInterruptCheck = millisInterruptCheck;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "ChannelInputStream[" + channel + "]";
+ }
+}
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelOutputStream.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelOutputStream.java
new file mode 100644
index 0000000000..2314836ffa
--- /dev/null
+++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/stream/ChannelOutputStream.java
@@ -0,0 +1,30 @@
+/***************************************************************************
+ * Copyright (c) 2004, 2005, 2006 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.stream;
+
+import org.eclipse.net4j.transport.BufferProvider;
+import org.eclipse.net4j.transport.Channel;
+
+/**
+ * @author Eike Stepper
+ */
+public class ChannelOutputStream extends BufferOutputStream
+{
+ public ChannelOutputStream(Channel channel)
+ {
+ super(channel, channel.getChannelID());
+ }
+
+ public ChannelOutputStream(Channel channel, BufferProvider bufferProvider)
+ {
+ super(channel, bufferProvider, channel.getChannelID());
+ }
+}

Back to the top