diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/IProcess.java b/common/source/java/ch/systemsx/cisd/common/utilities/IProcess.java
new file mode 100644
index 0000000000000000000000000000000000000000..4f71c216741c5ba9e0b7a8fa627b57816fae807d
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/IProcess.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.utilities;
+
+/**
+ * A <code>Runnable</code> extension that describes a process.
+ * 
+ * @author Christian Ribeaud
+ */
+public interface IProcess extends Runnable
+{
+
+    /**
+     * Whether this <code>IProcess</code> exited successfully.
+     * <p>
+     * Is typically called after {@link Runnable#run()} has performed.
+     * </p>
+     * 
+     * @return <code>true</code> if this <code>IProcess</code> succeeds, terminating so the whole running process.
+     */
+    public boolean succeeded();
+
+    /**
+     * The number of times we should try if this <code>IProcess</code> failed.
+     * <p>
+     * This is a static method: it only gets called once during the initialization process.
+     * </p>
+     */
+    public int getMaxRetryOnFailure();
+
+    /**
+     * The number of milliseconds we should wait before re-executing {@link Runnable#run()}.
+     * <p>
+     * This is a static method: it only gets called once during the initialization process.
+     * </p>
+     */
+    public long getMillisToSleepOnFailure();
+}
diff --git a/common/source/java/ch/systemsx/cisd/common/utilities/ProcessRunner.java b/common/source/java/ch/systemsx/cisd/common/utilities/ProcessRunner.java
new file mode 100644
index 0000000000000000000000000000000000000000..d93a6b7f53d3099f2ed9f18df0f32e8a2d37c77b
--- /dev/null
+++ b/common/source/java/ch/systemsx/cisd/common/utilities/ProcessRunner.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.utilities;
+
+import ch.systemsx.cisd.common.exceptions.CheckedExceptionTunnel;
+
+/**
+ * This class takes cares of running encapsulated {@link IProcess}.
+ * 
+ * @author Christian Ribeaud
+ */
+public final class ProcessRunner
+{
+
+    public ProcessRunner(final IProcess process)
+    {
+        runProcess(process);
+    }
+
+    final static void runProcess(final IProcess process)
+    {
+        final int maxRetryOnFailure = process.getMaxRetryOnFailure();
+        final long millisToSleepOnFailure = process.getMillisToSleepOnFailure();
+        assert millisToSleepOnFailure > -1;
+        int counter = 0;
+        do
+        {
+            process.run();
+            if (counter > 0 && millisToSleepOnFailure > 0)
+            {
+                try
+                {
+                    Thread.sleep(millisToSleepOnFailure);
+                } catch (InterruptedException ex)
+                {
+                    throw new CheckedExceptionTunnel(ex);
+                }
+            }
+        } while (++counter < maxRetryOnFailure && process.succeeded() == false);
+    }
+}
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ProcessRunnerTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ProcessRunnerTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..8f6fb89a9348ed62450529119493db71a22162e2
--- /dev/null
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/utilities/ProcessRunnerTest.java
@@ -0,0 +1,96 @@
+/*
+ * Copyright 2007 ETH Zuerich, CISD
+ *
+ * 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 ch.systemsx.cisd.common.utilities;
+
+import org.jmock.Expectations;
+import org.jmock.Mockery;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+/**
+ * Test cases for the {@link ProcessRunner}.
+ * 
+ * @author Christian Ribeaud
+ */
+public class ProcessRunnerTest
+{
+
+    private Mockery context;
+
+    private IProcess process;
+
+    @BeforeMethod
+    public final void beforeMethod()
+    {
+        context = new Mockery();
+        process = context.mock(IProcess.class);
+    }
+
+    @AfterMethod
+    public final void afterMethod()
+    {
+        // To following line of code should also be called at the end of each test method.
+        // Otherwise one do not known which test failed.
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public final void testRunSuccessfulProcess()
+    {
+        context.checking(new Expectations()
+            {
+                {
+                    one(process).run();
+
+                    one(process).succeeded();
+                    will(returnValue(true));
+
+                    one(process).getMillisToSleepOnFailure();
+                    will(returnValue(1L));
+
+                    one(process).getMaxRetryOnFailure();
+                    will(returnValue(2));
+                }
+            });
+        new ProcessRunner(process);
+        context.assertIsSatisfied();
+    }
+
+    @Test
+    public final void testRunUnsuccessfulProcess()
+    {
+        final int tries = 3;
+        context.checking(new Expectations()
+            {
+                {
+                    exactly(tries).of(process).run();
+
+                    exactly(tries - 1).of(process).succeeded();
+                    will(returnValue(false));
+
+                    one(process).getMillisToSleepOnFailure();
+                    will(returnValue(1L));
+
+                    one(process).getMaxRetryOnFailure();
+                    will(returnValue(tries));
+                }
+            });
+        new ProcessRunner(process);
+        context.assertIsSatisfied();
+    }
+}