FELIX-2642 Adapt to implementation to R4.3 draft3 specification

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1067008 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/coordinator/src/main/java/org/apache/felix/coordination/impl/Activator.java b/coordinator/src/main/java/org/apache/felix/coordination/impl/Activator.java
index ca37fd9..7196ec4 100644
--- a/coordinator/src/main/java/org/apache/felix/coordination/impl/Activator.java
+++ b/coordinator/src/main/java/org/apache/felix/coordination/impl/Activator.java
@@ -24,8 +24,8 @@
 import javax.management.MalformedObjectNameException;
 import javax.management.ObjectName;
 
-import org.apache.felix.jmx.service.coordination.CoordinatorMBean;
-import org.apache.felix.service.coordination.Coordinator;
+import org.apache.felix.jmx.service.coordinator.CoordinatorMBean;
+import org.apache.felix.service.coordinator.Coordinator;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleActivator;
 import org.osgi.framework.BundleContext;
diff --git a/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationImpl.java b/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationImpl.java
index 590ab9e..4e2010b 100644
--- a/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationImpl.java
+++ b/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationImpl.java
@@ -25,8 +25,9 @@
 import java.util.Map;
 import java.util.TimerTask;
 
-import org.apache.felix.service.coordination.Coordination;
-import org.apache.felix.service.coordination.Participant;
+import org.apache.felix.service.coordinator.Coordination;
+import org.apache.felix.service.coordinator.CoordinationException;
+import org.apache.felix.service.coordinator.Participant;
 
 @SuppressWarnings("deprecation")
 public class CoordinationImpl implements Coordination
@@ -41,9 +42,6 @@
     /** Coordination completed */
     private static final int TERMINATED = 3;
 
-    /** Coordination failed */
-    private static final int FAILED = 4;
-
     private final CoordinatorImpl owner;
 
     private final long id;
@@ -51,7 +49,7 @@
     private final String name;
 
     // TODO: timeout must be enforced
-    private long timeOutInMs;
+    private long deadLine;
 
     /**
      * Access to this field must be synchronized as long as the expected state
@@ -61,8 +59,6 @@
      */
     private volatile int state;
 
-    private int mustFail;
-
     private Throwable failReason;
 
     private ArrayList<Participant> participants;
@@ -73,19 +69,25 @@
 
     private Thread initiatorThread;
 
-    public CoordinationImpl(final CoordinatorImpl owner, final long id, final String name, final long defaultTimeOutInMs)
+    public CoordinationImpl(final CoordinatorImpl owner, final long id, final String name, final int timeOutInMs)
     {
+        // TODO: validate name against Bundle Symbolic Name pattern
+
         this.owner = owner;
         this.id = id;
         this.name = name;
-        this.mustFail = 0;
         this.state = ACTIVE;
         this.participants = new ArrayList<Participant>();
         this.variables = new HashMap<Class<?>, Object>();
-        this.timeOutInMs = -defaultTimeOutInMs;
+        this.deadLine = (timeOutInMs > 0) ? System.currentTimeMillis() + timeOutInMs : 0;
         this.initiatorThread = Thread.currentThread();
 
-        scheduleTimeout(defaultTimeOutInMs);
+        scheduleTimeout(deadLine);
+    }
+
+    public long getId()
+    {
+        return this.id;
     }
 
     public String getName()
@@ -93,154 +95,83 @@
         return name;
     }
 
-    long getId()
-    {
-        return this.id;
-    }
-
-    void mustFail(final Throwable reason)
-    {
-        this.mustFail = FAILED;
-        this.failReason = reason;
-    }
-
-    /**
-     * Initiates a coordination timeout. Called from the timer task scheduled by
-     * the {@link #scheduleTimeout(long)} method.
-     * <p>
-     * This method is inteded to only be called from the scheduled timer task.
-     */
-    void timeout()
-    {
-        // If a timeout happens, the coordination thread is set to always fail
-        this.mustFail = TIMEOUT;
-
-        // Fail the Coordination upon timeout
-        fail(null);
-    }
-
-    long getTimeOut()
-    {
-        return this.timeOutInMs;
-    }
-
-    public int end() throws IllegalStateException
-    {
-        if (startTermination())
-        {
-            if (mustFail != 0)
-            {
-                failInternal();
-                return mustFail;
-            }
-            return endInternal();
-        }
-
-        // already terminated
-        throw new IllegalStateException();
-    }
-
     public boolean fail(Throwable reason)
     {
         if (startTermination())
         {
             this.failReason = reason;
-            failInternal();
+
+            // consider failure reason (if not null)
+            for (Participant part : participants)
+            {
+                try
+                {
+                    part.failed(this);
+                }
+                catch (Exception e)
+                {
+                    // TODO: log
+                }
+
+                // release the participant for other coordinations
+                owner.releaseParticipant(part);
+            }
+
+            state = TERMINATED;
+
+            synchronized (this)
+            {
+                this.notifyAll();
+            }
+
             return true;
         }
         return false;
     }
 
-    public boolean terminate()
+    public void end()
     {
-        if (state == ACTIVE)
+        if (startTermination())
         {
-            try
+            boolean partialFailure = false;
+            for (Participant part : participants)
             {
-                end();
-                return true;
-            }
-            catch (IllegalStateException ise)
-            {
-                // another thread might have started the termination just
-                // after the current thread checked the state but before the
-                // end() method called on this thread was able to change the
-                // state. Just ignore this exception and continue.
-            }
-        }
-        return false;
-    }
-
-    /**
-     * Returns whether the coordination has ended in failure.
-     * <p>
-     * The return value of <code>false</code> may be a transient situation if
-     * the coordination is in the process of terminating due to a failure.
-     */
-    public boolean isFailed()
-    {
-        return state == FAILED;
-    }
-
-    /**
-     * Returns whether the coordination has ended.
-     * <p>
-     * The return value of <code>false</code> may be a transient situation if
-     * the coordination is in the process of terminating.
-     */
-    public boolean isTerminated()
-    {
-        return state == TERMINATED || state == FAILED;
-    }
-
-    public void addTimeout(long timeOutInMs)
-    {
-        if (this.timeOutInMs > 0)
-        {
-            // already set, ignore
-        }
-
-        this.timeOutInMs = timeOutInMs;
-        scheduleTimeout(timeOutInMs);
-    }
-
-    /**
-     * Adds the participant to the end of the list of participants of this
-     * coordination.
-     * <p>
-     * This method blocks if the given participant is currently participating in
-     * another coordination.
-     * <p>
-     * Participants can only be added to a coordination if it is active.
-     *
-     * @throws org.apache.felix.service.coordination.CoordinationException if
-     *             the participant cannot currently participate in this
-     *             coordination
-     */
-    public boolean participate(Participant p)
-    {
-
-        // ensure participant only pariticipates on a single coordination
-        // this blocks until the participant can participate or until
-        // a timeout occurrs (or a deadlock is detected)
-        owner.lockParticipant(p, this);
-
-        // synchronize access to the state to prevent it from being changed
-        // while adding the participant
-        synchronized (this)
-        {
-            if (state == ACTIVE)
-            {
-                if (!participants.contains(p))
+                try
                 {
-                    participants.add(p);
+                    part.ended(this);
                 }
-                return true;
+                catch (Exception e)
+                {
+                    // TODO: log
+                    partialFailure = true;
+                }
+
+                // release the participant for other coordinations
+                owner.releaseParticipant(part);
             }
-            return false;
+
+            state = TERMINATED;
+
+            synchronized (this)
+            {
+                this.notifyAll();
+            }
+
+            if (partialFailure)
+            {
+                throw new CoordinationException("One or more participants threw while ending the coordination", this,
+                    CoordinationException.PARTIALLY_ENDED);
+            }
+        }
+        else
+        {
+            // already terminated
+            throw new CoordinationException("Coordination " + id + "/" + name + " has already terminated", this,
+                CoordinationException.ALREADY_ENDED);
         }
     }
 
+
     public Collection<Participant> getParticipants()
     {
         // synchronize access to the state to prevent it from being changed
@@ -256,11 +187,131 @@
         return Collections.<Participant> emptyList();
     }
 
+    public Throwable getFailure()
+    {
+        return failReason;
+    }
+
+
+    /**
+     * Adds the participant to the end of the list of participants of this
+     * coordination.
+     * <p>
+     * This method blocks if the given participant is currently participating in
+     * another coordination.
+     * <p>
+     * Participants can only be added to a coordination if it is active.
+     *
+     * @throws org.apache.felix.service.coordination.CoordinationException if
+     *             the participant cannot currently participate in this
+     *             coordination
+     */
+    public void addParticipant(Participant p)
+    {
+
+        // ensure participant only pariticipates on a single coordination
+        // this blocks until the participant can participate or until
+        // a timeout occurrs (or a deadlock is detected)
+        owner.lockParticipant(p, this);
+
+        // synchronize access to the state to prevent it from being changed
+        // while adding the participant
+        synchronized (this)
+        {
+            if (isTerminated())
+            {
+                owner.releaseParticipant(p);
+
+                throw new CoordinationException("Cannot add Participant " + p + " to terminated Coordination", this,
+                    (getFailure() != null) ? CoordinationException.FAILED : CoordinationException.ALREADY_ENDED);
+            }
+
+            if (!participants.contains(p))
+            {
+                participants.add(p);
+            }
+        }
+    }
+
     public Map<Class<?>, ?> getVariables()
     {
         return variables;
     }
 
+    public long extendTimeout(long timeOutInMs)
+    {
+        synchronized (this)
+        {
+            if (isTerminated())
+            {
+                throw new CoordinationException("Cannot extend timeout on terminated Coordination", this,
+                    (getFailure() != null) ? CoordinationException.FAILED : CoordinationException.ALREADY_ENDED);
+            }
+
+            if (timeOutInMs > 0)
+            {
+                this.deadLine += timeOutInMs;
+                scheduleTimeout(this.deadLine);
+            }
+
+            return this.deadLine;
+        }
+    }
+
+    /**
+     * Returns whether the coordination has ended.
+     * <p>
+     * The return value of <code>false</code> may be a transient situation if
+     * the coordination is in the process of terminating.
+     */
+    public boolean isTerminated()
+    {
+        return state != ACTIVE;
+    }
+
+    public Thread getThread()
+    {
+        return initiatorThread;
+    }
+
+    public void join(long timeoutInMillis) throws InterruptedException
+    {
+        synchronized (this)
+        {
+            if (!isTerminated())
+            {
+                this.wait(timeoutInMillis);
+            }
+        }
+    }
+
+    public Coordination push()
+    {
+        // TODO: Check whether this has already been pushed !
+        // throw new CoordinationException("Coordination already pushed", this, CoordinationException.ALREADY_PUSHED);
+
+        return owner.push(this);
+    }
+
+    //-------
+
+    /**
+     * Initiates a coordination timeout. Called from the timer task scheduled by
+     * the {@link #scheduleTimeout(long)} method.
+     * <p>
+     * This method is inteded to only be called from the scheduled timer task.
+     */
+    void timeout()
+    {
+        // Fail the Coordination upon timeout
+        fail(TIMEOUT);
+    }
+
+    long getDeadLine()
+    {
+        return this.deadLine;
+    }
+
     /**
      * If this coordination is still active, this method initiates the
      * termination of the coordination by setting the state to
@@ -288,72 +339,13 @@
     }
 
     /**
-     * Internal implemenation of successful termination of the coordination.
-     * <p>
-     * This method must only be called after the {@link #state} field has been
-     * set to {@link State#TERMINATING} and only be the method successfully
-     * setting this state.
-     *
-     * @return OK or PARTIALLY_ENDED depending on whether all participants
-     *         succeeded or some of them failed ending the coordination.
-     */
-    private int endInternal()
-    {
-        int reason = OK;
-        for (Participant part : participants)
-        {
-            try
-            {
-                part.ended(this);
-            }
-            catch (Exception e)
-            {
-                // TODO: log
-                reason = PARTIALLY_ENDED;
-            }
-
-            // release the participant for other coordinations
-            owner.releaseParticipant(part);
-        }
-        state = TERMINATED;
-        return reason;
-    }
-
-    /**
-     * Internal implemenation of coordination failure.
-     * <p>
-     * This method must only be called after the {@link #state} field has been
-     * set to {@link State#TERMINATING} and only be the method successfully
-     * setting this state.
-     */
-    private void failInternal()
-    {
-        // consider failure reason (if not null)
-        for (Participant part : participants)
-        {
-            try
-            {
-                part.failed(this);
-            }
-            catch (Exception e)
-            {
-                // TODO: log
-            }
-
-            // release the participant for other coordinations
-            owner.releaseParticipant(part);
-        }
-        state = FAILED;
-    }
-
-    /**
      * Helper method for timeout scheduling. If a timer is currently scheduled
      * it is canceled. If the new timeout value is a positive value a new timer
-     * is scheduled to fire of so many milliseconds from now.
+     * is scheduled to fire at the desired time (in the future)
      *
-     * @param timeout The new timeout value
+     * @param deadline The at which to schedule the timer
      */
-    private void scheduleTimeout(final long timeout)
+    private void scheduleTimeout(final long deadLine)
     {
         if (timeoutTask != null)
         {
@@ -361,7 +353,7 @@
             timeoutTask = null;
         }
 
-        if (timeout > 0)
+        if (deadLine > System.currentTimeMillis())
         {
             timeoutTask = new TimerTask()
             {
@@ -372,7 +364,7 @@
                 }
             };
 
-            owner.schedule(timeoutTask, timeout);
+            owner.schedule(timeoutTask, deadLine);
         }
     }
 }
diff --git a/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationMgr.java b/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationMgr.java
index 07aaaf6..b696205 100644
--- a/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationMgr.java
+++ b/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinationMgr.java
@@ -21,6 +21,7 @@
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.Collection;
+import java.util.Date;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.Stack;
@@ -35,10 +36,10 @@
 import javax.management.openmbean.TabularData;
 import javax.management.openmbean.TabularDataSupport;
 
-import org.apache.felix.jmx.service.coordination.CoordinatorMBean;
-import org.apache.felix.service.coordination.Coordination;
-import org.apache.felix.service.coordination.CoordinationException;
-import org.apache.felix.service.coordination.Participant;
+import org.apache.felix.jmx.service.coordinator.CoordinatorMBean;
+import org.apache.felix.service.coordinator.Coordination;
+import org.apache.felix.service.coordinator.CoordinationException;
+import org.apache.felix.service.coordinator.Participant;
 
 /**
  * The <code>CoordinationMgr</code> is the actual backend manager of all
@@ -117,15 +118,15 @@
         this.participationTimeOut = participationTimeout;
     }
 
-    void schedule(final TimerTask task, final long delay)
+    void schedule(final TimerTask task, final long deadLine)
     {
-        if (delay < 0)
+        if (deadLine < 0)
         {
             task.cancel();
         }
         else
         {
-            coordinationTimer.schedule(task, delay);
+            coordinationTimer.schedule(task, new Date(deadLine));
         }
     }
 
@@ -139,20 +140,29 @@
             CoordinationImpl current = participants.get(p);
             while (current != null && current != c)
             {
+                if (current.getThread() == c.getThread())
+                {
+                    throw new CoordinationException("Participant " + p + " already participating in Coordination "
+                        + current.getId() + "/" + current.getName() + " in this thread", c,
+                        CoordinationException.DEADLOCK_DETECTED);
+                }
+
                 try
                 {
                     participants.wait(waitTime);
                 }
                 catch (InterruptedException ie)
                 {
-                    // don't worry, just keep on waiting
+                    throw new CoordinationException("Interrupted waiting to add Participant " + p
+                        + " currently participating in Coordination " + current.getId() + "/" + current.getName()
+                        + " in this thread", c, CoordinationException.LOCK_INTERRUPTED);
                 }
 
                 // timeout waiting for participation
                 if (System.currentTimeMillis() > cutOff)
                 {
-                    throw new CoordinationException("Timed out waiting to join coordinaton", c.getName(),
-                        CoordinationException.TIMEOUT);
+                    throw new CoordinationException("Timed out waiting to join coordinaton", c,
+                        CoordinationException.UNKNOWN);
                 }
 
                 // check again
@@ -175,10 +185,10 @@
 
     // ---------- Coordinator back end implementation
 
-    Coordination create(final CoordinatorImpl owner, final String name)
+    Coordination create(final CoordinatorImpl owner, final String name, final int timeout)
     {
         long id = ctr.incrementAndGet();
-        CoordinationImpl c = new CoordinationImpl(owner, id, name, defaultTimeOut);
+        CoordinationImpl c = new CoordinationImpl(owner, id, name, timeout);
         coordinations.put(id, c);
         return c;
     }
@@ -214,7 +224,7 @@
         return null;
     }
 
-    Coordination getCurrentCoordination()
+    Coordination peek()
     {
         Stack<Coordination> stack = threadStacks.get();
         if (stack != null && !stack.isEmpty())
@@ -235,6 +245,12 @@
         return result;
     }
 
+    Coordination getCoordinationById(final long id)
+    {
+        CoordinationImpl c = coordinations.get(id);
+        return (c == null || c.isTerminated()) ? null : c;
+    }
+
     // ---------- CoordinatorMBean interface
 
     public TabularData listCoordinations(String regexFilter)
@@ -260,12 +276,12 @@
 
     public CompositeData getCoordination(long id) throws IOException
     {
-        CoordinationImpl c = coordinations.get(id);
+        Coordination c = getCoordinationById(id);
         if (c != null)
         {
             try
             {
-                return fromCoordination(c);
+                return fromCoordination((CoordinationImpl) c);
             }
             catch (OpenDataException e)
             {
@@ -277,7 +293,7 @@
 
     public boolean fail(long id, String reason)
     {
-        Coordination c = coordinations.get(id);
+        Coordination c = getCoordinationById(id);
         if (c != null)
         {
             return c.fail(new Exception(reason));
@@ -287,10 +303,10 @@
 
     public void addTimeout(long id, long timeout)
     {
-        Coordination c = coordinations.get(id);
+        Coordination c = getCoordinationById(id);
         if (c != null)
         {
-            c.addTimeout(timeout);
+            c.extendTimeout(timeout);
         }
     }
 
@@ -298,6 +314,6 @@
     {
         return new CompositeDataSupport(COORDINATION_TYPE, new String[]
             { ID, NAME, TIMEOUT }, new Object[]
-            { c.getId(), c.getName(), c.getTimeOut() });
+            { c.getId(), c.getName(), c.getDeadLine() });
     }
 }
diff --git a/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinatorImpl.java b/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinatorImpl.java
index e28fac2..7ef8c6c 100644
--- a/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinatorImpl.java
+++ b/coordinator/src/main/java/org/apache/felix/coordination/impl/CoordinatorImpl.java
@@ -6,9 +6,9 @@
  * to you under the Apache License, Version 2.0 (the
  * "License"); you may not use this file except in compliance
  * with the License. You may obtain a copy of the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing,
  * software distributed under the License is distributed on an
  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
@@ -22,10 +22,10 @@
 import java.util.HashSet;
 import java.util.TimerTask;
 
-import org.apache.felix.service.coordination.Coordination;
-import org.apache.felix.service.coordination.CoordinationException;
-import org.apache.felix.service.coordination.Coordinator;
-import org.apache.felix.service.coordination.Participant;
+import org.apache.felix.service.coordinator.Coordination;
+import org.apache.felix.service.coordinator.CoordinationException;
+import org.apache.felix.service.coordinator.Coordinator;
+import org.apache.felix.service.coordinator.Participant;
 import org.osgi.framework.Bundle;
 
 @SuppressWarnings("deprecation")
@@ -51,7 +51,7 @@
      * <p>
      * Called by the Coordinator ServiceFactory when this CoordinatorImpl
      * instance is not used any longer by the owner bundle.
-     * 
+     *
      * @see FELIX-2671/OSGi Bug 104
      */
     void dispose()
@@ -80,10 +80,10 @@
         }
     }
 
-    public Coordination create(String name)
+    public Coordination create(final String name, final int timeout)
     {
         // TODO: check permission
-        Coordination c = mgr.create(this, name);
+        Coordination c = mgr.create(this, name, timeout);
         synchronized (coordinations)
         {
             coordinations.add(c);
@@ -91,60 +91,67 @@
         return c;
     }
 
-    public Coordination begin(String name)
-    {
-        // TODO: check permission
-        return push(create(name));
-    }
-
-    public Coordination push(Coordination c)
-    {
-        // TODO: check permission
-        return mgr.push(c);
-    }
-
-    public Coordination pop()
-    {
-        // TODO: check permission
-        return mgr.pop();
-    }
-
-    public Coordination getCurrentCoordination()
-    {
-        // TODO: check permission
-        return mgr.getCurrentCoordination();
-    }
-
-    public boolean alwaysFail(Throwable reason)
-    {
-        // TODO: check permission
-        CoordinationImpl current = (CoordinationImpl) getCurrentCoordination();
-        if (current != null)
-        {
-            current.mustFail(reason);
-            return true;
-        }
-        return false;
-    }
-
     public Collection<Coordination> getCoordinations()
     {
         // TODO: check permission
         return mgr.getCoordinations();
     }
 
-    public boolean participate(Participant participant) throws CoordinationException
+    public boolean fail(Throwable reason)
     {
         // TODO: check permission
-        Coordination current = getCurrentCoordination();
+        CoordinationImpl current = (CoordinationImpl) peek();
         if (current != null)
         {
-            current.participate(participant);
+            return current.fail(reason);
+        }
+        return false;
+    }
+
+    public Coordination peek()
+    {
+        // TODO: check permission
+        return mgr.peek();
+    }
+
+    public Coordination begin(final String name, final int timeoutInMillis)
+    {
+        // TODO: check permission
+        return push(create(name, timeoutInMillis));
+    }
+
+    public Coordination pop()
+    {
+        // TODO: check permission
+        return mgr.pop();
+    }
+
+    public boolean addParticipant(Participant participant) throws CoordinationException
+    {
+        // TODO: check permission
+        Coordination current = peek();
+        if (current != null)
+        {
+            current.addParticipant(participant);
             return true;
         }
         return false;
     }
 
+    public Coordination getCoordination(long id)
+    {
+        // TODO: check permission
+        return mgr.getCoordinationById(id);
+    }
+
+    //----------
+
+    Coordination push(Coordination c)
+    {
+        // TODO: check permission
+        return mgr.push(c);
+    }
+
     void unregister(final CoordinationImpl c)
     {
         mgr.unregister(c);
@@ -154,9 +161,9 @@
         }
     }
 
-    void schedule(final TimerTask task, final long delay)
+    void schedule(final TimerTask task, final long deadLine)
     {
-        mgr.schedule(task, delay);
+        mgr.schedule(task, deadLine);
     }
 
     void lockParticipant(final Participant p, final CoordinationImpl c)
diff --git a/coordinator/src/main/java/org/apache/felix/coordination/impl/CrdCommand.java b/coordinator/src/main/java/org/apache/felix/coordination/impl/CrdCommand.java
index edc981c..c8fd5fd 100644
--- a/coordinator/src/main/java/org/apache/felix/coordination/impl/CrdCommand.java
+++ b/coordinator/src/main/java/org/apache/felix/coordination/impl/CrdCommand.java
@@ -21,8 +21,8 @@
 import java.util.Collection;
 import java.util.Hashtable;
 
-import org.apache.felix.service.coordination.Coordination;
-import org.apache.felix.service.coordination.Participant;
+import org.apache.felix.service.coordinator.Coordination;
+import org.apache.felix.service.coordinator.Participant;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleContext;
 import org.osgi.framework.Constants;
diff --git a/coordinator/src/main/java/org/apache/felix/jmx/service/coordination/CoordinatorMBean.java b/coordinator/src/main/java/org/apache/felix/jmx/service/coordinator/CoordinatorMBean.java
similarity index 98%
rename from coordinator/src/main/java/org/apache/felix/jmx/service/coordination/CoordinatorMBean.java
rename to coordinator/src/main/java/org/apache/felix/jmx/service/coordinator/CoordinatorMBean.java
index 8ce307c..0bb069b 100644
--- a/coordinator/src/main/java/org/apache/felix/jmx/service/coordination/CoordinatorMBean.java
+++ b/coordinator/src/main/java/org/apache/felix/jmx/service/coordinator/CoordinatorMBean.java
@@ -13,7 +13,7 @@
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.jmx.service.coordination;
+package org.apache.felix.jmx.service.coordinator;
 
 import java.io.IOException;
 
diff --git a/coordinator/src/main/java/org/apache/felix/jmx/service/coordination/package-info.java b/coordinator/src/main/java/org/apache/felix/jmx/service/coordinator/package-info.java
similarity index 96%
rename from coordinator/src/main/java/org/apache/felix/jmx/service/coordination/package-info.java
rename to coordinator/src/main/java/org/apache/felix/jmx/service/coordinator/package-info.java
index 1fbc826..2c3417e 100644
--- a/coordinator/src/main/java/org/apache/felix/jmx/service/coordination/package-info.java
+++ b/coordinator/src/main/java/org/apache/felix/jmx/service/coordinator/package-info.java
@@ -34,5 +34,5 @@
  * @Provisional
  */
 @Deprecated
-package org.apache.felix.jmx.service.coordination;
+package org.apache.felix.jmx.service.coordinator;
 
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordination/Coordination.java b/coordinator/src/main/java/org/apache/felix/service/coordination/Coordination.java
deleted file mode 100644
index 2686d8f..0000000
--- a/coordinator/src/main/java/org/apache/felix/service/coordination/Coordination.java
+++ /dev/null
@@ -1,210 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.service.coordination;
-
-import java.util.Collection;
-import java.util.Map;
-
-/**
- * A Coordination object is used to coordinate a number of independent
- * participants. Once a Coordination is created, it can be used to add
- * Participant objects. When the Coordination is ended, the participants are
- * called back. A Coordination can also fail for various reasons, in that case
- * the participants are informed of this failure.
- * 
- * @ThreadSafe
- * @Provisional
- */
-@Deprecated
-public interface Coordination
-{
-    /**
-     * Return value of end(). The Coordination ended normally, no participant
-     * threw an exception.
-     */
-    public static final int OK = 0;
-
-    /**
-     * Return value of end(). The Coordination did not end normally, a
-     * participant threw an exception making the outcome unclear.
-     */
-    public static final int PARTIALLY_ENDED = 1;
-
-    /**
-     * Return value of end(). The Coordination was set to always fail
-     * (fail(Throwable)).
-     */
-    public static final int FAILED = 2;
-
-    /**
-     * Return value of end(). The Coordination failed because it had timed out.
-     */
-    public static final int TIMEOUT = 3;
-
-    /**
-     * Return the name of this Coordination. The name is given in the
-     * Coordinator.begin(String) or Coordinator.create(String) method.
-     * 
-     * @return the name of this Coordination
-     */
-    String getName();
-
-    /**
-     * Fail and then end this Coordination while returning the outcome. Any
-     * participants will be called on their Participant.failed(Coordination)
-     * method. Participants must assume that the Coordination failed and should
-     * discard and cleanup any work that was processed during this Coordination.
-     * The fail method must terminate the current Coordination before any of the
-     * failed methods are called. That is, the Participant.failed(Coordination)
-     * methods must be running outside the current coordination, no participants
-     * can be added during the termination phase. A fail method must return
-     * silently when the Coordination has already finished.
-     * 
-     * @param reasonThrowable describing the reason of the failure for
-     *            documentation
-     * @return true if the Coordination was still active, otherwise false
-     */
-    boolean fail(Throwable reason);
-
-    /**
-     * If the Coordination is terminated then return, otherwise set the
-     * Coordination to fail. This method enables the following fail-safe pattern
-     * to ensure Coordinations are properly terminated.
-     * 
-     * <pre>
-     * Coordination c = coordinator.begin("show_fail");
-     *     try {
-     *         work1();
-     *         work2();
-     *         if ( end() != OK )
-     *             log("...");
-     *     } catch( SomeException e) {
-     *         ...
-     *     } finally {
-     *         c.terminate();
-     *     }
-     * </pre>
-     * <p>
-     * With this pattern, it is easy to ensure that the coordination is always
-     * terminated.
-     * 
-     * @return true if this method actually terminated the coordination (that
-     *         is, it was not properly ended). false if the Coordination was
-     *         already properly terminate by an end() or fail(Throwable) method.
-     */
-    boolean terminate();
-
-    /**
-     * End the current Coordination. Any participants will be called on their
-     * Participant.ended(Coordination) method. This end() method indicates that
-     * the Coordination has properly terminated and any participants should The
-     * end method must terminate the current Coordination before any of the
-     * Participant.ended(Coordination) methods is called. That is, the
-     * Participant.ended(Coordination) methods must be running outside the
-     * current coordination, no participants can be added during the termination
-     * phase. This method returns the outcome of the Coordination:
-     * <ol>
-     * <li>OK - Correct outcome, no exceptions thrown</li>
-     * <li>PARTIALLY_ENDED - One of the participants threw an exception</li>
-     * <li>FAILED - The Coordination was set to always fail</li>
-     * </ol>
-     * 
-     * @return OK, PARTIALLY_ENDED, FAILED
-     * @throws IllegalStateException when the Coordination is already
-     *             terminated.
-     */
-    int end() throws IllegalStateException;
-
-    /**
-     * Return the current list of participants that joined the Coordination.
-     * This list is only valid as long as the Coordination has not been
-     * terminated. That is, after end() or fail(Throwable) is called this method
-     * will return an empty list.
-     * 
-     * @return list of participants.
-     * @throws SecurityException This method requires the action for the
-     *             CoordinationPermission.
-     */
-    Collection<Participant> getParticipants();
-
-    /**
-     * @return true if this Coordination has failed, false otherwise.
-     */
-    boolean isFailed();
-
-    /**
-     * @return true if this Coordination has terminated, false otherwise.
-     */
-    boolean isTerminated();
-
-    /**
-     * Add a minimum timeout for this Coordination. If this timeout expires,
-     * then the Coordination will fail and the initiating thread will be
-     * interrupted. This method must only be called on an active Coordination,
-     * that is, before end() or fail(Throwable) is called. If the current
-     * deadline is arriving later than the given timeout then the timeout is
-     * ignored.
-     * 
-     * @param timeOutInMsNumber of ms to wait, zero means forever.
-     * @throws SecurityException This method requires the or action for the
-     *             CoordinationPermission. participate
-     */
-    void addTimeout(long timeOutInMs);
-
-    /**
-     * Add a Participant to this Coordination. If this method returns true then
-     * there was a current Coordination and the participant has successfully
-     * joined it. If there was no current Coordination then false is returned.
-     * Once a Participant is participating it is guaranteed to receive a call
-     * back on either the Participant.ended(Coordination) or
-     * Participant.failed(Coordination) method when the Coordination is
-     * terminated. A participant can be added to the Coordination multiple times
-     * but it must only be called back once when the Coordination is terminated.
-     * A Participant can only participate at a single Coordination, if it
-     * attempts to block at another Coordination, then it will block until prior
-     * Coordinations are finished. Notice that in edge cases the call back can
-     * happen before this method returns. The ordering of the call-backs must
-     * follow the order of participation. If participant is participating
-     * multiple times the first time it participates defines this order.
-     * 
-     * @return true if the Coordination was active, otherwise false.
-     * @throws CoordinationException - This exception should normally not be
-     *             caught by the caller but allowed to bubble up to the
-     *             initiator of the coordination, it is therefore a
-     *             RuntimeException. It signals that this participant could not
-     *             participate the current coordination. This can be cause by
-     *             the following reasons:
-     *             <ol>
-     *             <li>CoordinationException.DEADLOCK_DETECTED</li>
-     *             <li>CoordinationException.TIMEOUT</li>
-     *             <li>CoordinationException.UNKNOWN</li>
-     *             </ol>
-     * @throws SecurityException This method requires the action for the current
-     *             Coordination, if any.
-     */
-    boolean participate(Participant p);
-
-    /**
-     * A utility map associated with the current Coordination. Each coordination
-     * carries a map that can be used for communicating between different
-     * participants. To namespace of the map is a class, allowing for private
-     * date to be stored in the map by using implementation classes or shared
-     * data by interfaces.
-     * 
-     * @return The map
-     */
-    Map<Class<?>, ?> getVariables();
-}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordination/CoordinationException.java b/coordinator/src/main/java/org/apache/felix/service/coordination/CoordinationException.java
deleted file mode 100644
index 8221fe0..0000000
--- a/coordinator/src/main/java/org/apache/felix/service/coordination/CoordinationException.java
+++ /dev/null
@@ -1,82 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.service.coordination;
-
-/**
- * Thrown when an implementation detects a potential deadlock situation that it
- * cannot solve. The name of the current coordination is given as argument.
- * 
- * @Provisional
- */
-@Deprecated
-public class CoordinationException extends RuntimeException
-{
-
-    private static final long serialVersionUID = -4466063711012717361L;
-
-    /**
-     * Unknown reason fot this exception.
-     */
-    public static final int UNKNOWN = 0;
-
-    /**
-     * Adding a participant caused a deadlock.
-     */
-    public static final int DEADLOCK_DETECTED = 1;
-
-    /**
-     * The Coordination took too long to finish.
-     */
-    public static final int TIMEOUT = 2;
-
-    private final String name;
-
-    private final int reason;
-
-    /**
-     * Create a new Coordination Exception.
-     * 
-     * @param message The message
-     * @param name The name of the Coordination
-     * @param reason The reason for the exception.
-     */
-    public CoordinationException(String message, String name, int reason)
-    {
-        super(message);
-        this.name = name;
-        this.reason = reason;
-    }
-
-    /**
-     * Answer the name of the Coordination associated with this exception.
-     * 
-     * @return the Coordination name
-     */
-    public String getName()
-    {
-        return name;
-    }
-
-    /**
-     * Answer the reason.
-     * 
-     * @return the reason
-     */
-    public int getReason()
-    {
-        return reason;
-    }
-}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordination/Coordinator.java b/coordinator/src/main/java/org/apache/felix/service/coordination/Coordinator.java
deleted file mode 100644
index 4b49591..0000000
--- a/coordinator/src/main/java/org/apache/felix/service/coordination/Coordinator.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.service.coordination;
-
-import java.util.Collection;
-
-/**
- * A Coordinator service provides a facility to coordinate activities between
- * different parties. The Coordinator is a factory of Coordination objects.
- * Coordination objects can be created. Once created, they can be pushed on a
- * thread local stack push(Coordination) as an implicit parameter for calls to
- * other parties, or they can be passed as an argument. The current top of the
- * thread local stack can be obtained with getCurrentCoordination(). The
- * participate(Participant) method on this service or the
- * Coordination.participate(Participant) method can be used to participate in a
- * Coordination. Participants can only participate in a single Coordination, if
- * a Participant object is added to two different Coordinations it will block
- * until any prior Coordination has been ended. A Coordination can end correctly
- * when the Coordination.end() method is called or when it fails. If the
- * Coordination ends correctly, all its participants are called on the
- * Participant.ended(Coordination) method, otherwise the
- * Participant.failed(Coordination) is called. A Coordination can fail because
- * it times out or it is explicitly failed. A Coordination will timeout after an
- * implementation defined amount of time that must be higher than 30 seconds
- * unless overridden with configuration. This time can be set on a per
- * Coordination basis with the Coordination.addTimeout(long) method. The typical
- * usage of the Coordinator service is as follows:
- * 
- * <pre>
- * Coordination coordination = coordinator.begin(&quot;mycoordination&quot;);
- * try
- * {
- *     doWork();
- *     if (coordination.end() != Coordination.OK)
- *         log(&quot;failed&quot;);
- * }
- * finally
- * {
- *     coordination.terminate();
- * }
- * </pre>
- * <p>
- * In the doWork() method, code can be called that requires a callback at the
- * end of the Coordination. This code is for a Participant.
- * 
- * <pre>
- * void doWork()
- * {
- *     if (coordinator.participate(this))
- *     {
- *         beginWork();
- *     }
- *     else
- *     {
- *         beginWork();
- *         finishWork();
- *     }
- * }
- * 
- * void ended()
- * {
- *     finishWork();
- * }
- * 
- * void failed()
- * {
- *     undoWork();
- * }
- * </pre>
- * <p>
- * Life cycle. All Coordinations that are begun through this service must
- * automatically fail before this service is ungotten.
- * 
- * @ThreadSafe
- * @Provisional
- */
-@Deprecated
-public interface Coordinator
-{
-
-    /**
-     * Create a new Coordination that is not associated with the current thread.
-     * Parameters:
-     * 
-     * @param name The name of this coordination, a name does not have to be
-     *            unique.
-     * @return The new Coordination object or null
-     * @throws SecurityException This method requires the action, no bundle
-     *             check is done.
-     */
-    Coordination create(String name);
-
-    /**
-     * Begin a new Coordination and push it on the thread local stack with
-     * push(Coordination). Parameters:
-     * 
-     * @param name The name of this coordination, a name does not have to be
-     *            unique.
-     * @return A new Coordination object
-     * @throws SecurityException This method requires the action, no bundle
-     *             check is done.
-     */
-    Coordination begin(String name);
-
-    /**
-     * Associate the given Coordination object with a thread local stack. The
-     * top of the thread local stack is returned with the
-     * getCurrentCoordination() method. To remove the Coordination from the top
-     * call pop().
-     * 
-     * @param c The Coordination to push
-     * @return c (for the builder pattern purpose)
-     */
-    Coordination push(Coordination c);
-
-    /**
-     * Pop the top of the thread local stack of Coordinations. If no current
-     * Coordination is present, return null.
-     * 
-     * @return The top of the stack or null
-     */
-    Coordination pop();
-
-    /**
-     * Participate in the current Coordination or return false if there is none.
-     * This method calls getCurrentCoordination(), if it is null, it will return
-     * false. Otherwise it will call Coordination.participate(Participant) and
-     * return the result of that method.
-     * 
-     * @param participant The participant of the Coordination
-     * @return true if there was a current Coordination that could be
-     *         successfully used to participate, otherwise false.
-     * @throws CoordinationException This exception should normally not be
-     *             caught by the caller but allowed to bubble up to the
-     *             initiator of the coordination, it is therefore a
-     *             RuntimeException. It signals that this participant could not
-     *             participate the current coordination. This can be cause by
-     *             the following reasons:
-     *             <ol>
-     *             <li>CoordinationException.DEADLOCK_DETECTED</li>
-     *             <li>CoordinationException.TIMEOUT</li>
-     *             <li>CoordinationException.UNKNOWN</li>
-     *             </ol>
-     * @throws SecurityException This method requires the action for the current
-     *             Coordination, if any.
-     */
-    boolean participate(Participant participant) throws CoordinationException;
-
-    /**
-     * Always fail the current Coordination, if exists. Must fail the current
-     * Coordination and return true or return false if there is no current
-     * Coordination.
-     * 
-     * @param reason Throwable describing why the collaboration must always fail
-     *            for debugging or null.
-     * @return true if there was a current Coordination and false if not.
-     */
-    boolean alwaysFail(Throwable reason);
-
-    /**
-     * Return the current Coordination. The current Coordination is the top of
-     * the thread local stack of Coordinations. If the stack is empty, there is
-     * no current Coordination.
-     * 
-     * @return null when the thread local stack is empty, otherwise the top of
-     *         the thread local stack of Coordinations.
-     */
-    Coordination getCurrentCoordination();
-
-    /**
-     * Provide a list of all Coordination objects. Answer a read only list of
-     * active Coordination. This list must be a mutable snapshot of the current
-     * situation. Changes to the list must not affect the original. Coordination
-     * objects are capabilities and designed to be used only on the Coordination
-     * thread. The returned list must only contain the Coordinations for which
-     * the caller has , without this permission an empty list must be returned.
-     * 
-     * @return a list of Coordination objects
-     */
-    Collection<Coordination> getCoordinations();
-}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordination/Participant.java b/coordinator/src/main/java/org/apache/felix/service/coordination/Participant.java
deleted file mode 100644
index 4a40c66..0000000
--- a/coordinator/src/main/java/org/apache/felix/service/coordination/Participant.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
- * 
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- * 
- * http://www.apache.org/licenses/LICENSE-2.0
- * 
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.felix.service.coordination;
-
-/**
- * A Participant participates in a Coordination. A Participant can participate
- * in a Coordination by calling Coordinator.participate(Participant) or
- * Coordinator.participateOrBegin(Participant). After successfully initiating
- * the participation, the Participant is called back when the Coordination is
- * terminated. If a Coordination ends with the Coordination.end() method, then
- * all the participants are called back on their ended(Coordination) method. If
- * the initiator decides to fail the Coordination (or another party has called
- * Coordinator.alwaysFail(Throwable)) then the failed(Coordination) method is
- * called back. Participants are required to be thread safe for the
- * ended(Coordination) method and the failed(Coordination) method. Both methods
- * can be called on another thread. A Coordinator service must block a
- * Participant when it tries to participate in multiple Coordinations.
- * 
- * @ThreadSafe
- * @Provisional
- */
-@Deprecated
-public interface Participant
-{
-
-    /**
-     * The Coordination has failed and the participant is informed. A
-     * participant should properly discard any work it has done during the
-     * active coordination.
-     * 
-     * @param c The Coordination that does the callback
-     * @throws Exception Any exception thrown should be logged but is further
-     *             ignored and does not influence the outcome of the
-     *             Coordination.
-     */
-    void failed(Coordination c) throws Exception;
-
-    /**
-     * The Coordination is being ended.
-     * 
-     * @param c The Coordination that does the callback
-     * @throws Exception If an exception is thrown it should be logged and the
-     *             return of the Coordination.end() method must be
-     *             Coordination.PARTIALLY_ENDED.
-     */
-    void ended(Coordination c) throws Exception;
-}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordinator/Coordination.java b/coordinator/src/main/java/org/apache/felix/service/coordinator/Coordination.java
new file mode 100644
index 0000000..0857feb
--- /dev/null
+++ b/coordinator/src/main/java/org/apache/felix/service/coordinator/Coordination.java
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.service.coordinator;
+
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * A Coordination object is used to coordinate a number of independent
+ * participants. Once a Coordination is created, it can be used to add
+ * Participant objects. When the Coordination is ended, the participants are
+ * called back. A Coordination can also fail for various reasons, in that case
+ * the participants are informed of this failure.
+ *
+ * @ThreadSafe
+ * @Provisional
+ */
+@Deprecated
+public interface Coordination
+{
+
+    /**
+     * The TIMEOUT exception is a singleton exception that will the reason for
+     * the failure when the Coordination times out.
+     */
+    public static final Exception TIMEOUT = new Exception();
+
+    /**
+     * A system assigned ID unique for a specific registered Coordinator. This
+     * id must not be reused as long as the Coordinator is registered and must
+     * be monotonically increasing for each Coordination and always be positive.
+     *
+     * @return an id
+     */
+    long getId();
+
+    /**
+     * Return the name of this Coordination. The name is given in the
+     * {@link Coordinator#begin(String, int)} or
+     * {@link Coordinator#create(String, int)} method. The name should follow
+     * the same naming pattern as a Bundle Symbolc Name.
+     *
+     * @return the name of this Coordination
+     */
+    String getName();
+
+    /**
+     * Fail this Coordination. If this Coordination is not terminated, fail it
+     * and call the {@link Participant#failed(Coordination)} method on all
+     * participant on the current thread. Participants must assume that the
+     * Coordination failed and should discard and cleanup any work that was
+     * processed during this Coordination. The {@link #fail(Throwable)} method
+     * will return <code>true</code> if it caused the termination. A fail method
+     * must return silently when the Coordination has already finished and
+     * return <code>false</code>. The fail method must terminate the current
+     * Coordination before any of the failed methods are called. That is, the
+     * {@link Participant#failed(Coordination)} methods must be running outside
+     * the current coordination, adding participants during this phase will
+     * cause a Configuration Exception to be thrown. If the Coordination is
+     * pushed on the Coordinator stack it is associated with a specific thread.
+     *
+     * @param reason The reason of the failure, must not be <code>null</code>
+     * @return true if the Coordination was active and this coordination was
+     *         terminated due to this call, otherwise false
+     */
+    boolean fail(Throwable reason);
+
+    /**
+     * End the current Coordination.
+     *
+     * <pre>
+     * void foo() throws CoordinationException
+     * {
+     *     Coordination c = coordinator.begin(&quot;work&quot;, 0);
+     *     try
+     *     {
+     *         doWork();
+     *     }
+     *     catch (Exception e)
+     *     {
+     *         c.fail(e);
+     *     }
+     *     finally
+     *     {
+     *         c.end();
+     *     }
+     * }
+     * </pre>
+     *
+     * If the coordination was terminated this method throws a Configuration
+     * Exception. Otherwise, any participants will be called on their
+     * {@link Participant#ended(Coordination)} method. A successful return of
+     * this {@link #end()} method indicates that the Coordination has properly
+     * terminated and any participants have been informed of the positive
+     * outcome. It is possible that one of the participants throws an exception
+     * during the callback. If this happens, the coordination fails partially
+     * and this is reported with an exception. This method must terminate the
+     * current Coordination before any of the
+     * {@link Participant#ended(Coordination)} methods are called. That is, the
+     * {@link Participant#ended(Coordination)} methods must be running outside
+     * the current coordination, no participants can be added during the
+     * termination phase. If the Coordination is on a thread local stack then it
+     * must be removed from this stack during termination.
+     *
+     * @throws CoordinationException when the Coordination has (partially)
+     *             failed or timed out.
+     *             <ol>
+     *             <li>{@link CoordinationException#PARTIALLY_ENDED}</li>
+     *             <li>{@link CoordinationException#ALREADY_ENDED}</li>
+     *             <li>{@link CoordinationException#FAILED}</li>
+     *             <li>{@link CoordinationException#UNKNOWN}</li>
+     *             </ol>
+     */
+    void end() throws CoordinationException;
+
+    /**
+     * Return a mutable snapshot of the participants that joined the
+     * Coordination. Each unique Participant object as defined by its identity
+     * occurs only once in this list.
+     *
+     * @return list of participants.
+     * @throws SecurityException This method requires the
+     *             {@link CoordinationPermission#ADMIN} action for the
+     *             {@link CoordinationPermission}.
+     */
+    Collection<Participant> getParticipants();
+
+    /**
+     * If the coordination has failed because {@link #fail(Throwable)} was
+     * called then this method can provide the Throwable that was given as
+     * argument to the {@link #fail(Throwable)} method. A timeout on this
+     * Coordination will set the failure to a TimeoutException.
+     *
+     * @return a Throwable if this Coordination has failed, otherwise
+     *         <code>null</code> if no failure occurred.
+     */
+    Throwable getFailure();
+
+    /**
+     * Add a Participant to this Coordination. Once a Participant is
+     * participating it is guaranteed to receive a call back on either the
+     * {@link Participant#ended(Coordination)} or
+     * {@link Participant#failed(Coordination)} method when the Coordination is
+     * terminated. A participant can be added to the Coordination multiple times
+     * but it must only be called back once when the Coordination is terminated.
+     * A Participant can only participate at a single Coordination, if it
+     * attempts to block at another Coordination, then it will block until prior
+     * Coordinations are finished. Notice that in edge cases the call back can
+     * happen before this method returns. The ordering of the call-backs must
+     * follow the order of participation. If participant is participating
+     * multiple times the first time it participates defines this order.
+     * *@param participant The participant of the Coordination
+     *
+     * @throws CoordinationException This exception should normally not be
+     *             caught by the caller but allowed to bubble up to the
+     *             initiator of the coordination, it is therefore a
+     *             <code>RuntimeException</code>. It signals that this
+     *             participant could not
+     *             participate the current coordination. This can be cause by
+     *             the following reasons:
+     *             <ol>
+     *             <li>{@link CoordinationException#DEADLOCK_DETECTED}</li>
+     *             <li>{@link CoordinationException#ALREADY_ENDED}</li>
+     *             <li>{@link CoordinationException#LOCK_INTERRUPTED}</li>
+     *             <li>{@link CoordinationException#FAILED}</li>
+     *             <li>{@link CoordinationException#UNKNOWN}</li>
+     *             </ol>
+     * @throws SecurityException This method requires the
+     *             {@link CoordinationPermission#PARTICIPATE} action for the
+     *             current Coordination, if any.
+     */
+    void addParticipant(Participant participant);
+
+    /**
+     * A utility map associated with the current Coordination. Each coordination
+     * carries a map that can be used for communicating between different
+     * participants. To namespace of the map is a class, allowing for private
+     * date to be stored in the map by using implementation classes or shared
+     * data by interfaces. The returned map is does not have to not
+     * synchronized. Users of this map must synchronize on the Map object while
+     * making changes.
+     *
+     * @return The map
+     */
+    Map<Class<?>, ?> getVariables();
+
+    /**
+     * Extend the time out. Allows participants to extend the timeout of the
+     * coordination with at least the given amount. This can be done by
+     * participants when they know a task will take more than normal time. This
+     * method returns the new deadline. Passing 0 will return the existing
+     * deadline.
+     *
+     * @param timeInMillis Add this timeout to the current timeout. If the
+     *            current timeout was set to 0, no extension must take place. A
+     *            zero or negative value must have no effect.
+     * @return the new deadline in the format of
+     *         <code>System.currentTimeMillis()</code> or 0 if no timeout was
+     *         set.
+     * @throws CoordinationException Can throw
+     *             <ol>
+     *             <li>{@link CoordinationException#ALREADY_ENDED}</li>
+     *             <li>{@link CoordinationException#FAILED}</li>
+     *             <li>{@link CoordinationException#UNKNOWN}</li>
+     *             </ol>
+     */
+    long extendTimeout(long timeInMs) throws CoordinationException;
+
+    /**
+     * @return true if this Coordination has terminated otherwise false.
+     */
+    boolean isTerminated();
+
+    /**
+     * Answer the associated thread or null.
+     *
+     * @return Associated thread or null
+     */
+    Thread getThread();
+
+    /**
+     * Wait until the Coordination is terminated and all Participant objects
+     * have been called.
+     *
+     * @param timeoutInMillis Maximum time to wait, 0 is forever
+     * @throws InterruptedException If the wait is interrupted
+     */
+    void join(long timeoutInMillis) throws InterruptedException;
+
+    /**
+     * Associate the given Coordination object with a thread local stack of its
+     * Coordinator. The top of the thread local stack is returned with the
+     * {@link Coordinator#peek()} method. To remove the Coordination from the
+     * top call {@link Coordinator#pop()}.
+     *
+     * @return this (for the builder pattern purpose)
+     * @throws CoordinationException Can throw the
+     *             <ol>
+     *             <li>{@link CoordinationException#ALREADY_PUSHED}</li>
+     *             <li>{@link CoordinationException#UNKNOWN}</li>
+     *             </ol>
+     */
+    Coordination push() throws CoordinationException;
+}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordinator/CoordinationException.java b/coordinator/src/main/java/org/apache/felix/service/coordinator/CoordinationException.java
new file mode 100644
index 0000000..663ace4
--- /dev/null
+++ b/coordinator/src/main/java/org/apache/felix/service/coordinator/CoordinationException.java
@@ -0,0 +1,142 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.service.coordinator;
+
+/**
+ * Thrown when an implementation detects a potential deadlock situation that it
+ * cannot solve. The name of the current coordination is given as argument.
+ *
+ * @Provisional
+ */
+@Deprecated
+public class CoordinationException extends RuntimeException
+{
+
+    private static final long serialVersionUID = -4466063711012717361L;
+
+    /**
+     * Unknown reason fot this exception.
+     */
+    public static final int UNKNOWN = 0;
+
+    /**
+     * Adding a participant caused a deadlock.
+     */
+    public static final int DEADLOCK_DETECTED = 1;
+
+    /**
+     * The Coordination was failed with {@link Coordination#fail(Throwable)}.
+     * When this exception type is used, the {@link Coordination#getFailure()}
+     * method must return a non-null value.
+     */
+    public static final int FAILED = 3;
+
+    /**
+     * The Coordination was partially ended.
+     */
+    public static final int PARTIALLY_ENDED = 4;
+
+    /**
+     * The Coordination was already ended.
+     */
+    public static final int ALREADY_ENDED = 5;
+
+    /**
+     * A Coordination was pushed on the stack that was already pushed.
+     */
+    public static final int ALREADY_PUSHED = 6;
+
+    /**
+     * Interrupted while trying to lock the participant.
+     */
+    public static final int LOCK_INTERRUPTED = 7;
+
+    /**
+     * The Coordination timed out.
+     */
+    public static final int TIMEOUT = 9;
+
+    private final Coordination coordination;
+
+    private final int type;
+
+    /**
+     * Create a new Coordination Exception.
+     *
+     * @param message The message
+     * @param coordination The coordination that failed
+     * @param type The reason for the exception
+     * @param exception The exception
+     */
+    public CoordinationException(String message, Coordination coordination, int type, Throwable exception)
+    {
+        super(message, exception);
+        this.coordination = coordination;
+        this.type = type;
+    }
+
+    /**
+     * Create a new Coordination Exception.
+     *
+     * @param message The message
+     * @param coordination The coordination that failed
+     * @param type The reason for the exception
+     */
+    public CoordinationException(String message, Coordination coordination, int type)
+    {
+        super(message);
+        this.coordination = coordination;
+        this.type = type;
+    }
+
+    /**
+     * Answer the name of the Coordination associated with this exception.
+     *
+     * @return the Coordination name
+     */
+    public String getName()
+    {
+        return coordination.getName();
+    }
+
+    /**
+     * Answer the reason.
+     *
+     * @return the reason
+     */
+    public int getType()
+    {
+        return type;
+    }
+
+    /**
+     * Must be set if to the exception type is {@link #FAILED}
+     *
+     * @return If exception is {@link #FAILED} a Throwable
+     */
+    public Throwable getFailure()
+    {
+        return getCause();
+    }
+
+    /**
+     * @return Answer the id
+     */
+    public long getId()
+    {
+        return coordination.getId();
+    }
+}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordination/CoordinationPermission.java b/coordinator/src/main/java/org/apache/felix/service/coordinator/CoordinationPermission.java
similarity index 88%
rename from coordinator/src/main/java/org/apache/felix/service/coordination/CoordinationPermission.java
rename to coordinator/src/main/java/org/apache/felix/service/coordinator/CoordinationPermission.java
index f0cedb7..a65966d 100644
--- a/coordinator/src/main/java/org/apache/felix/service/coordination/CoordinationPermission.java
+++ b/coordinator/src/main/java/org/apache/felix/service/coordinator/CoordinationPermission.java
@@ -1,19 +1,19 @@
 /*
  * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  * See the License for the specific language governing permissions and
  * limitations under the License.
  */
-package org.apache.felix.service.coordination;
+package org.apache.felix.service.coordinator;
 
 import java.security.BasicPermission;
 
@@ -82,7 +82,7 @@
  * </table>
  * </li>
  * </ol>
- * 
+ *
  * @Provisional
  */
 @Deprecated
@@ -110,12 +110,12 @@
     /**
      * The name parameter specifies a filter condition. The filter asserts the
      * bundle that initiated the Coordination. An implicit grant is made for a
-     * bundle's own coordinations. Parameters:
-     * 
+     * bundle's own coordinations.
+     *
      * @param filterExpression A filter expression asserting the bundle
      *            associated with the coordination.
-     * @param actions A comma separated combination of INITIATE, ADMIN,
-     *            PARTICIPATE.
+     * @param actions A comma separated combination of {@link #INITIATE},
+     *            {@link #ADMIN}, {@link #PARTICIPATE}.
      */
     public CoordinationPermission(String filterExpression, String actions)
     {
@@ -124,12 +124,12 @@
 
     /**
      * The verification permission
-     * 
+     *
      * @param bundle The bundle that will be the target of the filter
      *            expression.
-     * @param coordinationName The name of the coordination or null
+     * @param coordinationName The name of the coordination or <code>null</code>
      * @param actions The set of actions required, which is a combination of
-     *            INITIATE, ADMIN, PARTICIPATE.
+     *            {@link #INITIATE}, {@link #ADMIN}, {@link #PARTICIPATE}.
      */
     public CoordinationPermission(org.osgi.framework.Bundle bundle, String coordinationName, String actions)
     {
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordinator/Coordinator.java b/coordinator/src/main/java/org/apache/felix/service/coordinator/Coordinator.java
new file mode 100644
index 0000000..d91b2dd
--- /dev/null
+++ b/coordinator/src/main/java/org/apache/felix/service/coordinator/Coordinator.java
@@ -0,0 +1,198 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.service.coordinator;
+
+import java.util.Collection;
+
+/**
+A Coordinator service coordinates activities between different parties. The Coordinator can create Coordination
+objects. Once a Coordination object is created, it can be pushed on a thread local stack {@link Coordination#push()} as
+an implicit parameter for calls to other parties, or it can be passed as an argument. The current top of the thread
+local stack can be obtained with #peek(). The addParticipant(Participant) method on this service or the
+Coordination.addParticipant(Participant) method can be used to participate in a Coordination. Participants
+participate only in a single Coordination, if a Participant object is added to a second Coordination the
+Coordination.addParticipant(Participant) method is blocked until the first Coordination is terminated. A
+Coordination ends correctly when the Coordination.end() method is called before termination or when the
+Coordination fails due to a timeout or a failure. If the Coordination ends correctly, all its participants are called on
+the Participant.ended(Coordination) method, in all other cases the Participant.failed(Coordination) is
+called. The typical usage of the Coordinator service is as follows:
+<pre>
+Coordination coordination = coordinator.begin("mycoordination",0);
+try {
+doWork();
+}
+finally {
+coordination.end();
+}
+</pre>
+In the doWork() method, code can be called that requires a callback at the end of the Coordination. The doWork
+method can then add a Participant to the coordination. This code is for a Participant.
+<pre>
+void doWork() {
+if (coordinator.addParticipant(this)) {
+beginWork();
+}
+else {
+beginWork();
+finishWork();
+}
+}
+void ended() {
+finishWork();
+}
+void failed() {
+undoWork();
+}
+</pre>
+Life cycle. All Coordinations that are begun through this service must automatically fail before this service is
+ungotten.
+ *
+ * @ThreadSafe
+ * @Provisional
+ */
+@Deprecated
+public interface Coordinator
+{
+
+    /**
+     * Create a new Coordination that is not associated with the current thread.
+     * Parameters:
+     *
+     * @param name The name of this coordination, a name does not have to be
+     *            unique.
+     * @param timeout Timeout in milliseconds, less or equal than 0 means no
+     *            timeout
+     * @return The new Coordination object, never <code>null</code>
+     * @throws SecurityException This method requires the
+     *             {@link CoordinationPermission#INITIATE} action, no bundle
+     *             check is done.
+     * @throws IllegalArgumentException when the name does not match the Bundle
+     *             Symbolic Name pattern
+     */
+    Coordination create(String name, int timeout);
+
+    /**
+     * Provide a mutable snapshot collection of all Coordination objects
+     * currently not terminated. Coordinations in
+     * this list can have terminated before this list is returned or any time
+     * thereafter. The returned collection must
+     * only contain the Coordinations for which the caller has
+     * {@link CoordinationPermission#ADMIN}, without this
+     * permission an empty list must be returned.
+     *
+     * @return a list of Coordination objects filtered by
+     *         {@link CoordinationPermission#ADMIN}
+     */
+    Collection<Coordination> getCoordinations();
+
+    /**
+     * Always fail the current Coordination, if it exists. If this is no current
+     * Coordination return <code>false</code>. Otherwise return the result of
+     * {@link Coordination#fail(Throwable)}, which is <code>true</code> in the
+     * case this call terminates the Coordination and <code>false</code>
+     * otherwise.
+     *
+     * <pre>
+     * false - No current Coordination
+     * false - Current Coordination was already terminated
+     * true - Current Coordination got terminated due to this call
+     * </pre>
+     *
+     * @param reason The reason for failure, must not be <code>null</code>.
+     * @return <code>true</code> if there was a current Coordination and it was
+     *         terminated, otherwise <code>false</code>.
+     */
+    boolean fail(Throwable reason);
+
+    /**
+     * Return the current Coordination or <code>null</code>. The current
+     * Coordination is the top of the thread local stack of Coordinations. If
+     * the stack is empty, there is no current Coordination.
+     *
+     * @return <code>null</code> when the thread local stack is empty, otherwise
+     *         the top of the thread local stack of
+     *         Coordinations.
+     */
+    Coordination peek();
+
+    /**
+     * Begin a new Coordination and push it on the thread local stack with
+     * {@link Coordination#push()}.
+     *
+     * @param name The name of this coordination, a name does not have to be
+     *            unique.
+     * @param timeoutInMillis Timeout in milliseconds, less or equal than 0
+     *            means no timeout
+     * @return A new Coordination object
+     * @throws SecurityException This method requires the
+     *             {@link CoordinationPermission#INITIATE} action, no bundle
+     *             check is done.
+     * @throws IllegalArgumentException when the name does not match the Bundle
+     *             Symbolic Name pattern
+     */
+    Coordination begin(String name, int timeoutInMillis);
+
+    /**
+     * Pop the top of the thread local stack of Coordinations. If no current
+     * Coordination is present, return <code>null</code>.
+     *
+     * @return The top of the stack or <code>null</code>
+     */
+    Coordination pop();
+
+    /**
+     * Participate in the current Coordination and return <code>true</code> or
+     * return <code>false</code> if there is none. This method calls
+     * {@link #peek()}, if it is <code>null</code>, it will return
+     * <code>false</code>. Otherwise it will call
+     * {@link Coordination#addParticipant(Participant)}.
+     *
+     * @param participant The participant of the Coordination
+     * @return <code>true</code> if there was a current Coordination that could
+     *         be successfully used to participate, otherwise <code>false</code>
+     *         .
+     * @throws CoordinationException This exception should normally not be
+     *             caught by the caller but allowed to bubble up to the
+     *             initiator of the coordination, it is therefore a
+     *             <code>RuntimeException</code>. It signals that this
+     *             participant could not participate the current coordination.
+     *             This can be cause by the following reasons:
+     *             <ol>
+     *             <li>{@link CoordinationException#DEADLOCK_DETECTED}</li>
+     *             <li>{@link CoordinationException#ALREADY_ENDED}</li>
+     *             <li>{@link CoordinationException#TIMEOUT}</li>
+     *             <li>{@link CoordinationException#UNKNOWN}</li>
+     *             </ol>
+     * @throws SecurityException This method requires the
+     *             {@link CoordinationPermission#PARTICIPATE} action for the
+     *             current
+     *             Coordination, if any.
+     */
+    boolean addParticipant(Participant participant) throws CoordinationException;
+
+    /**
+     * Answer the coordination associated with the given id if it exists.
+     *
+     * @param id The id of the requested Coordination
+     * @return a Coordination with the given ID or <code>null</code> when
+     *         Coordination cannot be found because it never existed or had
+     *         terminated before this call.
+     * @throws SecurityException if the caller has no
+     *             {@link CoordinationPermission#ADMIN} for the requested
+     *             Coordination.
+     */
+    Coordination getCoordination(long id);
+}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordinator/Participant.java b/coordinator/src/main/java/org/apache/felix/service/coordinator/Participant.java
new file mode 100644
index 0000000..f83138c
--- /dev/null
+++ b/coordinator/src/main/java/org/apache/felix/service/coordinator/Participant.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.felix.service.coordinator;
+
+/**
+ * A Participant participates in a Coordination. A Participant can participate
+ * in a Coordination by calling {@link Coordinator#addParticipant(Participant)}.
+ * After successfully initiating the participation, the Participant is called
+ * back when the Coordination is terminated. If a Coordination ends with the
+ * {@link Coordination#end()} method, then all the participants are called back
+ * on their {@link #ended(Coordination)} method. If the Coordination is failed
+ * (someone has called {@link Coordination#fail(Throwable)} then the
+ * {@link #failed(Coordination)} method is called back. Participants are
+ * required to be thread safe for the {@link #ended(Coordination)} method and
+ * the {@link #failed(Coordination)} method. Both methods can be called on
+ * another thread.
+ *
+ * @ThreadSafe
+ * @Provisional
+ */
+@Deprecated
+public interface Participant
+{
+
+    /**
+     * The Coordination has failed and the participant is informed. A
+     * participant should properly discard any work it has done during the
+     * active coordination.
+     *
+     * @param c The Coordination that does the callback
+     * @throws Exception Any exception thrown should be logged but is further
+     *             ignored and does not influence the outcome of the
+     *             Coordination.
+     */
+    void failed(Coordination c) throws Exception;
+
+    /**
+     * The Coordination is being ended.
+     *
+     * @param c The Coordination that does the callback
+     * @throws Exception If an exception is thrown it should be logged and the
+     *             return of the {@link Coordination#end()} method must throw
+     *             {@link CoordinationException#PARTIALLY_ENDED}.
+     */
+    void ended(Coordination c) throws Exception;
+}
diff --git a/coordinator/src/main/java/org/apache/felix/service/coordination/package-info.java b/coordinator/src/main/java/org/apache/felix/service/coordinator/package-info.java
similarity index 77%
rename from coordinator/src/main/java/org/apache/felix/service/coordination/package-info.java
rename to coordinator/src/main/java/org/apache/felix/service/coordinator/package-info.java
index fe64004..a7c33ec 100644
--- a/coordinator/src/main/java/org/apache/felix/service/coordination/package-info.java
+++ b/coordinator/src/main/java/org/apache/felix/service/coordinator/package-info.java
@@ -1,12 +1,12 @@
 /*
  * Copyright (c) OSGi Alliance (2004, 2010). All Rights Reserved.
- * 
+ *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
- * 
+ *
  * http://www.apache.org/licenses/LICENSE-2.0
- * 
+ *
  * Unless required by applicable law or agreed to in writing, software
  * distributed under the License is distributed on an "AS IS" BASIS,
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 /**
- * Coordination Package Version 1.0.
+ * Coordinator Package Version 1.0.
  * <p>
  * Bundles wishing to use this package must list the package in the
  * Import-Package header of the bundle's manifest.
@@ -23,15 +23,15 @@
  * package and the providers that implement the API in this package.
  * <p>
  * Example import for consumers using the API in this package: <blockquote>
- * <code>Import-Package: org.apache.felix.service.coordination; version="[1.0,2.0)"; status="provisional"</code>
+ * <code>Import-Package: org.apache.felix.service.coordinator; version="[1.0,2.0)"; status="provisional"</code>
  * </blockquote>
  * <p>
  * Example import for providers implementing the API in this package:
  * <blockquote>
- * <code>Import-Package: org.apache.felix.service.coordination; version="[1.0,1.1)"; status="provisional"</code>
+ * <code>Import-Package: org.apache.felix.service.coordinator; version="[1.0,1.1)"; status="provisional"</code>
  * </blockquote>
- * 
+ *
  * @Provisional
  */
 @Deprecated
-package org.apache.felix.service.coordination;
\ No newline at end of file
+package org.apache.felix.service.coordinator;
\ No newline at end of file
diff --git a/coordinator/src/test/java/org/apache/felix/coordination/impl/CoordinatorImplTest.java b/coordinator/src/test/java/org/apache/felix/coordination/impl/CoordinatorImplTest.java
index a605fbe..f6dfe88 100644
--- a/coordinator/src/test/java/org/apache/felix/coordination/impl/CoordinatorImplTest.java
+++ b/coordinator/src/test/java/org/apache/felix/coordination/impl/CoordinatorImplTest.java
@@ -18,9 +18,9 @@
  */
 package org.apache.felix.coordination.impl;
 
-import org.apache.felix.service.coordination.Coordination;
-import org.apache.felix.service.coordination.CoordinationException;
-import org.apache.felix.service.coordination.Participant;
+import org.apache.felix.service.coordinator.Coordination;
+import org.apache.felix.service.coordinator.CoordinationException;
+import org.apache.felix.service.coordinator.Participant;
 
 import junit.framework.TestCase;
 
@@ -43,129 +43,132 @@
     public void test_createCoordination()
     {
         final String name = "test";
-        final Coordination c1 = coordinator.create(name);
+        final Coordination c1 = coordinator.create(name, 0);
         assertNotNull(c1);
         assertEquals(name, c1.getName());
-        assertNull(coordinator.getCurrentCoordination());
-        assertFalse(c1.isFailed());
+        assertNull(coordinator.peek());
+        assertNull(c1.getFailure());
         assertFalse(c1.isTerminated());
         assertTrue(c1.getParticipants().isEmpty());
 
-        assertTrue(c1.fail(new Exception()));
-        assertTrue(c1.isFailed());
+        Exception cause = new Exception();
+        assertTrue(c1.fail(cause));
+        assertSame(cause, c1.getFailure());
         assertTrue(c1.isTerminated());
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
 
         assertFalse(c1.fail(new Exception()));
         try
         {
             c1.end();
-            fail("Expected IllegalStateException on end() after fail()");
+            fail("Expected CoordinationException.ALREADY_ENDED on end() after fail()");
         }
-        catch (IllegalStateException ise)
+        catch (CoordinationException ce)
         {
-            // expected
+            // expected already terminated
+            assertEquals(CoordinationException.ALREADY_ENDED, ce.getType());
         }
 
-        final Coordination c2 = coordinator.create(name);
+        final Coordination c2 = coordinator.create(name, 0);
         assertNotNull(c2);
         assertEquals(name, c2.getName());
-        assertNull(coordinator.getCurrentCoordination());
-        assertFalse(c2.isFailed());
+        assertNull(coordinator.peek());
+        assertNull(c2.getFailure());
         assertFalse(c2.isTerminated());
         assertTrue(c2.getParticipants().isEmpty());
 
-        assertEquals(Coordination.OK, c2.end());
-        assertFalse(c2.isFailed());
+        c2.end();
+        assertNull(c2.getFailure());
         assertTrue(c2.isTerminated());
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
 
         assertFalse(c2.fail(new Exception()));
         try
         {
             c2.end();
-            fail("Expected IllegalStateException on second end()");
+            fail("Expected CoordinationException.ALREADY_ENDED on second end()");
         }
-        catch (IllegalStateException ise)
+        catch (CoordinationException ce)
         {
-            // expected
+            // expected already terminated
+            assertEquals(CoordinationException.ALREADY_ENDED, ce.getType());
         }
     }
 
     public void test_beginCoordination()
     {
         final String name = "test";
-        final Coordination c1 = coordinator.begin(name);
+        final Coordination c1 = coordinator.begin(name, 0);
         assertNotNull(c1);
         assertEquals(name, c1.getName());
 
-        assertEquals(c1, coordinator.getCurrentCoordination());
+        assertEquals(c1, coordinator.peek());
         assertEquals(c1, coordinator.pop());
 
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
         coordinator.push(c1);
-        assertEquals(c1, coordinator.getCurrentCoordination());
+        assertEquals(c1, coordinator.peek());
 
         c1.end();
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
 
-        final Coordination c2 = coordinator.begin(name);
+        final Coordination c2 = coordinator.begin(name, 0);
         assertNotNull(c2);
         assertEquals(name, c2.getName());
-        assertEquals(c2, coordinator.getCurrentCoordination());
+        assertEquals(c2, coordinator.peek());
         c2.fail(null);
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
     }
 
     public void test_beginCoordination_stack()
     {
         final String name = "test";
 
-        final Coordination c1 = coordinator.begin(name);
+        final Coordination c1 = coordinator.begin(name, 0);
         assertNotNull(c1);
         assertEquals(name, c1.getName());
-        assertEquals(c1, coordinator.getCurrentCoordination());
+        assertEquals(c1, coordinator.peek());
 
-        final Coordination c2 = coordinator.begin(name);
+        final Coordination c2 = coordinator.begin(name, 0);
         assertNotNull(c2);
         assertEquals(name, c2.getName());
-        assertEquals(c2, coordinator.getCurrentCoordination());
+        assertEquals(c2, coordinator.peek());
 
         c2.end();
-        assertEquals(c1, coordinator.getCurrentCoordination());
+        assertEquals(c1, coordinator.peek());
 
         c1.end();
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
     }
 
     public void test_beginCoordination_stack2()
     {
         final String name = "test";
 
-        final Coordination c1 = coordinator.begin(name);
+        final Coordination c1 = coordinator.begin(name, 0);
         assertNotNull(c1);
         assertEquals(name, c1.getName());
-        assertEquals(c1, coordinator.getCurrentCoordination());
+        assertEquals(c1, coordinator.peek());
 
-        final Coordination c2 = coordinator.begin(name);
+        final Coordination c2 = coordinator.begin(name, 0);
         assertNotNull(c2);
         assertEquals(name, c2.getName());
-        assertEquals(c2, coordinator.getCurrentCoordination());
+        assertEquals(c2, coordinator.peek());
 
         c1.end();
-        assertEquals(c2, coordinator.getCurrentCoordination());
+        assertEquals(c2, coordinator.peek());
 
         c2.end();
-        assertNull(coordinator.getCurrentCoordination());
+        assertNull(coordinator.peek());
     }
 
-    public void test_participate_with_ended()
+    public void test_addParticipant_with_ended()
     {
         final String name = "test";
-        final Coordination c1 = coordinator.create(name);
+        final Coordination c1 = coordinator.create(name, 0);
 
         final MockParticipant p1 = new MockParticipant();
-        c1.participate(p1);
+        c1.addParticipant(p1);
         assertTrue(c1.getParticipants().contains(p1));
         assertEquals(1, c1.getParticipants().size());
 
@@ -175,11 +178,11 @@
         assertEquals(c1, p1.c);
 
         // assert order of call
-        final Coordination c2 = coordinator.create(name);
+        final Coordination c2 = coordinator.create(name, 0);
         final MockParticipant p21 = new MockParticipant();
         final MockParticipant p22 = new MockParticipant();
-        c2.participate(p21);
-        c2.participate(p22);
+        c2.addParticipant(p21);
+        c2.addParticipant(p22);
         assertTrue(c2.getParticipants().contains(p21));
         assertTrue(c2.getParticipants().contains(p22));
         assertEquals(2, c2.getParticipants().size());
@@ -192,12 +195,12 @@
         assertTrue("p21 must be called before p22", p21.time < p22.time);
 
         // assert order of call with two registrations
-        final Coordination c3 = coordinator.create(name);
+        final Coordination c3 = coordinator.create(name, 0);
         final MockParticipant p31 = new MockParticipant();
         final MockParticipant p32 = new MockParticipant();
-        c3.participate(p31);
-        c3.participate(p32);
-        c3.participate(p31); // should be "ignored"
+        c3.addParticipant(p31);
+        c3.addParticipant(p32);
+        c3.addParticipant(p31); // should be "ignored"
         assertTrue(c3.getParticipants().contains(p31));
         assertTrue(c3.getParticipants().contains(p32));
         assertEquals(2, c3.getParticipants().size());
@@ -210,13 +213,13 @@
         assertTrue("p21 must be called before p22", p31.time < p32.time);
     }
 
-    public void test_participate_with_failed()
+    public void test_addParticipant_with_failed()
     {
         final String name = "test";
-        final Coordination c1 = coordinator.create(name);
+        final Coordination c1 = coordinator.create(name, 0);
 
         final MockParticipant p1 = new MockParticipant();
-        c1.participate(p1);
+        c1.addParticipant(p1);
         assertTrue(c1.getParticipants().contains(p1));
         assertEquals(1, c1.getParticipants().size());
 
@@ -226,11 +229,11 @@
         assertEquals(c1, p1.c);
 
         // assert order of call
-        final Coordination c2 = coordinator.create(name);
+        final Coordination c2 = coordinator.create(name, 0);
         final MockParticipant p21 = new MockParticipant();
         final MockParticipant p22 = new MockParticipant();
-        c2.participate(p21);
-        c2.participate(p22);
+        c2.addParticipant(p21);
+        c2.addParticipant(p22);
         assertTrue(c2.getParticipants().contains(p21));
         assertTrue(c2.getParticipants().contains(p22));
         assertEquals(2, c2.getParticipants().size());
@@ -243,12 +246,12 @@
         assertTrue("p21 must be called before p22", p21.time < p22.time);
 
         // assert order of call with two registrations
-        final Coordination c3 = coordinator.create(name);
+        final Coordination c3 = coordinator.create(name, 0);
         final MockParticipant p31 = new MockParticipant();
         final MockParticipant p32 = new MockParticipant();
-        c3.participate(p31);
-        c3.participate(p32);
-        c3.participate(p31); // should be "ignored"
+        c3.addParticipant(p31);
+        c3.addParticipant(p32);
+        c3.addParticipant(p31); // should be "ignored"
         assertTrue(c3.getParticipants().contains(p31));
         assertTrue(c3.getParticipants().contains(p32));
         assertEquals(2, c3.getParticipants().size());
@@ -264,26 +267,25 @@
     public void test_Coordination_timeout() throws InterruptedException
     {
         final String name = "test";
-        final Coordination c1 = coordinator.create(name);
+        final Coordination c1 = coordinator.create(name, 200);
         final MockParticipant p1 = new MockParticipant();
-        c1.participate(p1);
+        c1.addParticipant(p1);
         assertTrue(c1.getParticipants().contains(p1));
         assertEquals(1, c1.getParticipants().size());
 
-        // set a short timeout and wait for it to pass
-        c1.addTimeout(100);
-        Thread.sleep(150);
+        // wait for the coordination to time out
+        Thread.sleep(250);
 
         // expect coordination to have terminated
         assertTrue(c1.isTerminated());
-        assertTrue(c1.isFailed());
+        assertSame(Coordination.TIMEOUT, c1.getFailure());
 
         // expect Participant.failed() being called
         assertTrue(p1.failed);
         assertEquals(c1, p1.c);
     }
 
-    public void test_Coordination_participate_timeout() throws InterruptedException
+    public void test_Coordination_addParticipant_timeout() throws InterruptedException
     {
         final String name1 = "test1";
         final String name2 = "test2";
@@ -292,31 +294,31 @@
         // ensure short timeout for participation
         mgr.configure(60000, 200);
 
-        final Coordination c1 = coordinator.create(name1);
-        c1.participate(p1);
+        final Coordination c1 = coordinator.create(name1, 0);
+        c1.addParticipant(p1);
         assertTrue(c1.getParticipants().contains(p1));
         assertEquals(1, c1.getParticipants().size());
 
         // preset p1PartFailure to be be sure the participation actually starts
-        p1.participateFailure(new Exception("Not Started yet"));
+        p1.addParticipantFailure(new Exception("Not Started yet"));
 
         Thread c2Thread = new Thread()
         {
             public void run()
             {
-                final Coordination c2 = coordinator.create(name2);
+                final Coordination c2 = coordinator.create(name2, 0);
                 try
                 {
-                    p1.participateFailure(null);
-                    c2.participate(p1);
+                    p1.addParticipantFailure(null);
+                    c2.addParticipant(p1);
                 }
                 catch (Throwable t)
                 {
-                    p1.participateFailure(t);
+                    p1.addParticipantFailure(t);
                 }
                 finally
                 {
-                    c2.terminate();
+                    c2.end();
                 }
             }
         };
@@ -327,21 +329,21 @@
         c2Thread.join(2000);
         assertFalse("Thread for second Coordination did not terminate....", c2Thread.isAlive());
 
-        Throwable p1PartFailure = p1.participateFailure;
+        Throwable p1PartFailure = p1.addParticipantFailure;
         if (p1PartFailure == null)
         {
-            fail("Expecting CoordinationException/TIMEOUT for second participation");
+            fail("Expecting CoordinationException/UNKNOWN for second participation");
         }
         else if (p1PartFailure instanceof CoordinationException)
         {
-            assertEquals(CoordinationException.TIMEOUT, ((CoordinationException) p1PartFailure).getReason());
+            assertEquals(CoordinationException.UNKNOWN, ((CoordinationException) p1PartFailure).getType());
         }
         else
         {
-            fail("Unexpected Throwable while trying to participate: " + p1PartFailure);
+            fail("Unexpected Throwable while trying to addParticipant: " + p1PartFailure);
         }
 
-        c1.terminate();
+        c1.end();
 
         // make sure c2Thread has terminated
         if (c2Thread.isAlive())
@@ -363,7 +365,7 @@
 
         boolean ended;
 
-        Throwable participateFailure;
+        Throwable addParticipantFailure;
 
         public void failed(Coordination c) throws Exception
         {
@@ -379,9 +381,9 @@
             this.time = System.nanoTime();
         }
 
-        void participateFailure(Throwable t)
+        void addParticipantFailure(Throwable t)
         {
-            this.participateFailure = t;
+            this.addParticipantFailure = t;
         }
     }
 }