Work around bug 333513.  Fix to remove CR chars.
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java
index fc890d6..eceb8dc 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Activator.java
@@ -1,47 +1,47 @@
-/*******************************************************************************

- * Copyright (c) 2010 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.util.Dictionary;

-import java.util.Hashtable;

-

-import org.osgi.framework.BundleActivator;

-import org.osgi.framework.BundleContext;

-import org.osgi.framework.ServiceRegistration;

-import org.osgi.service.coordinator.Coordinator;

-

-public class Activator implements BundleActivator {

-	// Static so the factory can be used by both DS and standard OSGi.

-	static volatile CoordinatorServiceFactory factory;

-

-	private ServiceRegistration<Coordinator> registration;

-

-	public void start(BundleContext bundleContext) throws Exception {

-		// Instantiate the factory to be used by both DS and standard OSGi. In the case of DS, the

-		// start method is guaranteed to be called before any components are created.

-		factory = new CoordinatorServiceFactory(bundleContext);

-		if (Boolean.valueOf(bundleContext.getProperty("equinox.use.ds")).booleanValue()) //$NON-NLS-1$

-			return; // If this property is set we assume DS is being used.

-		Dictionary<String, Object> properties = new Hashtable<String, Object>();

-		// TODO Add desired properties (bundle vendor, etc.).

-		@SuppressWarnings({"unchecked"})

-		// Use local variable to avoid suppressing unchecked warnings at method level.

-		ServiceRegistration<Coordinator> reg = (ServiceRegistration<Coordinator>) bundleContext.registerService(Coordinator.class.getName(), factory, properties);

-		this.registration = reg;

-	}

-

-	public void stop(BundleContext bundleContext) throws Exception {

-		// Will be null when using DS.

-		if (registration != null)

-			registration.unregister();

-		factory.shutdown();

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.util.Dictionary;
+import java.util.Hashtable;
+
+import org.osgi.framework.BundleActivator;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.coordinator.Coordinator;
+
+public class Activator implements BundleActivator {
+	// Static so the factory can be used by both DS and standard OSGi.
+	static volatile CoordinatorServiceFactory factory;
+
+	private ServiceRegistration<Coordinator> registration;
+
+	public void start(BundleContext bundleContext) throws Exception {
+		// Instantiate the factory to be used by both DS and standard OSGi. In the case of DS, the
+		// start method is guaranteed to be called before any components are created.
+		factory = new CoordinatorServiceFactory(bundleContext);
+		if (Boolean.valueOf(bundleContext.getProperty("equinox.use.ds")).booleanValue()) //$NON-NLS-1$
+			return; // If this property is set we assume DS is being used.
+		Dictionary<String, Object> properties = new Hashtable<String, Object>();
+		// TODO Add desired properties (bundle vendor, etc.).
+		@SuppressWarnings({"unchecked"})
+		// Use local variable to avoid suppressing unchecked warnings at method level.
+		ServiceRegistration<Coordinator> reg = (ServiceRegistration<Coordinator>) bundleContext.registerService(Coordinator.class.getName(), factory, properties);
+		this.registration = reg;
+	}
+
+	public void stop(BundleContext bundleContext) throws Exception {
+		// Will be null when using DS.
+		if (registration != null)
+			registration.unregister();
+		factory.shutdown();
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java
index 4abdca7..bfc2839 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationImpl.java
@@ -1,387 +1,387 @@
-/*******************************************************************************

- * Copyright (c) 2010, 2011 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.lang.ref.Reference;

-import java.util.ArrayList;

-import java.util.Collections;

-import java.util.Date;

-import java.util.HashMap;

-import java.util.List;

-import java.util.Map;

-import java.util.TimerTask;

-

-import org.osgi.framework.Bundle;

-import org.osgi.service.coordinator.Coordination;

-import org.osgi.service.coordinator.CoordinationException;

-import org.osgi.service.coordinator.CoordinationPermission;

-import org.osgi.service.coordinator.Participant;

-import org.osgi.service.log.LogService;

-

-public class CoordinationImpl implements Coordination {

-	private volatile Throwable failure;

-	private volatile boolean terminated;

-	

-	private Date deadline;

-	private Reference<CoordinationImpl> enclosingCoordination;

-	private Thread thread;

-	private TimerTask timerTask;

-	

-	private final CoordinatorImpl coordinator;

-	private final long id;

-	private final String name;

-	private final List<Participant> participants;

-	private final Map<Class<?>, Object> variables;

-

-	public CoordinationImpl(long id, String name, long timeout, CoordinatorImpl coordinator) {

-		validateName(name);

-		validateTimeout(timeout);

-		this.id = id;

-		this.name = name;

-		this.deadline = new Date(System.currentTimeMillis() + timeout);

-		this.coordinator = coordinator;

-		participants = Collections.synchronizedList(new ArrayList<Participant>());

-		variables = new HashMap<Class<?>, Object>();

-	}

-

-	public void addParticipant(Participant participant) throws CoordinationException {

-		// This method requires the PARTICIPATE permission.

-		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);

-		if (participant == null)

-			throw new NullPointerException(Messages.CoordinationImpl_15);

-		/* The caller has permission. Check to see if the participant is already 

-		 * participating in another coordination. Do this in a loop in case the 

-		 * participant must wait for the other coordination to finish. The loop 

-		 * will exit under the following circumstances.

-		 * 

-		 * (1) This coordination is terminated.

-		 * (2) The participant is already participating in another coordination

-		 * using the same thread as this one.

-		 * (3) This thread is interrupted.

-		 * (4) The participant is not participating in another coordination.

-		 */

-		while (true) {

-			CoordinationImpl coordination;

-			synchronized (this) {

-				// Check to see if this coordination has already terminated. If so, 

-				// throw the appropriate exception.

-				checkTerminated();

-				coordination = coordinator.addParticipant(participant, this);

-				if (coordination == null) {

-					// The same participant is not currently participating in 

-					// any coordination. Add it to this coordination and break 

-					// out of the loop.

-					participants.add(participant);

-					break;

-				} else if (coordination == this) {

-					// The same participant is being added twice to this 

-					// coordination. Nothing to do.

-					break;

-				} else {

-					// This means the participant is already participating in another

-					// coordination. Check to see if it's on the same thread.

-					Thread t = coordination.getThread();

-					// If thread is null, the coordination is not associated with

-					// any thread, and there's nothing to compare. If the coordination 

-					// is using this thread, then we can't block due to risk of deadlock.

-					if (t == Thread.currentThread()) {

-						throw new CoordinationException(Messages.CoordinationImpl_1, CoordinationImpl.this, CoordinationException.DEADLOCK_DETECTED);

-					}

-				}

-			}

-			// The participant is already participating in another coordination 

-			// that's not using this thread. Block until that coordination has

-			// finished. A decision was made here to use a timeout and incur the

-			// expense of waking up and rejoining in order to make a reasonably 

-			// timely exit if this coordination terminates.

-			try {

-				coordination.join(1000);

-			} catch (InterruptedException e) {

-				coordinator.getLogService().log(LogService.LOG_DEBUG, Messages.CoordinationImpl_2, e);

-				// This thread was interrupted while waiting for the coordination

-				// to terminate.

-				throw new CoordinationException(Messages.CoordinationImpl_3, CoordinationImpl.this, CoordinationException.LOCK_INTERRUPTED, e);

-			}

-		}

-	}

-

-	public void end() throws CoordinationException {

-		coordinator.checkPermission(CoordinationPermission.INITIATE, name);

-		// Terminating the coordination must be atomic.

-		synchronized (this) {

-			// If this coordination is associated with a thread, an additional

-			// check is required.

-			if (thread != null) {

-				// Coordinations may only be ended by the same thread that

-				// pushed them onto the stack, if any.

-				if (thread != Thread.currentThread()) {

-					throw new CoordinationException(Messages.CoordinationImpl_14, this, CoordinationException.WRONG_THREAD);

-				}

-				// Unwind the stack in case there are other coordinations higher

-				// up than this one.

-				while (coordinator.peek() != this) {

-					try {

-						coordinator.peek().end();

-					} catch (CoordinationException e) {

-						coordinator.peek().fail(e);

-					}

-				}

-				// A coordination is removed from the thread local stack only when being ended.

-				// This must occur even if the coordination is already terminated due to a

-				// failure.

-				coordinator.pop();

-			}

-			terminate();

-		}

-		// Notify participants this coordination has ended. Track whether or

-		// not a partial ending has occurred.

-		Exception exception = null;

-		// No additional synchronization is needed here because the participant

-		// list will not be modified post termination.

-		for (Participant participant : participants) {

-			try {

-				participant.ended(this);

-			} catch (Exception e) {

-				coordinator.getLogService().log(LogService.LOG_WARNING, Messages.CoordinationImpl_4, e);

-				// Only the first exception will be propagated.

-				if (exception == null)

-					exception = e;

-			}

-		}

-		synchronized (this) {

-			// Notify everything joined to this coordination that it has finished.

-			notifyAll();

-		}

-		// If a partial ending has occurred, throw the required exception.

-		if (exception != null) {

-			throw new CoordinationException(Messages.CoordinationImpl_5, this, CoordinationException.PARTIALLY_ENDED, exception);

-		}

-	}

-

-	public long extendTimeout(long timeInMillis) throws CoordinationException {

-		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);

-		validateTimeout(timeInMillis);

-		// We don't want this coordination to terminate before the new timer is 

-		// in place.

-		synchronized (this) {

-			// Check to see if this coordination has already terminated. If so, 

-			// throw the appropriate exception.

-			checkTerminated();

-			// If there was no previous timeout set, return 0 indicating that no

-			// extension has taken place.

-			if (timerTask == null)

-				return 0;

-			// Passing anything less than zero as well as zero itself will return the

-			// existing deadline. The deadline will not be null if timerTask is not null.

-			if (timeInMillis == 0)

-				return deadline.getTime();

-			// Cancel the current timeout.

-			boolean cancelled = timerTask.cancel();

-			if (!cancelled) {

-				// This means the previous task has run and is waiting to get a lock on

-				// this coordination. We can't throw an exception yet because we can't

-				// know which one to use (ALREADY_ENDED or FAILED). Once the lock is

-				// released, the running task may fail this coordination due to a timeout, 

-				// or something else might be waiting to fail this coordination for other

-				// reasons or to end it. We simply don't know who will win the race.

-				try {

-					// Wait until this coordination terminates.

-					join(0);

-					// Now determine how it terminated and throw the appropriate exception.

-					checkTerminated();

-				}

-				catch (InterruptedException e) {

-					throw new CoordinationException(Messages.CoordinationImpl_13, this, CoordinationException.UNKNOWN, e);

-				}

-			}

-			// Create the new timeout.

-			timerTask = new CoordinationTimerTask(this);

-			// Extend the current deadline.

-			deadline = new Date(deadline.getTime() + timeInMillis);

-			// Schedule the new timeout.

-			coordinator.schedule(timerTask, deadline);

-			// Return the new deadline.

-			return deadline.getTime();

-		}

-	}

-

-	public boolean fail(Throwable reason) {

-		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);

-		// The reason must not be null.

-		if (reason == null)

-			throw new NullPointerException(Messages.CoordinationImpl_11);

-		// Terminating the coordination must be atomic.

-		synchronized (this) {

-			// If this coordination is terminated, return false. Do not throw a

-			// CoordinationException as in other methods.

-			if (terminated)

-				return false;

-			// This coordination has not already terminated, so terminate now.

-			terminate();

-			// Store the reason for the failure.

-			failure = reason;

-		}

-		// Notify participants this coordination has failed.

-		// No additional synchronization is needed here because the participant

-		// list will not be modified post termination.

-		for (Participant participant : participants) {

-			try {

-				participant.failed(this);

-			} catch (Exception e) {

-				coordinator.getLogService().log(LogService.LOG_WARNING, Messages.CoordinationImpl_6, e);

-			}

-		}

-		synchronized (this) {

-			// Notify everything joined to this coordination that it has finished.

-			notifyAll();

-		}

-		// Return true to indicate this call resulted in the coordination's failure.

-		return true;

-	}

-	

-	public Bundle getBundle() {

-		coordinator.checkPermission(CoordinationPermission.ADMIN, name);

-		return coordinator.getBundle();

-	}

-	

-	public synchronized Coordination getEnclosingCoordination() {

-		coordinator.checkPermission(CoordinationPermission.ADMIN, name);

-		return enclosingCoordination == null ? null : enclosingCoordination.get();

-	}

-

-	public Throwable getFailure() {

-		coordinator.checkPermission(CoordinationPermission.INITIATE, name);

-		return failure;

-	}

-

-	public long getId() {

-		return id;

-	}

-

-	public String getName() {

-		return name;

-	}

-

-	public List<Participant> getParticipants() {

-		// This method requires the ADMIN permission.

-		coordinator.checkPermission(CoordinationPermission.INITIATE, name);

-		// Return a mutable snapshot.

-		synchronized (participants) {

-			return new ArrayList<Participant>(participants);

-		}

-	}

-

-	public synchronized Thread getThread() {

-		coordinator.checkPermission(CoordinationPermission.ADMIN, name);

-		return thread;

-	}

-

-	public Map<Class<?>, Object> getVariables() {

-		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);

-		return variables;

-	}

-

-	public boolean isTerminated() {

-		return terminated;

-	}

-

-	public void join(long timeInMillis) throws InterruptedException {

-		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);

-		long start = System.currentTimeMillis();

-		// Wait until this coordination has terminated. Guard against spurious

-		// wakeups using isTerminated().

-		synchronized (this) {

-			while (!terminated) {

-				wait(timeInMillis);

-				long elapsed = System.currentTimeMillis() - start;

-				if (elapsed > timeInMillis)

-					break;

-			}

-		}

-	}

-

-	public Coordination push() throws CoordinationException {

-		coordinator.checkPermission(CoordinationPermission.INITIATE, name);

-		synchronized (this) {

-			checkTerminated();

-			coordinator.push(this);

-		}

-		return this;

-	}

-

-	synchronized Date getDeadline() {

-		return deadline;

-	}

-

-	LogService getLogService() {

-		return coordinator.getLogService();

-	}

-

-	synchronized void setTimerTask(TimerTask timerTask) {

-		this.timerTask = timerTask;

-	}

-	

-	synchronized void setThreadAndEnclosingCoordination(Thread t, Reference<CoordinationImpl> c) {

-		thread = t;

-		enclosingCoordination = c;

-	}

-

-	private void checkTerminated() throws CoordinationException {

-		// If this coordination is not terminated, simply return.

-		if (!terminated)

-			return;

-		// The coordination has terminated. Figure out which type of exception

-		// must be thrown.

-		if (failure != null) {

-			// The fail() method was called indicating the coordination failed.

-			throw new CoordinationException(Messages.CoordinationImpl_7, this, CoordinationException.FAILED, failure);

-		}

-		// The coordination did not fail, so it either partially ended or 

-		// ended successfully.

-		throw new CoordinationException(Messages.CoordinationImpl_8, CoordinationImpl.this, CoordinationException.ALREADY_ENDED);

-	}

-

-	private void terminate() throws CoordinationException {

-		checkTerminated();

-		terminated = true;

-		// Cancel the timeout. Purge the task if it was, in fact, canceled.

-		if (timerTask != null && timerTask.cancel()) {

-			coordinator.purge();

-		}

-		coordinator.terminate(this, participants);

-	}

-

-	private static void validateName(String name) {

-		boolean valid = true;

-		if (name == null || name.length() == 0)

-			valid = false;

-		else {

-			boolean period = false;

-			for (char c : name.toCharArray()) {

-				if (Character.isLetterOrDigit(c) || c == '_' || c == '-') {

-					period = false;

-				} else if (c == '.' && !period) {

-					period = true;

-				} else {

-					valid = false;

-					break;

-				}

-			}

-		}

-		if (!valid)

-			throw new IllegalArgumentException(Messages.CoordinationImpl_10);

-	}

-

-	private static void validateTimeout(long timeout) {

-		if (timeout < 0)

-			throw new IllegalArgumentException(Messages.CoordinationImpl_12);

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.lang.ref.Reference;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.TimerTask;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.CoordinationException;
+import org.osgi.service.coordinator.CoordinationPermission;
+import org.osgi.service.coordinator.Participant;
+import org.osgi.service.log.LogService;
+
+public class CoordinationImpl implements Coordination {
+	private volatile Throwable failure;
+	private volatile boolean terminated;
+	
+	private Date deadline;
+	private Reference<CoordinationImpl> enclosingCoordination;
+	private Thread thread;
+	private TimerTask timerTask;
+	
+	private final CoordinatorImpl coordinator;
+	private final long id;
+	private final String name;
+	private final List<Participant> participants;
+	private final Map<Class<?>, Object> variables;
+
+	public CoordinationImpl(long id, String name, long timeout, CoordinatorImpl coordinator) {
+		validateName(name);
+		validateTimeout(timeout);
+		this.id = id;
+		this.name = name;
+		this.deadline = new Date(System.currentTimeMillis() + timeout);
+		this.coordinator = coordinator;
+		participants = Collections.synchronizedList(new ArrayList<Participant>());
+		variables = new HashMap<Class<?>, Object>();
+	}
+
+	public void addParticipant(Participant participant) throws CoordinationException {
+		// This method requires the PARTICIPATE permission.
+		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);
+		if (participant == null)
+			throw new NullPointerException(Messages.CoordinationImpl_15);
+		/* The caller has permission. Check to see if the participant is already 
+		 * participating in another coordination. Do this in a loop in case the 
+		 * participant must wait for the other coordination to finish. The loop 
+		 * will exit under the following circumstances.
+		 * 
+		 * (1) This coordination is terminated.
+		 * (2) The participant is already participating in another coordination
+		 * using the same thread as this one.
+		 * (3) This thread is interrupted.
+		 * (4) The participant is not participating in another coordination.
+		 */
+		while (true) {
+			CoordinationImpl coordination;
+			synchronized (this) {
+				// Check to see if this coordination has already terminated. If so, 
+				// throw the appropriate exception.
+				checkTerminated();
+				coordination = coordinator.addParticipant(participant, this);
+				if (coordination == null) {
+					// The same participant is not currently participating in 
+					// any coordination. Add it to this coordination and break 
+					// out of the loop.
+					participants.add(participant);
+					break;
+				} else if (coordination == this) {
+					// The same participant is being added twice to this 
+					// coordination. Nothing to do.
+					break;
+				} else {
+					// This means the participant is already participating in another
+					// coordination. Check to see if it's on the same thread.
+					Thread t = coordination.getThread();
+					// If thread is null, the coordination is not associated with
+					// any thread, and there's nothing to compare. If the coordination 
+					// is using this thread, then we can't block due to risk of deadlock.
+					if (t == Thread.currentThread()) {
+						throw new CoordinationException(Messages.CoordinationImpl_1, CoordinationImpl.this, CoordinationException.DEADLOCK_DETECTED);
+					}
+				}
+			}
+			// The participant is already participating in another coordination 
+			// that's not using this thread. Block until that coordination has
+			// finished. A decision was made here to use a timeout and incur the
+			// expense of waking up and rejoining in order to make a reasonably 
+			// timely exit if this coordination terminates.
+			try {
+				coordination.join(1000);
+			} catch (InterruptedException e) {
+				coordinator.getLogService().log(LogService.LOG_DEBUG, Messages.CoordinationImpl_2, e);
+				// This thread was interrupted while waiting for the coordination
+				// to terminate.
+				throw new CoordinationException(Messages.CoordinationImpl_3, CoordinationImpl.this, CoordinationException.LOCK_INTERRUPTED, e);
+			}
+		}
+	}
+
+	public void end() throws CoordinationException {
+		coordinator.checkPermission(CoordinationPermission.INITIATE, name);
+		// Terminating the coordination must be atomic.
+		synchronized (this) {
+			// If this coordination is associated with a thread, an additional
+			// check is required.
+			if (thread != null) {
+				// Coordinations may only be ended by the same thread that
+				// pushed them onto the stack, if any.
+				if (thread != Thread.currentThread()) {
+					throw new CoordinationException(Messages.CoordinationImpl_14, this, CoordinationException.WRONG_THREAD);
+				}
+				// Unwind the stack in case there are other coordinations higher
+				// up than this one.
+				while (coordinator.peek() != this) {
+					try {
+						coordinator.peek().end();
+					} catch (CoordinationException e) {
+						coordinator.peek().fail(e);
+					}
+				}
+				// A coordination is removed from the thread local stack only when being ended.
+				// This must occur even if the coordination is already terminated due to a
+				// failure.
+				coordinator.pop();
+			}
+			terminate();
+		}
+		// Notify participants this coordination has ended. Track whether or
+		// not a partial ending has occurred.
+		Exception exception = null;
+		// No additional synchronization is needed here because the participant
+		// list will not be modified post termination.
+		for (Participant participant : participants) {
+			try {
+				participant.ended(this);
+			} catch (Exception e) {
+				coordinator.getLogService().log(LogService.LOG_WARNING, Messages.CoordinationImpl_4, e);
+				// Only the first exception will be propagated.
+				if (exception == null)
+					exception = e;
+			}
+		}
+		synchronized (this) {
+			// Notify everything joined to this coordination that it has finished.
+			notifyAll();
+		}
+		// If a partial ending has occurred, throw the required exception.
+		if (exception != null) {
+			throw new CoordinationException(Messages.CoordinationImpl_5, this, CoordinationException.PARTIALLY_ENDED, exception);
+		}
+	}
+
+	public long extendTimeout(long timeInMillis) throws CoordinationException {
+		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);
+		validateTimeout(timeInMillis);
+		// We don't want this coordination to terminate before the new timer is 
+		// in place.
+		synchronized (this) {
+			// Check to see if this coordination has already terminated. If so, 
+			// throw the appropriate exception.
+			checkTerminated();
+			// If there was no previous timeout set, return 0 indicating that no
+			// extension has taken place.
+			if (timerTask == null)
+				return 0;
+			// Passing anything less than zero as well as zero itself will return the
+			// existing deadline. The deadline will not be null if timerTask is not null.
+			if (timeInMillis == 0)
+				return deadline.getTime();
+			// Cancel the current timeout.
+			boolean cancelled = timerTask.cancel();
+			if (!cancelled) {
+				// This means the previous task has run and is waiting to get a lock on
+				// this coordination. We can't throw an exception yet because we can't
+				// know which one to use (ALREADY_ENDED or FAILED). Once the lock is
+				// released, the running task may fail this coordination due to a timeout, 
+				// or something else might be waiting to fail this coordination for other
+				// reasons or to end it. We simply don't know who will win the race.
+				try {
+					// Wait until this coordination terminates.
+					join(0);
+					// Now determine how it terminated and throw the appropriate exception.
+					checkTerminated();
+				}
+				catch (InterruptedException e) {
+					throw new CoordinationException(Messages.CoordinationImpl_13, this, CoordinationException.UNKNOWN, e);
+				}
+			}
+			// Create the new timeout.
+			timerTask = new CoordinationTimerTask(this);
+			// Extend the current deadline.
+			deadline = new Date(deadline.getTime() + timeInMillis);
+			// Schedule the new timeout.
+			coordinator.schedule(timerTask, deadline);
+			// Return the new deadline.
+			return deadline.getTime();
+		}
+	}
+
+	public boolean fail(Throwable reason) {
+		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);
+		// The reason must not be null.
+		if (reason == null)
+			throw new NullPointerException(Messages.CoordinationImpl_11);
+		// Terminating the coordination must be atomic.
+		synchronized (this) {
+			// If this coordination is terminated, return false. Do not throw a
+			// CoordinationException as in other methods.
+			if (terminated)
+				return false;
+			// This coordination has not already terminated, so terminate now.
+			terminate();
+			// Store the reason for the failure.
+			failure = reason;
+		}
+		// Notify participants this coordination has failed.
+		// No additional synchronization is needed here because the participant
+		// list will not be modified post termination.
+		for (Participant participant : participants) {
+			try {
+				participant.failed(this);
+			} catch (Exception e) {
+				coordinator.getLogService().log(LogService.LOG_WARNING, Messages.CoordinationImpl_6, e);
+			}
+		}
+		synchronized (this) {
+			// Notify everything joined to this coordination that it has finished.
+			notifyAll();
+		}
+		// Return true to indicate this call resulted in the coordination's failure.
+		return true;
+	}
+	
+	public Bundle getBundle() {
+		coordinator.checkPermission(CoordinationPermission.ADMIN, name);
+		return coordinator.getBundle();
+	}
+	
+	public synchronized Coordination getEnclosingCoordination() {
+		coordinator.checkPermission(CoordinationPermission.ADMIN, name);
+		return enclosingCoordination == null ? null : enclosingCoordination.get();
+	}
+
+	public Throwable getFailure() {
+		coordinator.checkPermission(CoordinationPermission.INITIATE, name);
+		return failure;
+	}
+
+	public long getId() {
+		return id;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public List<Participant> getParticipants() {
+		// This method requires the ADMIN permission.
+		coordinator.checkPermission(CoordinationPermission.INITIATE, name);
+		// Return a mutable snapshot.
+		synchronized (participants) {
+			return new ArrayList<Participant>(participants);
+		}
+	}
+
+	public synchronized Thread getThread() {
+		coordinator.checkPermission(CoordinationPermission.ADMIN, name);
+		return thread;
+	}
+
+	public Map<Class<?>, Object> getVariables() {
+		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);
+		return variables;
+	}
+
+	public boolean isTerminated() {
+		return terminated;
+	}
+
+	public void join(long timeInMillis) throws InterruptedException {
+		coordinator.checkPermission(CoordinationPermission.PARTICIPATE, name);
+		long start = System.currentTimeMillis();
+		// Wait until this coordination has terminated. Guard against spurious
+		// wakeups using isTerminated().
+		synchronized (this) {
+			while (!terminated) {
+				wait(timeInMillis);
+				long elapsed = System.currentTimeMillis() - start;
+				if (elapsed > timeInMillis)
+					break;
+			}
+		}
+	}
+
+	public Coordination push() throws CoordinationException {
+		coordinator.checkPermission(CoordinationPermission.INITIATE, name);
+		synchronized (this) {
+			checkTerminated();
+			coordinator.push(this);
+		}
+		return this;
+	}
+
+	synchronized Date getDeadline() {
+		return deadline;
+	}
+
+	LogService getLogService() {
+		return coordinator.getLogService();
+	}
+
+	synchronized void setTimerTask(TimerTask timerTask) {
+		this.timerTask = timerTask;
+	}
+	
+	synchronized void setThreadAndEnclosingCoordination(Thread t, Reference<CoordinationImpl> c) {
+		thread = t;
+		enclosingCoordination = c;
+	}
+
+	private void checkTerminated() throws CoordinationException {
+		// If this coordination is not terminated, simply return.
+		if (!terminated)
+			return;
+		// The coordination has terminated. Figure out which type of exception
+		// must be thrown.
+		if (failure != null) {
+			// The fail() method was called indicating the coordination failed.
+			throw new CoordinationException(Messages.CoordinationImpl_7, this, CoordinationException.FAILED, failure);
+		}
+		// The coordination did not fail, so it either partially ended or 
+		// ended successfully.
+		throw new CoordinationException(Messages.CoordinationImpl_8, CoordinationImpl.this, CoordinationException.ALREADY_ENDED);
+	}
+
+	private void terminate() throws CoordinationException {
+		checkTerminated();
+		terminated = true;
+		// Cancel the timeout. Purge the task if it was, in fact, canceled.
+		if (timerTask != null && timerTask.cancel()) {
+			coordinator.purge();
+		}
+		coordinator.terminate(this, participants);
+	}
+
+	private static void validateName(String name) {
+		boolean valid = true;
+		if (name == null || name.length() == 0)
+			valid = false;
+		else {
+			boolean period = false;
+			for (char c : name.toCharArray()) {
+				if (Character.isLetterOrDigit(c) || c == '_' || c == '-') {
+					period = false;
+				} else if (c == '.' && !period) {
+					period = true;
+				} else {
+					valid = false;
+					break;
+				}
+			}
+		}
+		if (!valid)
+			throw new IllegalArgumentException(Messages.CoordinationImpl_10);
+	}
+
+	private static void validateTimeout(long timeout) {
+		if (timeout < 0)
+			throw new IllegalArgumentException(Messages.CoordinationImpl_12);
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationTimerTask.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationTimerTask.java
index 6f3279f..8c243d3 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationTimerTask.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinationTimerTask.java
@@ -1,37 +1,37 @@
-/*******************************************************************************

- * Copyright (c) 2010 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.util.TimerTask;

-

-import org.osgi.service.coordinator.Coordination;

-import org.osgi.service.log.LogService;

-

-public class CoordinationTimerTask extends TimerTask {

-	private final CoordinationImpl coordination;

-

-	public CoordinationTimerTask(CoordinationImpl coordination) {

-		if (coordination == null)

-			throw new IllegalArgumentException(Messages.CoordinationImpl_0);

-		this.coordination = coordination;

-	}

-

-	@Override

-	public void run() {

-		// Catch all exceptions and errors in order to prevent the timer 

-		// thread from stopping.

-		try {

-			coordination.fail(Coordination.TIMEOUT);

-		} catch (Throwable t) {

-			coordination.getLogService().log(LogService.LOG_ERROR, Messages.CoordinationImpl_9, t);

-		}

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.util.TimerTask;
+
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.log.LogService;
+
+public class CoordinationTimerTask extends TimerTask {
+	private final CoordinationImpl coordination;
+
+	public CoordinationTimerTask(CoordinationImpl coordination) {
+		if (coordination == null)
+			throw new IllegalArgumentException(Messages.CoordinationImpl_0);
+		this.coordination = coordination;
+	}
+
+	@Override
+	public void run() {
+		// Catch all exceptions and errors in order to prevent the timer 
+		// thread from stopping.
+		try {
+			coordination.fail(Coordination.TIMEOUT);
+		} catch (Throwable t) {
+			coordination.getLogService().log(LogService.LOG_ERROR, Messages.CoordinationImpl_9, t);
+		}
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorComponent.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorComponent.java
index a03b311..31b8e3e 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorComponent.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorComponent.java
@@ -1,64 +1,64 @@
-/*******************************************************************************

- * Copyright (c) 2010, 2011 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.util.Collection;

-

-import org.osgi.framework.BundleContext;

-import org.osgi.service.component.ComponentContext;

-import org.osgi.service.coordinator.Coordination;

-import org.osgi.service.coordinator.CoordinationException;

-import org.osgi.service.coordinator.Coordinator;

-import org.osgi.service.coordinator.Participant;

-

-public class CoordinatorComponent implements Coordinator {

-	private volatile Coordinator coordinator;

-

-	public boolean addParticipant(Participant participant) throws CoordinationException {

-		return coordinator.addParticipant(participant);

-	}

-

-	public Coordination begin(String name, long timeout) {

-		return coordinator.begin(name, timeout);

-	}

-

-	public Coordination create(String name, long timeout) {

-		return coordinator.create(name, timeout);

-	}

-

-	public boolean fail(Throwable reason) {

-		return coordinator.fail(reason);

-	}

-

-	public Coordination getCoordination(long id) {

-		return coordinator.getCoordination(id);

-	}

-

-	public Collection<Coordination> getCoordinations() {

-		return coordinator.getCoordinations();

-	}

-

-	public Coordination peek() {

-		return coordinator.peek();

-	}

-

-	public Coordination pop() {

-		return coordinator.pop();

-	}

-

-	void activate(ComponentContext componentContext) {

-		coordinator = Activator.factory.getService(componentContext.getUsingBundle(), null);

-	}

-

-	void deactivate(BundleContext context) {

-		((CoordinatorImpl) coordinator).shutdown();

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.util.Collection;
+
+import org.osgi.framework.BundleContext;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.CoordinationException;
+import org.osgi.service.coordinator.Coordinator;
+import org.osgi.service.coordinator.Participant;
+
+public class CoordinatorComponent implements Coordinator {
+	private volatile Coordinator coordinator;
+
+	public boolean addParticipant(Participant participant) throws CoordinationException {
+		return coordinator.addParticipant(participant);
+	}
+
+	public Coordination begin(String name, long timeout) {
+		return coordinator.begin(name, timeout);
+	}
+
+	public Coordination create(String name, long timeout) {
+		return coordinator.create(name, timeout);
+	}
+
+	public boolean fail(Throwable reason) {
+		return coordinator.fail(reason);
+	}
+
+	public Coordination getCoordination(long id) {
+		return coordinator.getCoordination(id);
+	}
+
+	public Collection<Coordination> getCoordinations() {
+		return coordinator.getCoordinations();
+	}
+
+	public Coordination peek() {
+		return coordinator.peek();
+	}
+
+	public Coordination pop() {
+		return coordinator.pop();
+	}
+
+	void activate(ComponentContext componentContext) {
+		coordinator = Activator.factory.getService(componentContext.getUsingBundle(), null);
+	}
+
+	void deactivate(BundleContext context) {
+		((CoordinatorImpl) coordinator).shutdown();
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java
index e89be7d..4060b66 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorImpl.java
@@ -1,292 +1,292 @@
-/*******************************************************************************

- * Copyright (c) 2010, 2011 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.lang.ref.Reference;

-import java.lang.ref.ReferenceQueue;

-import java.lang.ref.WeakReference;

-import java.security.Permission;

-import java.util.ArrayList;

-import java.util.Collection;

-import java.util.Date;

-import java.util.HashMap;

-import java.util.IdentityHashMap;

-import java.util.LinkedList;

-import java.util.List;

-import java.util.Map;

-import java.util.Timer;

-import java.util.TimerTask;

-

-import org.osgi.framework.Bundle;

-import org.osgi.service.coordinator.Coordination;

-import org.osgi.service.coordinator.CoordinationException;

-import org.osgi.service.coordinator.CoordinationPermission;

-import org.osgi.service.coordinator.Coordinator;

-import org.osgi.service.coordinator.Participant;

-import org.osgi.service.log.LogService;

-

-public class CoordinatorImpl implements Coordinator {

-	// IDs must be positive integers and monotonically increasing.

-	private static long lastId;

-

-	private synchronized static long getNextId() {

-		if (Long.MAX_VALUE == lastId)

-			throw new IllegalStateException(Messages.CoordinatorImpl_0);

-		// First ID will be 1.

-		return ++lastId;

-	}

-

-	// Coordination IDs must be unique across all using bundles.

-	private static final Map<Long, CoordinationImpl> idToCoordination = new HashMap<Long, CoordinationImpl>();

-	// Coordination participation must be tracked across all using bundles.

-	private static final Map<Participant, CoordinationImpl> participantToCoordination = new IdentityHashMap<Participant, CoordinationImpl>();

-

-	private static ThreadLocal<WeakCoordinationStack> coordinationStack = new ThreadLocal<WeakCoordinationStack>() {

-		@Override 

-		protected WeakCoordinationStack initialValue() {

-			return new WeakCoordinationStack();

-		}

-	};

-	

-	private static class WeakCoordinationStack {

-		private final LinkedList<Reference<CoordinationImpl>> coordinations = new LinkedList<Reference<CoordinationImpl>>();

-		private final ReferenceQueue<CoordinationImpl> queue = new ReferenceQueue<CoordinationImpl>();

-		

-		public WeakCoordinationStack() {

-		}

-

-		public boolean contains(CoordinationImpl c) {

-			purge();

-			for (Reference<CoordinationImpl> r : coordinations) {

-				if (c.equals(r.get()))

-					return true;

-			}

-			return false;

-		}

-		

-		public CoordinationImpl peek() {

-			purge();

-			if (coordinations.isEmpty())

-				return null;

-			return coordinations.getFirst().get();

-		}

-		

-		public CoordinationImpl pop() {

-			purge();

-			if (coordinations.isEmpty())

-				return null;

-			CoordinationImpl c = coordinations.removeFirst().get();

-			if (c != null)

-				c.setThreadAndEnclosingCoordination(null, null);

-			return c;

-		}

-		

-		public void push(CoordinationImpl c) {

-			purge();

-			if (contains(c))

-				throw new CoordinationException(Messages.CoordinatorImpl_3, c, CoordinationException.ALREADY_PUSHED);

-			Reference<CoordinationImpl> r = new WeakReference<CoordinationImpl>(c, queue);

-			c.setThreadAndEnclosingCoordination(Thread.currentThread(), coordinations.isEmpty() ? null : coordinations.getFirst());

-			coordinations.addFirst(r);

-		}

-		

-		private void purge() {

-			Reference<? extends CoordinationImpl> r;

-			while ((r = queue.poll()) != null) {

-				int index = coordinations.indexOf(r);

-				coordinations.remove(r);

-				if (index > 0) {

-					r = coordinations.get(index - 1);

-					CoordinationImpl c = r.get();

-					if (c != null)

-						c.setThreadAndEnclosingCoordination(Thread.currentThread(), coordinations.get(index));

-				}

-			}

-		}

-	}

-	

-	private final Bundle bundle;

-	private final List<CoordinationImpl> coordinations;

-	private final LogService logService;

-	private final Timer timer;

-

-	private boolean shutdown;

-

-	public CoordinatorImpl(Bundle bundle, LogService logService, Timer timer) {

-		this.bundle = bundle;

-		this.logService = logService;

-		this.timer = timer;

-		coordinations = new ArrayList<CoordinationImpl>();

-	}

-

-	public boolean addParticipant(Participant participant) throws CoordinationException {

-		Coordination coordination = peek();

-		if (coordination == null)

-			return false;

-		coordination.addParticipant(participant);

-		return true;

-	}

-

-	public Coordination begin(String name, long timeout) {

-		CoordinationImpl coordination = (CoordinationImpl) create(name, timeout);

-		coordination.push();

-		return coordination;

-	}

-

-	public Coordination create(String name, long timeout) {

-		// This method requires the INITIATE permission. No bundle check is done.

-		checkPermission(CoordinationPermission.INITIATE, name);

-		CoordinationImpl coordination = new CoordinationImpl(getNextId(), name, timeout, this);

-		synchronized (this) {

-			if (shutdown)

-				throw new IllegalStateException(Messages.CoordinatorImpl_2);

-			synchronized (CoordinatorImpl.class) {

-				coordinations.add(coordination);

-				idToCoordination.put(new Long(coordination.getId()), coordination);

-			}

-		}

-		if (timeout > 0) {

-			TimerTask timerTask = new CoordinationTimerTask(coordination);

-			coordination.setTimerTask(timerTask);

-			schedule(timerTask, coordination.getDeadline());

-		}

-		return coordination;

-	}

-

-	public boolean fail(Throwable reason) {

-		Coordination coordination = peek();

-		if (coordination == null)

-			return false;

-		return coordination.fail(reason);

-	}

-

-	public Coordination getCoordination(long id) {

-		CoordinationImpl result = null;

-		synchronized (CoordinatorImpl.class) {

-			result = idToCoordination.get(new Long(id));

-		}

-		if (result != null && !result.isTerminated()) {

-			try {

-				checkPermission(CoordinationPermission.ADMIN, result.getName());

-			} catch (SecurityException e) {

-				logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_1, e);

-				result = null;

-			}

-		}

-		return result;

-	}

-

-	public Collection<Coordination> getCoordinations() {

-		ArrayList<Coordination> result;

-		synchronized (CoordinatorImpl.class) {

-			result = new ArrayList<Coordination>(idToCoordination.size());

-			for (CoordinationImpl coordination : idToCoordination.values()) {

-				// Ideally, we're only interested in coordinations that have not terminated.

-				// It's okay, however, if the coordination terminates from this point forward.

-				if (coordination.isTerminated())

-					continue;

-				try {

-					checkPermission(CoordinationPermission.ADMIN, coordination.getName());

-					result.add(coordination);

-				} catch (SecurityException e) {

-					logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_1, e);

-				}

-			}

-		}

-		result.trimToSize();

-		return result;

-	}

-

-	public Coordination peek() {

-		return coordinationStack.get().peek();

-	}

-

-	public Coordination pop() {

-		Coordination c = coordinationStack.get().peek();

-		if (c == null) return null;

-		checkPermission(CoordinationPermission.INITIATE, c.getName());

-		return coordinationStack.get().pop();

-	}

-

-	CoordinationImpl addParticipant(Participant participant, CoordinationImpl coordination) {

-		CoordinationImpl result = null;

-		synchronized (participantToCoordination) {

-			result = participantToCoordination.get(participant);

-			if (result == null) {

-				participantToCoordination.put(participant, coordination);

-			}

-		}

-		return result;

-	}

-

-	void checkPermission(String permissionType, String coordinationName) {

-		checkPermission(new CoordinationPermission(coordinationName, bundle, permissionType));

-	}

-

-	void checkPermission(Permission permission) {

-		SecurityManager securityManager = System.getSecurityManager();

-		if (securityManager == null)

-			return;

-		securityManager.checkPermission(permission);

-	}

-

-	Bundle getBundle() {

-		return bundle;

-	}

-

-	LogService getLogService() {

-		return logService;

-	}

-

-	void purge() {

-		// Purge the timer of all canceled tasks if we're running on a supportive JCL.

-		try {

-			Timer.class.getMethod("purge", (Class<?>[]) null).invoke(timer, (Object[]) null); //$NON-NLS-1$

-		} catch (Exception e) {

-			logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_4, e);

-		}

-	}

-

-	void push(CoordinationImpl coordination) throws CoordinationException {

-		coordinationStack.get().push(coordination);

-	}

-

-	void schedule(TimerTask task, Date deadline) {

-		timer.schedule(task, deadline);

-	}

-

-	void shutdown() {

-		List<Coordination> coords;

-		synchronized (this) {

-			shutdown = true;

-			// Make a copy so the removal of the coordination from the list during

-			// termination does not interfere with the iteration.

-			coords = new ArrayList<Coordination>(this.coordinations);

-		}

-		for (Coordination coordination : coords) {

-			coordination.fail(Coordination.RELEASED);

-		}

-	}

-

-	/*

-	 * This procedure must occur when a coordination is being failed or ended.

-	 */

-	void terminate(Coordination coordination, List<Participant> participants) {

-		// A coordination has been terminated and needs to be removed from the thread local stack.

-		synchronized (this) {

-			synchronized (CoordinatorImpl.class) {

-				this.coordinations.remove(coordination);

-				idToCoordination.remove(new Long(coordination.getId()));

-				participantToCoordination.keySet().removeAll(participants);

-			}

-		}

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.lang.ref.Reference;
+import java.lang.ref.ReferenceQueue;
+import java.lang.ref.WeakReference;
+import java.security.Permission;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.IdentityHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.osgi.framework.Bundle;
+import org.osgi.service.coordinator.Coordination;
+import org.osgi.service.coordinator.CoordinationException;
+import org.osgi.service.coordinator.CoordinationPermission;
+import org.osgi.service.coordinator.Coordinator;
+import org.osgi.service.coordinator.Participant;
+import org.osgi.service.log.LogService;
+
+public class CoordinatorImpl implements Coordinator {
+	// IDs must be positive integers and monotonically increasing.
+	private static long lastId;
+
+	private synchronized static long getNextId() {
+		if (Long.MAX_VALUE == lastId)
+			throw new IllegalStateException(Messages.CoordinatorImpl_0);
+		// First ID will be 1.
+		return ++lastId;
+	}
+
+	// Coordination IDs must be unique across all using bundles.
+	private static final Map<Long, CoordinationImpl> idToCoordination = new HashMap<Long, CoordinationImpl>();
+	// Coordination participation must be tracked across all using bundles.
+	private static final Map<Participant, CoordinationImpl> participantToCoordination = new IdentityHashMap<Participant, CoordinationImpl>();
+
+	private static ThreadLocal<WeakCoordinationStack> coordinationStack = new ThreadLocal<WeakCoordinationStack>() {
+		@Override 
+		protected WeakCoordinationStack initialValue() {
+			return new WeakCoordinationStack();
+		}
+	};
+	
+	private static class WeakCoordinationStack {
+		private final LinkedList<Reference<CoordinationImpl>> coordinations = new LinkedList<Reference<CoordinationImpl>>();
+		private final ReferenceQueue<CoordinationImpl> queue = new ReferenceQueue<CoordinationImpl>();
+		
+		public WeakCoordinationStack() {
+		}
+
+		public boolean contains(CoordinationImpl c) {
+			purge();
+			for (Reference<CoordinationImpl> r : coordinations) {
+				if (c.equals(r.get()))
+					return true;
+			}
+			return false;
+		}
+		
+		public CoordinationImpl peek() {
+			purge();
+			if (coordinations.isEmpty())
+				return null;
+			return coordinations.getFirst().get();
+		}
+		
+		public CoordinationImpl pop() {
+			purge();
+			if (coordinations.isEmpty())
+				return null;
+			CoordinationImpl c = coordinations.removeFirst().get();
+			if (c != null)
+				c.setThreadAndEnclosingCoordination(null, null);
+			return c;
+		}
+		
+		public void push(CoordinationImpl c) {
+			purge();
+			if (contains(c))
+				throw new CoordinationException(Messages.CoordinatorImpl_3, c, CoordinationException.ALREADY_PUSHED);
+			Reference<CoordinationImpl> r = new WeakReference<CoordinationImpl>(c, queue);
+			c.setThreadAndEnclosingCoordination(Thread.currentThread(), coordinations.isEmpty() ? null : coordinations.getFirst());
+			coordinations.addFirst(r);
+		}
+		
+		private void purge() {
+			Reference<? extends CoordinationImpl> r;
+			while ((r = queue.poll()) != null) {
+				int index = coordinations.indexOf(r);
+				coordinations.remove(r);
+				if (index > 0) {
+					r = coordinations.get(index - 1);
+					CoordinationImpl c = r.get();
+					if (c != null)
+						c.setThreadAndEnclosingCoordination(Thread.currentThread(), coordinations.get(index));
+				}
+			}
+		}
+	}
+	
+	private final Bundle bundle;
+	private final List<CoordinationImpl> coordinations;
+	private final LogService logService;
+	private final Timer timer;
+
+	private boolean shutdown;
+
+	public CoordinatorImpl(Bundle bundle, LogService logService, Timer timer) {
+		this.bundle = bundle;
+		this.logService = logService;
+		this.timer = timer;
+		coordinations = new ArrayList<CoordinationImpl>();
+	}
+
+	public boolean addParticipant(Participant participant) throws CoordinationException {
+		Coordination coordination = peek();
+		if (coordination == null)
+			return false;
+		coordination.addParticipant(participant);
+		return true;
+	}
+
+	public Coordination begin(String name, long timeout) {
+		CoordinationImpl coordination = (CoordinationImpl) create(name, timeout);
+		coordination.push();
+		return coordination;
+	}
+
+	public Coordination create(String name, long timeout) {
+		// This method requires the INITIATE permission. No bundle check is done.
+		checkPermission(CoordinationPermission.INITIATE, name);
+		CoordinationImpl coordination = new CoordinationImpl(getNextId(), name, timeout, this);
+		synchronized (this) {
+			if (shutdown)
+				throw new IllegalStateException(Messages.CoordinatorImpl_2);
+			synchronized (CoordinatorImpl.class) {
+				coordinations.add(coordination);
+				idToCoordination.put(new Long(coordination.getId()), coordination);
+			}
+		}
+		if (timeout > 0) {
+			TimerTask timerTask = new CoordinationTimerTask(coordination);
+			coordination.setTimerTask(timerTask);
+			schedule(timerTask, coordination.getDeadline());
+		}
+		return coordination;
+	}
+
+	public boolean fail(Throwable reason) {
+		Coordination coordination = peek();
+		if (coordination == null)
+			return false;
+		return coordination.fail(reason);
+	}
+
+	public Coordination getCoordination(long id) {
+		CoordinationImpl result = null;
+		synchronized (CoordinatorImpl.class) {
+			result = idToCoordination.get(new Long(id));
+		}
+		if (result != null && !result.isTerminated()) {
+			try {
+				checkPermission(CoordinationPermission.ADMIN, result.getName());
+			} catch (SecurityException e) {
+				logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_1, e);
+				result = null;
+			}
+		}
+		return result;
+	}
+
+	public Collection<Coordination> getCoordinations() {
+		ArrayList<Coordination> result;
+		synchronized (CoordinatorImpl.class) {
+			result = new ArrayList<Coordination>(idToCoordination.size());
+			for (CoordinationImpl coordination : idToCoordination.values()) {
+				// Ideally, we're only interested in coordinations that have not terminated.
+				// It's okay, however, if the coordination terminates from this point forward.
+				if (coordination.isTerminated())
+					continue;
+				try {
+					checkPermission(CoordinationPermission.ADMIN, coordination.getName());
+					result.add(coordination);
+				} catch (SecurityException e) {
+					logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_1, e);
+				}
+			}
+		}
+		result.trimToSize();
+		return result;
+	}
+
+	public Coordination peek() {
+		return coordinationStack.get().peek();
+	}
+
+	public Coordination pop() {
+		Coordination c = coordinationStack.get().peek();
+		if (c == null) return null;
+		checkPermission(CoordinationPermission.INITIATE, c.getName());
+		return coordinationStack.get().pop();
+	}
+
+	CoordinationImpl addParticipant(Participant participant, CoordinationImpl coordination) {
+		CoordinationImpl result = null;
+		synchronized (participantToCoordination) {
+			result = participantToCoordination.get(participant);
+			if (result == null) {
+				participantToCoordination.put(participant, coordination);
+			}
+		}
+		return result;
+	}
+
+	void checkPermission(String permissionType, String coordinationName) {
+		checkPermission(new CoordinationPermission(coordinationName, bundle, permissionType));
+	}
+
+	void checkPermission(Permission permission) {
+		SecurityManager securityManager = System.getSecurityManager();
+		if (securityManager == null)
+			return;
+		securityManager.checkPermission(permission);
+	}
+
+	Bundle getBundle() {
+		return bundle;
+	}
+
+	LogService getLogService() {
+		return logService;
+	}
+
+	void purge() {
+		// Purge the timer of all canceled tasks if we're running on a supportive JCL.
+		try {
+			Timer.class.getMethod("purge", (Class<?>[]) null).invoke(timer, (Object[]) null); //$NON-NLS-1$
+		} catch (Exception e) {
+			logService.log(LogService.LOG_DEBUG, Messages.CoordinatorImpl_4, e);
+		}
+	}
+
+	void push(CoordinationImpl coordination) throws CoordinationException {
+		coordinationStack.get().push(coordination);
+	}
+
+	void schedule(TimerTask task, Date deadline) {
+		timer.schedule(task, deadline);
+	}
+
+	void shutdown() {
+		List<Coordination> coords;
+		synchronized (this) {
+			shutdown = true;
+			// Make a copy so the removal of the coordination from the list during
+			// termination does not interfere with the iteration.
+			coords = new ArrayList<Coordination>(this.coordinations);
+		}
+		for (Coordination coordination : coords) {
+			coordination.fail(Coordination.RELEASED);
+		}
+	}
+
+	/*
+	 * This procedure must occur when a coordination is being failed or ended.
+	 */
+	void terminate(Coordination coordination, List<Participant> participants) {
+		// A coordination has been terminated and needs to be removed from the thread local stack.
+		synchronized (this) {
+			synchronized (CoordinatorImpl.class) {
+				this.coordinations.remove(coordination);
+				idToCoordination.remove(new Long(coordination.getId()));
+				participantToCoordination.keySet().removeAll(participants);
+			}
+		}
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java
index 7dbe3f8..86dee19 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/CoordinatorServiceFactory.java
@@ -1,42 +1,42 @@
-/*******************************************************************************

- * Copyright (c) 2010, 2011 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.util.Timer;

-

-import org.osgi.framework.Bundle;

-import org.osgi.framework.BundleContext;

-import org.osgi.framework.ServiceFactory;

-import org.osgi.framework.ServiceRegistration;

-import org.osgi.service.coordinator.Coordinator;

-

-public class CoordinatorServiceFactory implements ServiceFactory<Coordinator> {

-	private final LogTracker logTracker;

-	private final Timer timer = new Timer(true);

-

-	public CoordinatorServiceFactory(BundleContext bundleContext) {

-		logTracker = new LogTracker(bundleContext, System.out);

-	}

-

-	public Coordinator getService(Bundle bundle, ServiceRegistration<Coordinator> registration) {

-		return new CoordinatorImpl(bundle, logTracker, timer);

-	}

-

-	public void ungetService(Bundle bundle, ServiceRegistration<Coordinator> registration, Coordinator service) {

-		((CoordinatorImpl) service).shutdown();

-	}

-

-	void shutdown() {

-		timer.cancel();

-//		CoordinatorImpl.reset();

-		logTracker.close();

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.util.Timer;
+
+import org.osgi.framework.Bundle;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceFactory;
+import org.osgi.framework.ServiceRegistration;
+import org.osgi.service.coordinator.Coordinator;
+
+public class CoordinatorServiceFactory implements ServiceFactory<Coordinator> {
+	private final LogTracker logTracker;
+	private final Timer timer = new Timer(true);
+
+	public CoordinatorServiceFactory(BundleContext bundleContext) {
+		logTracker = new LogTracker(bundleContext, System.out);
+	}
+
+	public Coordinator getService(Bundle bundle, ServiceRegistration<Coordinator> registration) {
+		return new CoordinatorImpl(bundle, logTracker, timer);
+	}
+
+	public void ungetService(Bundle bundle, ServiceRegistration<Coordinator> registration, Coordinator service) {
+		((CoordinatorImpl) service).shutdown();
+	}
+
+	void shutdown() {
+		timer.cancel();
+//		CoordinatorImpl.reset();
+		logTracker.close();
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogMessages.properties b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogMessages.properties
index 825f115..55d4784 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogMessages.properties
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogMessages.properties
@@ -1,17 +1,17 @@
-###############################################################################

-# Copyright (c) 2005, 2008 IBM Corporation and others.

-# All rights reserved. This program and the accompanying materials

-# are made available under the terms of the Eclipse Public License v1.0

-# which accompanies this distribution, and is available at

-# http://www.eclipse.org/legal/epl-v10.html

-#

-# Contributors:

-#     IBM Corporation - initial API and implementation

-###############################################################################

-# NLS_MESSAGEFORMAT_ALL 

-

-Unknown_Log_level=Unknown Log Level

-Info=Log Info

-Warning=Log Warning

-Error=Log Error

-Debug=Log Debug

+###############################################################################
+# Copyright (c) 2005, 2011 IBM Corporation and others.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+# NLS_MESSAGEFORMAT_ALL 
+
+Unknown_Log_level=Unknown Log Level
+Info=Log Info
+Warning=Log Warning
+Error=Log Error
+Debug=Log Debug
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTracker.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTracker.java
index 427cae7..2bd60a0 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTracker.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTracker.java
@@ -1,175 +1,175 @@
-/*******************************************************************************

- * Copyright (c) 1998, 2010 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import java.io.PrintStream;

-import java.util.Calendar;

-import java.util.Date;

-import org.osgi.framework.BundleContext;

-import org.osgi.framework.ServiceReference;

-import org.osgi.service.log.LogService;

-import org.osgi.util.tracker.ServiceTracker;

-

-/**

- * LogTracker class. This class encapsulates the LogService

- * and handles all issues such as the service coming and going.

- */

-

-public class LogTracker extends ServiceTracker<LogService, LogService> implements LogService {

-	/** LogService interface class name */

-	protected final static String clazz = "org.osgi.service.log.LogService"; //$NON-NLS-1$

-

-	/** PrintStream to use if LogService is unavailable */

-	private final PrintStream out;

-

-	/**

-	 * Create new LogTracker.

-	 *

-	 * @param context BundleContext of parent bundle.

-	 * @param out Default PrintStream to use if LogService is unavailable.

-	 */

-	public LogTracker(BundleContext context, PrintStream out) {

-		super(context, clazz, null);

-		this.out = out;

-	}

-

-	/*

-	 * ----------------------------------------------------------------------

-	 *      LogService Interface implementation

-	 * ----------------------------------------------------------------------

-	 */

-

-	public void log(int level, String message) {

-		log(null, level, message, null);

-	}

-

-	public void log(int level, String message, Throwable exception) {

-		log(null, level, message, exception);

-	}

-

-	public void log(@SuppressWarnings("rawtypes")

-	ServiceReference reference, int level, String message) {

-		log(reference, level, message, null);

-	}

-

-	public synchronized void log(@SuppressWarnings("rawtypes")

-	ServiceReference reference, int level, String message, Throwable exception) {

-		ServiceReference<LogService>[] references = getServiceReferences();

-

-		if (references != null) {

-			int size = references.length;

-

-			for (int i = 0; i < size; i++) {

-				LogService service = getService(references[i]);

-				if (service != null) {

-					try {

-						service.log(reference, level, message, exception);

-					} catch (Exception e) {

-						// TODO: consider printing to System Error

-					}

-				}

-			}

-

-			return;

-		}

-

-		noLogService(level, message, exception, reference);

-	}

-

-	/**

-	 * The LogService is not available so we write the message to a PrintStream.

-	 *

-	 * @param level Logging level

-	 * @param message Log message.

-	 * @param throwable Log exception or null if none.

-	 * @param reference ServiceReference associated with message or null if none.

-	 */

-	protected void noLogService(int level, String message, Throwable throwable, ServiceReference<?> reference) {

-		if (out != null) {

-			synchronized (out) {

-				// Bug #113286.  If no log service present and messages are being

-				// printed to stdout, prepend message with a timestamp.

-				String timestamp = getDate(new Date());

-				out.print(timestamp + " "); //$NON-NLS-1$

-

-				switch (level) {

-					case LOG_DEBUG : {

-						out.print(LogTrackerMsg.Debug);

-

-						break;

-					}

-					case LOG_INFO : {

-						out.print(LogTrackerMsg.Info);

-

-						break;

-					}

-					case LOG_WARNING : {

-						out.print(LogTrackerMsg.Warning);

-

-						break;

-					}

-					case LOG_ERROR : {

-						out.print(LogTrackerMsg.Error);

-

-						break;

-					}

-					default : {

-						out.print("["); //$NON-NLS-1$

-						out.print(LogTrackerMsg.Unknown_Log_level);

-						out.print("]: "); //$NON-NLS-1$

-

-						break;

-					}

-				}

-

-				out.println(message);

-

-				if (reference != null) {

-					out.println(reference);

-				}

-

-				if (throwable != null) {

-					throwable.printStackTrace(out);

-				}

-			}

-		}

-	}

-

-	// from EclipseLog to avoid using DateFormat -- see bug 149892#c10

-	private String getDate(Date date) {

-		Calendar c = Calendar.getInstance();

-		c.setTime(date);

-		StringBuffer sb = new StringBuffer();

-		appendPaddedInt(c.get(Calendar.YEAR), 4, sb).append('-');

-		appendPaddedInt(c.get(Calendar.MONTH) + 1, 2, sb).append('-');

-		appendPaddedInt(c.get(Calendar.DAY_OF_MONTH), 2, sb).append(' ');

-		appendPaddedInt(c.get(Calendar.HOUR_OF_DAY), 2, sb).append(':');

-		appendPaddedInt(c.get(Calendar.MINUTE), 2, sb).append(':');

-		appendPaddedInt(c.get(Calendar.SECOND), 2, sb).append('.');

-		appendPaddedInt(c.get(Calendar.MILLISECOND), 3, sb);

-		return sb.toString();

-	}

-

-	private StringBuffer appendPaddedInt(int value, int pad, StringBuffer buffer) {

-		pad = pad - 1;

-		if (pad == 0)

-			return buffer.append(Integer.toString(value));

-		int padding = (int) Math.pow(10, pad);

-		if (value >= padding)

-			return buffer.append(Integer.toString(value));

-		while (padding > value && padding > 1) {

-			buffer.append('0');

-			padding = padding / 10;

-		}

-		buffer.append(value);

-		return buffer;

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 1998, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import java.io.PrintStream;
+import java.util.Calendar;
+import java.util.Date;
+import org.osgi.framework.BundleContext;
+import org.osgi.framework.ServiceReference;
+import org.osgi.service.log.LogService;
+import org.osgi.util.tracker.ServiceTracker;
+
+/**
+ * LogTracker class. This class encapsulates the LogService
+ * and handles all issues such as the service coming and going.
+ */
+
+public class LogTracker extends ServiceTracker<LogService, LogService> implements LogService {
+	/** LogService interface class name */
+	protected final static String clazz = "org.osgi.service.log.LogService"; //$NON-NLS-1$
+
+	/** PrintStream to use if LogService is unavailable */
+	private final PrintStream out;
+
+	/**
+	 * Create new LogTracker.
+	 *
+	 * @param context BundleContext of parent bundle.
+	 * @param out Default PrintStream to use if LogService is unavailable.
+	 */
+	public LogTracker(BundleContext context, PrintStream out) {
+		super(context, clazz, null);
+		this.out = out;
+	}
+
+	/*
+	 * ----------------------------------------------------------------------
+	 *      LogService Interface implementation
+	 * ----------------------------------------------------------------------
+	 */
+
+	public void log(int level, String message) {
+		log(null, level, message, null);
+	}
+
+	public void log(int level, String message, Throwable exception) {
+		log(null, level, message, exception);
+	}
+
+	public void log(@SuppressWarnings("rawtypes")
+	ServiceReference reference, int level, String message) {
+		log(reference, level, message, null);
+	}
+
+	public synchronized void log(@SuppressWarnings("rawtypes")
+	ServiceReference reference, int level, String message, Throwable exception) {
+		ServiceReference<LogService>[] references = getServiceReferences();
+
+		if (references != null) {
+			int size = references.length;
+
+			for (int i = 0; i < size; i++) {
+				LogService service = getService(references[i]);
+				if (service != null) {
+					try {
+						service.log(reference, level, message, exception);
+					} catch (Exception e) {
+						// TODO: consider printing to System Error
+					}
+				}
+			}
+
+			return;
+		}
+
+		noLogService(level, message, exception, reference);
+	}
+
+	/**
+	 * The LogService is not available so we write the message to a PrintStream.
+	 *
+	 * @param level Logging level
+	 * @param message Log message.
+	 * @param throwable Log exception or null if none.
+	 * @param reference ServiceReference associated with message or null if none.
+	 */
+	protected void noLogService(int level, String message, Throwable throwable, ServiceReference<?> reference) {
+		if (out != null) {
+			synchronized (out) {
+				// Bug #113286.  If no log service present and messages are being
+				// printed to stdout, prepend message with a timestamp.
+				String timestamp = getDate(new Date());
+				out.print(timestamp + " "); //$NON-NLS-1$
+
+				switch (level) {
+					case LOG_DEBUG : {
+						out.print(LogTrackerMsg.Debug);
+
+						break;
+					}
+					case LOG_INFO : {
+						out.print(LogTrackerMsg.Info);
+
+						break;
+					}
+					case LOG_WARNING : {
+						out.print(LogTrackerMsg.Warning);
+
+						break;
+					}
+					case LOG_ERROR : {
+						out.print(LogTrackerMsg.Error);
+
+						break;
+					}
+					default : {
+						out.print("["); //$NON-NLS-1$
+						out.print(LogTrackerMsg.Unknown_Log_level);
+						out.print("]: "); //$NON-NLS-1$
+
+						break;
+					}
+				}
+
+				out.println(message);
+
+				if (reference != null) {
+					out.println(reference);
+				}
+
+				if (throwable != null) {
+					throwable.printStackTrace(out);
+				}
+			}
+		}
+	}
+
+	// from EclipseLog to avoid using DateFormat -- see bug 149892#c10
+	private String getDate(Date date) {
+		Calendar c = Calendar.getInstance();
+		c.setTime(date);
+		StringBuffer sb = new StringBuffer();
+		appendPaddedInt(c.get(Calendar.YEAR), 4, sb).append('-');
+		appendPaddedInt(c.get(Calendar.MONTH) + 1, 2, sb).append('-');
+		appendPaddedInt(c.get(Calendar.DAY_OF_MONTH), 2, sb).append(' ');
+		appendPaddedInt(c.get(Calendar.HOUR_OF_DAY), 2, sb).append(':');
+		appendPaddedInt(c.get(Calendar.MINUTE), 2, sb).append(':');
+		appendPaddedInt(c.get(Calendar.SECOND), 2, sb).append('.');
+		appendPaddedInt(c.get(Calendar.MILLISECOND), 3, sb);
+		return sb.toString();
+	}
+
+	private StringBuffer appendPaddedInt(int value, int pad, StringBuffer buffer) {
+		pad = pad - 1;
+		if (pad == 0)
+			return buffer.append(Integer.toString(value));
+		int padding = (int) Math.pow(10, pad);
+		if (value >= padding)
+			return buffer.append(Integer.toString(value));
+		while (padding > value && padding > 1) {
+			buffer.append('0');
+			padding = padding / 10;
+		}
+		buffer.append(value);
+		return buffer;
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTrackerMsg.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTrackerMsg.java
index 412163f..33ea3d0 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTrackerMsg.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/LogTrackerMsg.java
@@ -1,28 +1,28 @@
-/*******************************************************************************

- * Copyright (c) 2005, 2008 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import org.eclipse.osgi.util.NLS;

-

-public class LogTrackerMsg extends NLS {

-	private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.event.LogMessages"; //$NON-NLS-1$

-

-	public static String Unknown_Log_level;

-	public static String Info;

-	public static String Warning;

-	public static String Error;

-	public static String Debug;

-

-	static {

-		// initialize resource bundles

-		NLS.initializeMessages(BUNDLE_NAME, LogTrackerMsg.class);

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2005, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import org.eclipse.osgi.util.NLS;
+
+public class LogTrackerMsg extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.equinox.internal.event.LogMessages"; //$NON-NLS-1$
+
+	public static String Unknown_Log_level;
+	public static String Info;
+	public static String Warning;
+	public static String Error;
+	public static String Debug;
+
+	static {
+		// initialize resource bundles
+		NLS.initializeMessages(BUNDLE_NAME, LogTrackerMsg.class);
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java
index b70104e..bb52058 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/Messages.java
@@ -1,47 +1,47 @@
-/*******************************************************************************

- * Copyright (c) 2010, 2011 IBM Corporation and others.

- * All rights reserved. This program and the accompanying materials

- * are made available under the terms of the Eclipse Public License v1.0

- * which accompanies this distribution, and is available at

- * http://www.eclipse.org/legal/epl-v10.html

- *

- * Contributors:

- *     IBM Corporation - initial API and implementation

- *******************************************************************************/

-package org.eclipse.equinox.coordinator;

-

-import org.eclipse.osgi.util.NLS;

-

-public class Messages extends NLS {

-	private static final String BUNDLE_NAME = "org.eclipse.equinox.coordinator.messages"; //$NON-NLS-1$

-	public static String CoordinationImpl_0;

-	public static String CoordinationImpl_1;

-	public static String CoordinationImpl_10;

-	public static String CoordinationImpl_11;

-	public static String CoordinationImpl_12;

-	public static String CoordinationImpl_13;

-	public static String CoordinationImpl_14;

-	public static String CoordinationImpl_15;

-	public static String CoordinationImpl_2;

-	public static String CoordinationImpl_3;

-	public static String CoordinationImpl_4;

-	public static String CoordinationImpl_5;

-	public static String CoordinationImpl_6;

-	public static String CoordinationImpl_7;

-	public static String CoordinationImpl_8;

-	public static String CoordinationImpl_9;

-	public static String CoordinatorImpl_0;

-	public static String CoordinatorImpl_1;

-	public static String CoordinatorImpl_2;

-	public static String CoordinatorImpl_3;

-	public static String CoordinatorImpl_4;

-

-	static {

-		// initialize resource bundle

-		NLS.initializeMessages(BUNDLE_NAME, Messages.class);

-	}

-

-	private Messages() {

-		// noop

-	}

-}

+/*******************************************************************************
+ * Copyright (c) 2010, 2011 IBM Corporation and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     IBM Corporation - initial API and implementation
+ *******************************************************************************/
+package org.eclipse.equinox.coordinator;
+
+import org.eclipse.osgi.util.NLS;
+
+public class Messages extends NLS {
+	private static final String BUNDLE_NAME = "org.eclipse.equinox.coordinator.messages"; //$NON-NLS-1$
+	public static String CoordinationImpl_0;
+	public static String CoordinationImpl_1;
+	public static String CoordinationImpl_10;
+	public static String CoordinationImpl_11;
+	public static String CoordinationImpl_12;
+	public static String CoordinationImpl_13;
+	public static String CoordinationImpl_14;
+	public static String CoordinationImpl_15;
+	public static String CoordinationImpl_2;
+	public static String CoordinationImpl_3;
+	public static String CoordinationImpl_4;
+	public static String CoordinationImpl_5;
+	public static String CoordinationImpl_6;
+	public static String CoordinationImpl_7;
+	public static String CoordinationImpl_8;
+	public static String CoordinationImpl_9;
+	public static String CoordinatorImpl_0;
+	public static String CoordinatorImpl_1;
+	public static String CoordinatorImpl_2;
+	public static String CoordinatorImpl_3;
+	public static String CoordinatorImpl_4;
+
+	static {
+		// initialize resource bundle
+		NLS.initializeMessages(BUNDLE_NAME, Messages.class);
+	}
+
+	private Messages() {
+		// noop
+	}
+}
diff --git a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties
index 8819736..bf1e76e 100644
--- a/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties
+++ b/bundles/org.eclipse.equinox.coordinator/src/org/eclipse/equinox/coordinator/messages.properties
@@ -1,31 +1,31 @@
-###############################################################################

-# Copyright (c) 2010, 2011 IBM Corporation.

-# All rights reserved. This program and the accompanying materials

-# are made available under the terms of the Eclipse Public License v1.0

-# which accompanies this distribution, and is available at

-# http://www.eclipse.org/legal/epl-v10.html

-#

-# Contributors:

-#     IBM Corporation - initial API and implementation

-###############################################################################

-CoordinationImpl_0=Parameter must not be null: coordination

-CoordinationImpl_1=Deadlock detected

-CoordinationImpl_10=The coordination name does not match the Bundle Symbolic Name pattern

-CoordinationImpl_11=A reason must be specified when failing a coordination

-CoordinationImpl_12=A timeout must be a non-negative integer

-CoordinationImpl_13=The timeout could not be extended because the previous one had already expired. The current thread was interrupted before it was possible to determine how this coordination terminated.

-CoordinationImpl_14=Coordinations may only be ended by the same thread that pushed them onto the thread local stack

-CoordinationImpl_15=The participant to add was null

-CoordinationImpl_2=The lock was interrupted

-CoordinationImpl_3=The lock was interrupted

-CoordinationImpl_4=A participant indicated an error occurred while the coordination was ending

-CoordinationImpl_5=Partially ended

-CoordinationImpl_6=A participant indicated an error occurred while the coordination was failing

-CoordinationImpl_7=Coordination has failed

-CoordinationImpl_8=Coordination has already ended

-CoordinationImpl_9=An unexpected exception occurred while failing a coordination. This will not stop the timer thread.

-CoordinatorImpl_0=The next Coordinator ID would exceed the maximum possible value

-CoordinatorImpl_1=A requestor did not have permission to view a coordination

-CoordinatorImpl_2=This coordinator has been shutdown

-CoordinatorImpl_3=Coordination already exists

-CoordinatorImpl_4=Unable to purge the canceled task

+###############################################################################
+# Copyright (c) 2010, 2011 IBM Corporation.
+# All rights reserved. This program and the accompanying materials
+# are made available under the terms of the Eclipse Public License v1.0
+# which accompanies this distribution, and is available at
+# http://www.eclipse.org/legal/epl-v10.html
+#
+# Contributors:
+#     IBM Corporation - initial API and implementation
+###############################################################################
+CoordinationImpl_0=Parameter must not be null: coordination
+CoordinationImpl_1=Deadlock detected
+CoordinationImpl_10=The coordination name does not match the Bundle Symbolic Name pattern
+CoordinationImpl_11=A reason must be specified when failing a coordination
+CoordinationImpl_12=A timeout must be a non-negative integer
+CoordinationImpl_13=The timeout could not be extended because the previous one had already expired. The current thread was interrupted before it was possible to determine how this coordination terminated.
+CoordinationImpl_14=Coordinations may only be ended by the same thread that pushed them onto the thread local stack
+CoordinationImpl_15=The participant to add was null
+CoordinationImpl_2=The lock was interrupted
+CoordinationImpl_3=The lock was interrupted
+CoordinationImpl_4=A participant indicated an error occurred while the coordination was ending
+CoordinationImpl_5=Partially ended
+CoordinationImpl_6=A participant indicated an error occurred while the coordination was failing
+CoordinationImpl_7=Coordination has failed
+CoordinationImpl_8=Coordination has already ended
+CoordinationImpl_9=An unexpected exception occurred while failing a coordination. This will not stop the timer thread.
+CoordinatorImpl_0=The next Coordinator ID would exceed the maximum possible value
+CoordinatorImpl_1=A requestor did not have permission to view a coordination
+CoordinatorImpl_2=This coordinator has been shutdown
+CoordinatorImpl_3=Coordination already exists
+CoordinatorImpl_4=Unable to purge the canceled task