diff --git a/deep_sequencing_unit/.classpath b/deep_sequencing_unit/.classpath
index 417fb1931958ed5f1692dab880073df47f1735a2..238c07c192773c1b5d8f0336c43075d687d8de07 100644
--- a/deep_sequencing_unit/.classpath
+++ b/deep_sequencing_unit/.classpath
@@ -6,5 +6,7 @@
 	<classpathentry combineaccessrules="false" kind="src" path="/datastore_server"/>
 	<classpathentry combineaccessrules="false" kind="src" path="/common"/>
 	<classpathentry kind="lib" path="/libraries/testng/testng-jdk15.jar" sourcepath="/libraries/testng/src.zip"/>
+	<classpathentry kind="lib" path="/libraries/cisd-base/cisd-base-test.jar" sourcepath="/libraries/cisd-base/cisd-base-src.zip"/>
+	<classpathentry kind="lib" path="/libraries/cisd-base/cisd-base.jar" sourcepath="/libraries/cisd-base/cisd-base-src.zip"/>
 	<classpathentry kind="output" path="targets/classes"/>
 </classpath>
diff --git a/deep_sequencing_unit/dist/etc/service.properties b/deep_sequencing_unit/dist/etc/service.properties
index 6210f2c083487950f3a8eea753cdb4ade39c798b..fdf1278cd0cf065be4aecd58da59bdac351bd548 100644
--- a/deep_sequencing_unit/dist/etc/service.properties
+++ b/deep_sequencing_unit/dist/etc/service.properties
@@ -124,3 +124,5 @@ flow-cell.type-extractor.is-measured = true
 # The storage processor (IStorageProcessor implementation)
 flow-cell.storage-processor = ch.ethz.bsse.cisd.dsu.dss.StorageProcessor
 flow-cell.storage-processor.processor = ch.systemsx.cisd.etlserver.DefaultStorageProcessor
+# Template of flow-line drop boxes. {0} is the place holder for flow line number
+flow-cell.storage-processor.flow-line-drop-box-template = data/drop-box-{0}
diff --git a/deep_sequencing_unit/etc/service.properties b/deep_sequencing_unit/etc/service.properties
index b973b46b7e70c1379ca5350fbaa75b417d58c567..9a0d8770e48bcfed6b99fad5ac835c838f79e067 100644
--- a/deep_sequencing_unit/etc/service.properties
+++ b/deep_sequencing_unit/etc/service.properties
@@ -124,3 +124,4 @@ flow-cell.type-extractor.is-measured = true
 # The storage processor (IStorageProcessor implementation)
 flow-cell.storage-processor = ch.ethz.bsse.cisd.dsu.dss.StorageProcessor
 flow-cell.storage-processor.processor = ch.systemsx.cisd.etlserver.DefaultStorageProcessor
+flow-cell.storage-processor.flow-line-drop-box-template = targets/playground/drop-box-{0}
diff --git a/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java b/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java
index a06534e63e903ee5ffa0847372ed0d3310cca891..18bd8ea30ac0d25046c2ad4a1e3233cb9543cdcc 100644
--- a/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java
+++ b/deep_sequencing_unit/source/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeeder.java
@@ -22,8 +22,13 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Properties;
 
+import ch.systemsx.cisd.common.TimingParameters;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
+import ch.systemsx.cisd.common.filesystem.FastRecursiveHardLinkMaker;
+import ch.systemsx.cisd.common.filesystem.FileOperations;
+import ch.systemsx.cisd.common.filesystem.IFileOperations;
+import ch.systemsx.cisd.common.filesystem.IImmutableCopier;
 import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.openbis.dss.generic.shared.IPostRegistrationDatasetHandler;
 import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
@@ -39,17 +44,21 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler
     static final String FILE_TYPE = ".srf";
     
     private final MessageFormat flowLineDropBoxTemplate;
+    private final IImmutableCopier copier;
+    private final IFileOperations fileOperations;
+    private final List<File> flowLineDataSets = new ArrayList<File>();
     
     FlowLineFeeder(Properties properties)
     {
         flowLineDropBoxTemplate =
                 new MessageFormat(PropertyUtils.getMandatoryProperty(properties,
                         FLOW_LINE_DROP_BOX_TEMPLATE));
+        copier = FastRecursiveHardLinkMaker.tryCreate(TimingParameters.getDefaultParameters());
+        fileOperations = FileOperations.getInstance();
     }
 
     public void handle(File originalData, DataSetInformation dataSetInformation)
     {
-        System.out.println("FlowLineFeeder.handle(): "+originalData+" "+dataSetInformation);
         String flowcellID = originalData.getName();
         List<File> files = new ArrayList<File>();
         findFiles(originalData, files);
@@ -58,20 +67,27 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler
             String flowLine = extractFlowLine(file);
             File dropBox = createDropBoxFile(flowLine);
             File flowLineDataSet = new File(dropBox, flowcellID + "_" + flowLine);
+            flowLineDataSets.add(flowLineDataSet);
             boolean success = flowLineDataSet.mkdir();
             if (success == false)
             {
                 throw new EnvironmentFailureException("Couldn't create folder '"
                         + flowLineDataSet.getAbsolutePath() + "'.");
             }
-            
+            success = copier.copyImmutably(file, flowLineDataSet, null);
+            if (success == false)
+            {
+                throw new EnvironmentFailureException("Couldn't create a hard-link copy of '"
+                        + file.getAbsolutePath() + "' in folder '"
+                        + flowLineDataSet.getAbsolutePath() + "'.");
+            }
         }
 
     }
 
     private File createDropBoxFile(String flowLine)
     {
-        File dropBox = new File(flowLineDropBoxTemplate.format(flowLine));
+        File dropBox = new File(flowLineDropBoxTemplate.format(new Object[] {flowLine}));
         if (dropBox.exists() == false)
         {
             throw new ConfigurationFailureException("Drop box '" + dropBox + "' does not exist.");
@@ -86,12 +102,7 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler
     private String extractFlowLine(File file)
     {
         String name = file.getName();
-        int lastIndexOfDot = name.lastIndexOf('.');
-        String nameWithoutType = name;
-        if (lastIndexOfDot >= 0)
-        {
-            nameWithoutType = name.substring(0, lastIndexOfDot);
-        }
+        String nameWithoutType = name.substring(0, name.lastIndexOf('.'));
         int lastIndexOfUnderScore = nameWithoutType.lastIndexOf('_');
         String flowLine = nameWithoutType;
         if (lastIndexOfUnderScore >= 0)
@@ -118,7 +129,10 @@ class FlowLineFeeder implements IPostRegistrationDatasetHandler
 
     public void undoLastOperation()
     {
-        System.out.println("FlowLineFeeder.undoLastOperation()");
+        for (File file : flowLineDataSets)
+        {
+            fileOperations.deleteRecursively(file);
+        }
     }
 
 }
diff --git a/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java b/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java
new file mode 100644
index 0000000000000000000000000000000000000000..1c728db677aeea052ce4d920b7cf2b4020e6ed59
--- /dev/null
+++ b/deep_sequencing_unit/sourceTest/java/ch/ethz/bsse/cisd/dsu/dss/FlowLineFeederTest.java
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2009 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.ethz.bsse.cisd.dsu.dss;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Properties;
+
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import ch.systemsx.cisd.base.tests.AbstractFileSystemTestCase;
+import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
+import ch.systemsx.cisd.common.test.AssertionUtil;
+
+/**
+ * 
+ *
+ * @author Franz-Josef Elmer
+ */
+public class FlowLineFeederTest extends AbstractFileSystemTestCase
+{
+    private static final String DROP_BOX_PREFIX = "drop-box-";
+    private FlowLineFeeder flowLineFeeder;
+
+    @Override
+    @BeforeMethod
+    public void setUp() throws IOException
+    {
+        super.setUp();
+        assertEquals(true, new File(workingDirectory, DROP_BOX_PREFIX + "1").mkdirs());
+        assertEquals(true, new File(workingDirectory, DROP_BOX_PREFIX + "2").mkdirs());
+        Properties properties = new Properties();
+        properties.setProperty(FlowLineFeeder.FLOW_LINE_DROP_BOX_TEMPLATE, new File(
+                workingDirectory, DROP_BOX_PREFIX).getAbsolutePath()
+                + "{0}");
+        flowLineFeeder = new FlowLineFeeder(properties);
+    }
+    
+    @Test
+    public void testMissingProperty()
+    {
+        try
+        {
+            new FlowLineFeeder(new Properties());
+            fail("ConfigurationFailureException expected");
+        } catch (ConfigurationFailureException ex)
+        {
+            assertEquals("Given key '" + FlowLineFeeder.FLOW_LINE_DROP_BOX_TEMPLATE
+                    + "' not found in properties '[]'", ex.getMessage());
+        }
+    }
+    
+    @Test 
+    void testMissingDropBox()
+    {
+        File flowCell = new File(workingDirectory, "abc");
+        assertEquals(true, flowCell.mkdir());
+        FileUtilities.writeToFile(new File(flowCell, "s_3.srf"), "hello flow line 3");
+        
+        try
+        {
+            flowLineFeeder.handle(flowCell, null);
+            fail("ConfigurationFailureException expected");
+        } catch (ConfigurationFailureException ex)
+        {
+            AssertionUtil.assertContains(DROP_BOX_PREFIX + "3", ex.getMessage());
+        }
+    }
+    
+    @Test
+    public void testHappyCase()
+    {
+        File flowCell = new File(workingDirectory, "abc");
+        assertEquals(true, flowCell.mkdir());
+        File logs = new File(flowCell, "logs");
+        assertEquals(true, logs.mkdir());
+        FileUtilities.writeToFile(new File(logs, "basic.log"), "hello log");
+        File srfFolder = new File(flowCell, "SRF");
+        assertEquals(true, srfFolder.mkdir());
+        File originalFlowLine1 = new File(srfFolder, "s_1.srf");
+        FileUtilities.writeToFile(originalFlowLine1, "hello flow line 1");
+        File originalFlowLine2 = new File(srfFolder, "2.srf");
+        FileUtilities.writeToFile(originalFlowLine2, "hello flow line 2");
+
+        flowLineFeeder.handle(flowCell, null);
+        
+        checkFlowLineDataSet(originalFlowLine1, "1");
+        checkFlowLineDataSet(originalFlowLine2, "2");
+    }
+    
+    @Test
+    public void testUndoLastOperation()
+    {
+        testHappyCase();
+        assertEquals(1, new File(workingDirectory, DROP_BOX_PREFIX + "1").list().length);
+        assertEquals(1, new File(workingDirectory, DROP_BOX_PREFIX + "2").list().length);
+        
+        flowLineFeeder.undoLastOperation();
+        
+        assertEquals(0, new File(workingDirectory, DROP_BOX_PREFIX + "1").list().length);
+        assertEquals(0, new File(workingDirectory, DROP_BOX_PREFIX + "2").list().length);
+    }
+
+    private void checkFlowLineDataSet(File originalFlowLine, String flowLineNumber)
+    {
+        File dropBox = new File(workingDirectory, DROP_BOX_PREFIX + flowLineNumber);
+        File ds = new File(dropBox, "abc_" + flowLineNumber);
+        assertEquals(true, ds.isDirectory());
+
+        File flowLine = new File(ds, originalFlowLine.getName());
+        assertEquals(true, flowLine.isFile());
+        assertEquals(FileUtilities.loadToString(originalFlowLine), FileUtilities
+                .loadToString(flowLine));
+        // check hard-link copy by changing last-modified date of one file should change
+        // last-modified date of the other file.
+        originalFlowLine.setLastModified(4711000);
+        assertEquals(4711000, flowLine.lastModified());
+    }
+}