diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java b/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java
index 8f86b6f58cac7cb34d9b340883b60e310b9af11e..997d0c01e7323fed05edab854a4a502d5a307bf6 100644
--- a/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java
+++ b/common/source/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopier.java
@@ -51,11 +51,11 @@ import ch.systemsx.cisd.common.utilities.ITerminable;
  */
 public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
 {
-    private static final Logger machineLog =
-            LogFactory.getLogger(LogCategory.MACHINE, RsyncCopier.class);
+    private static final Logger machineLog = LogFactory.getLogger(LogCategory.MACHINE,
+            RsyncCopier.class);
 
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, RsyncCopier.class);
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            RsyncCopier.class);
 
     /**
      * The {@link Status} returned if the process was terminated by {@link Process#destroy()}.
@@ -63,11 +63,11 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
     @Private
     static final Status TERMINATED_STATUS = Status.createRetriableError("Process was terminated.");
 
-    private static final Status INTERRUPTED_STATUS =
-            Status.createRetriableError("Process was interrupted.");
+    private static final Status INTERRUPTED_STATUS = Status
+            .createRetriableError("Process was interrupted.");
 
-    private static final Status TIMEOUT_STATUS =
-            Status.createRetriableError("Process has stopped because of timeout.");
+    private static final Status TIMEOUT_STATUS = Status
+            .createRetriableError("Process has stopped because of timeout.");
 
     private final String rsyncExecutable;
 
@@ -103,7 +103,10 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
 
     private final String sshExecutable;
 
-    private final List<String> additionalCmdLineFlags;
+    private final List<String> additionalCmdLineFlagsOrNull;
+    
+    /** If set, overrides all command line parameters for mutable copying. */
+    private final List<String> cmdLineFlagsOrNull;
 
     private final boolean overwrite;
 
@@ -127,6 +130,30 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
         this(rsyncExecutable, null, false, false);
     }
 
+    /**
+     * Constructs an <code>RsyncCopier</code> with fully custom command line flags.
+     * 
+     * @param rsyncExecutable The <code>rsync</code> binary to call for copying.
+     * @param sshExecutableOrNull The <code>ssh</code> binary to use for creating tunnels, or
+     *            <code>null</code>, if no <code>ssh</code> is available on this machine.
+     * @param cmdLineFlags The command line flags to use for the rsync command.
+     */
+    public RsyncCopier(final File rsyncExecutable, final File sshExecutableOrNull,
+            String... cmdLineFlags)
+    {
+        assert rsyncExecutable != null && rsyncExecutable.exists();
+        assert sshExecutableOrNull == null || rsyncExecutable.exists();
+
+        this.rsyncExecutable = rsyncExecutable.getAbsolutePath();
+        this.rsyncVersion = RsyncVersionChecker.getVersion(rsyncExecutable.getAbsolutePath());
+        this.sshExecutable = (sshExecutableOrNull != null) ? sshExecutableOrNull.getPath() : null;
+        this.rsyncTerminator = new AtomicReference<ITerminable>(null);
+        this.overwrite = false;
+        this.destinationDirectoryRequiresDeletionBeforeCreation = false;
+        this.additionalCmdLineFlagsOrNull = null;
+        this.cmdLineFlagsOrNull = Arrays.asList(cmdLineFlags);
+    }
+
     /**
      * Constructs an <code>RsyncCopier</code>.
      * 
@@ -153,11 +180,12 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
         this.rsyncTerminator = new AtomicReference<ITerminable>(null);
         if (cmdLineFlags.length > 0)
         {
-            this.additionalCmdLineFlags = Arrays.asList(cmdLineFlags);
+            this.additionalCmdLineFlagsOrNull = Arrays.asList(cmdLineFlags);
         } else
         {
-            this.additionalCmdLineFlags = null;
+            this.additionalCmdLineFlagsOrNull = null;
         }
+        this.cmdLineFlagsOrNull = null;
     }
 
     private boolean rsyncSupportsAppend(RsyncVersion versionOrNull)
@@ -237,8 +265,10 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
         assert destinationDirectory.isDirectory() : destinationDirectory.getAbsolutePath();
 
         final List<String> commandLine =
-                createCommandLineForImmutableCopy(sourceDirectory, createTargetDirectory(
-                        sourceDirectory, destinationDirectory, targetNameOrNull));
+                createCommandLineForImmutableCopy(
+                        sourceDirectory,
+                        createTargetDirectory(sourceDirectory, destinationDirectory,
+                                targetNameOrNull));
         final ProcessResult processResult =
                 runCommand(commandLine, ProcessExecutionHelper.DEFAULT_OUTPUT_READING_STRATEGY);
         return processResult.isOK();
@@ -329,8 +359,8 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
         }
         if (rsyncVersion.isRsyncPreReleaseVersion())
         {
-            machineLog.warn(String
-                    .format(
+            machineLog
+                    .warn(String.format(
                             "The rsync executable '%s' is a pre-release version. It is not recommended "
                                     + "to use such a version in a production environment.",
                             rsyncExecutable));
@@ -425,12 +455,13 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
         {
             if (result.getOutput().size() == 0)
             {
-                machineLog.warn(String.format("No output on command '%s'.", StringUtils.join(
-                        commandLineList, ' ')));
+                machineLog.warn(String.format("No output on command '%s'.",
+                        StringUtils.join(commandLineList, ' ')));
             } else
             {
-                machineLog.warn(String.format("Unexpected output on command '%s':\n%s", StringUtils
-                        .join(commandLineList, ' '), StringUtils.join(result.getOutput(), '\n')));
+                machineLog.warn(String.format("Unexpected output on command '%s':\n%s",
+                        StringUtils.join(commandLineList, ' '),
+                        StringUtils.join(result.getOutput(), '\n')));
             }
         }
         if (result.isOK() && result.getOutput().size() == 1)
@@ -485,19 +516,25 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
                 || (destinationHostOrNull == null);
         assert (sourceHostOrNull != null && sshExecutable != null) || (sourceHostOrNull == null);
 
-        final List<String> standardParameters = Arrays.asList("--archive", "--delete", "--inplace");
         final List<String> commandLineList = new ArrayList<String>();
         final RsyncRecord remoteRsyncOrNull =
                 tryGetRemoteRsync(sourceHostOrNull, destinationHostOrNull);
-
         commandLineList.add(rsyncExecutable);
-        commandLineList.addAll(standardParameters);
-        if (isOverwriteMode(remoteRsyncOrNull))
+        if (cmdLineFlagsOrNull != null)
         {
-            commandLineList.add("--whole-file");
+            commandLineList.addAll(cmdLineFlagsOrNull);
         } else
         {
-            commandLineList.add("--append");
+            final List<String> standardParameters = Arrays.asList("--archive", "--delete", "--inplace");
+    
+            commandLineList.addAll(standardParameters);
+            if (isOverwriteMode(remoteRsyncOrNull))
+            {
+                commandLineList.add("--whole-file");
+            } else
+            {
+                commandLineList.add("--append");
+            }
         }
         if (sshExecutable != null && (destinationHostOrNull != null || sourceHostOrNull != null)
                 && rsyncModuleNameOrNull == null)
@@ -516,9 +553,9 @@ public final class RsyncCopier implements IPathCopier, IDirectoryImmutableCopier
             commandLineList.add("--password-file");
             commandLineList.add(rsyncPasswordFileOrNull);
         }
-        if (additionalCmdLineFlags != null)
+        if (additionalCmdLineFlagsOrNull != null)
         {
-            commandLineList.addAll(additionalCmdLineFlags);
+            commandLineList.addAll(additionalCmdLineFlagsOrNull);
         }
         commandLineList.add(buildPath(sourceHostOrNull, sourcePath, rsyncModuleNameOrNull,
                 copyDirectoryContent));
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java
index 2ef3343cc012f421fc797e6e6f45652078b14a51..ec8932aca9ece271bb55c9ad2e1cf2e0b3e94a95 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/rsync/RsyncCopierTest.java
@@ -53,13 +53,13 @@ import ch.systemsx.cisd.common.test.StoringUncaughtExceptionHandler;
 @Friend(toClasses = RsyncCopier.class)
 public final class RsyncCopierTest
 {
-    private static final Logger operationLog =
-            LogFactory.getLogger(LogCategory.OPERATION, RsyncCopierTest.class);
+    private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
+            RsyncCopierTest.class);
 
     private static final long SLEEP_MILLIS = 1000L;
 
-    private static final File unitTestRootDirectory =
-            new File("targets" + File.separator + "unit-test-wd");
+    private static final File unitTestRootDirectory = new File("targets" + File.separator
+            + "unit-test-wd");
 
     private static final File workingDirectory = new File(unitTestRootDirectory, "RsyncCopierTest");
 
@@ -128,8 +128,8 @@ public final class RsyncCopierTest
         final File rsyncBinary = new File(workingDirectory, "rsync");
         rsyncBinary.delete();
         final List<String> lines = new ArrayList<String>();
-        lines.addAll(Arrays.asList("#! /bin/sh", "if [ \"$1\" = \"--version\" ]; then ", String
-                .format("  echo \"rsync  version %s\"", rsyncVersion), "exit 0", "fi"));
+        lines.addAll(Arrays.asList("#! /bin/sh", "if [ \"$1\" = \"--version\" ]; then ",
+                String.format("  echo \"rsync  version %s\"", rsyncVersion), "exit 0", "fi"));
         lines.addAll(Arrays.asList(additionalLines));
         CollectionIO.writeIterable(rsyncBinary, lines);
         Runtime.getRuntime().exec(String.format("/bin/chmod +x %s", rsyncBinary.getPath()))
@@ -156,6 +156,40 @@ public final class RsyncCopierTest
         assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine.size() - 1));
     }
 
+    @Test
+    public void testCommandLineForMutableCopyLocalNoOwnerNoGroup() throws IOException,
+            InterruptedException
+    {
+        final File rsyncBinary = createRsync(0);
+        final RsyncCopier copier =
+                new RsyncCopier(rsyncBinary, rsyncBinary, false, false, "--no-owner", "--no-group");
+        final List<String> cmdLine =
+                copier.createCommandLineForMutableCopy(sourceDirectory, null, destinationDirectory,
+                        null, null, null, false);
+        assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0));
+        assertEquals("--no-owner", cmdLine.get(cmdLine.size() - 4));
+        assertEquals("--no-group", cmdLine.get(cmdLine.size() - 3));
+        assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(cmdLine.size() - 2));
+        assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(cmdLine.size() - 1));
+    }
+
+    @Test
+    public void testCommandLineForMutableCopyCustomParameters() throws IOException,
+            InterruptedException
+    {
+        final File rsyncBinary = createRsync(0);
+        final RsyncCopier copier =
+                new RsyncCopier(rsyncBinary, rsyncBinary, "--archive", "--no-perms");
+        final List<String> cmdLine =
+                copier.createCommandLineForMutableCopy(sourceDirectory, null, destinationDirectory,
+                        null, null, null, false);
+        assertEquals(rsyncBinary.getAbsolutePath(), cmdLine.get(0));
+        assertEquals("--archive", cmdLine.get(1));
+        assertEquals("--no-perms", cmdLine.get(2));
+        assertEquals(sourceDirectory.getAbsolutePath(), cmdLine.get(3));
+        assertEquals(destinationDirectory.getAbsolutePath() + "/", cmdLine.get(4));
+    }
+
     @Test
     public void testCommandLineForMutableCopyLocalContentRatherThanDirectory() throws IOException,
             InterruptedException
@@ -332,14 +366,14 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.7", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.7",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, false);
         final Status status = copier.copy(sourceDirectory, destinationDirectory);
         assertEquals(Status.OK, status);
         final String expectedRsyncCmdLine =
-                String.format("--archive --delete --inplace --append %s %s/\n", sourceDirectory
-                        .getAbsolutePath(), destinationDirectory.getAbsolutePath());
+                String.format("--archive --delete --inplace --append %s %s/\n",
+                        sourceDirectory.getAbsolutePath(), destinationDirectory.getAbsolutePath());
         final String observedRsyncCmdLine = FileUtilities.loadToString(parametersLogFile);
         assertEquals(expectedRsyncCmdLine, observedRsyncCmdLine);
     }
@@ -350,14 +384,14 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.7", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.7",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, false);
         final Status status = copier.copyContent(sourceDirectory, destinationDirectory);
         assertEquals(Status.OK, status);
         final String expectedRsyncCmdLine =
-                String.format("--archive --delete --inplace --append %s/ %s/\n", sourceDirectory
-                        .getAbsolutePath(), destinationDirectory.getAbsolutePath());
+                String.format("--archive --delete --inplace --append %s/ %s/\n",
+                        sourceDirectory.getAbsolutePath(), destinationDirectory.getAbsolutePath());
         final String observedRsyncCmdLine = FileUtilities.loadToString(parametersLogFile);
         assertEquals(expectedRsyncCmdLine, observedRsyncCmdLine);
     }
@@ -368,8 +402,8 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.7", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.7",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, false);
         assertTrue(copier.copyDirectoryImmutably(sourceDirectory, destinationDirectory, null));
         final String absWd = workingDirectory.getAbsolutePath();
@@ -385,8 +419,8 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.7", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.7",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, false);
         final String name = "xxx";
         assertTrue(copier.copyDirectoryImmutably(sourceDirectory, destinationDirectory, name));
@@ -443,8 +477,8 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.7", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.7",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, false);
         copier.copy(sourceFile, destinationDirectory);
         final String rsyncParameters = FileUtilities.loadToString(parametersLogFile);
@@ -458,8 +492,8 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.6", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.6",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, false);
         copier.copy(sourceFile, destinationDirectory);
         final String rsyncParameters = FileUtilities.loadToString(parametersLogFile);
@@ -473,8 +507,8 @@ public final class RsyncCopierTest
     {
         final File parametersLogFile = new File(workingDirectory, "parameters.log");
         final File loggingRsyncBinary =
-                createRsync("2.6.7", String.format("echo \"$@\" > %s", parametersLogFile
-                        .getAbsolutePath()));
+                createRsync("2.6.7",
+                        String.format("echo \"$@\" > %s", parametersLogFile.getAbsolutePath()));
         final RsyncCopier copier = new RsyncCopier(loggingRsyncBinary, null, false, true);
         copier.copy(sourceFile, destinationDirectory);
         final String rsyncParameters = FileUtilities.loadToString(parametersLogFile);