diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/StorageProcessor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/StorageProcessor.java
index 49407936743429cdbbf7ed0883d3e152292a41bf..69a7c600f35589443dacaaf7085cea30073e9020 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/StorageProcessor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/StorageProcessor.java
@@ -19,7 +19,6 @@ package ch.systemsx.cisd.cina.dss;
 import java.io.File;
 import java.util.Properties;
 
-import ch.systemsx.cisd.cina.dss.info.EntityRegistrationSuccessEmail;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.etlserver.AbstractDelegatingStorageProcessor;
 import ch.systemsx.cisd.etlserver.IStorageProcessor;
@@ -35,18 +34,9 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
  */
 public class StorageProcessor extends AbstractDelegatingStorageProcessor
 {
-    private String defaultEmailAddress = "root@localhost";
-
-    private static final String DEFAULT_EMAIL_ADDRESS_KEY = "default-email";
-
     public StorageProcessor(Properties properties)
     {
         super(properties);
-
-        if (properties.containsKey(DEFAULT_EMAIL_ADDRESS_KEY))
-        {
-            defaultEmailAddress = properties.getProperty(DEFAULT_EMAIL_ADDRESS_KEY);
-        }
     }
 
     public StorageProcessor(IStorageProcessor delegatedProcessor)
@@ -59,25 +49,10 @@ public class StorageProcessor extends AbstractDelegatingStorageProcessor
             final ITypeExtractor typeExtractor, final IMailClient mailClient,
             final File incomingDataSetDirectory, final File rootDir)
     {
-        // Create the email first because the email looks into the directory to determine its
-        // content.
-        EntityRegistrationSuccessEmail successEmail =
-                new EntityRegistrationSuccessEmail(dataSetInformation, incomingDataSetDirectory);
-
         File answer =
                 super.storeData(dataSetInformation, typeExtractor, mailClient,
                         incomingDataSetDirectory, rootDir);
 
-        String emailAddress = dataSetInformation.tryGetUploadingUserEmail();
-        if (emailAddress == null)
-        {
-            emailAddress = defaultEmailAddress;
-        }
-
-        mailClient.sendMessageWithAttachment(successEmail.getSubject(), successEmail
-                .getContentMimeText(), successEmail.getContentMimeAttachmentFileName(),
-                successEmail.getContentMimeAttachmentContent(), null, null, emailAddress);
-
         return answer;
     }
 
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/BundleDataSetHelper.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/BundleDataSetHelper.java
new file mode 100644
index 0000000000000000000000000000000000000000..5dd523fbb1b6e5745dbe4bb26653cf523d53a728
--- /dev/null
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/BundleDataSetHelper.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright 2010 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.cina.dss.bundle;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import ch.systemsx.cisd.cina.shared.metadata.BundleMetadataExtractor;
+import ch.systemsx.cisd.cina.shared.metadata.ImageMetadataExtractor;
+import ch.systemsx.cisd.cina.shared.metadata.ReplicaMetadataExtractor;
+import ch.systemsx.cisd.etlserver.IDataSetHandler;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetTypeWithVocabularyTerms;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.NewSample;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+import ch.systemsx.cisd.openbis.generic.shared.dto.identifier.SampleIdentifier;
+
+/**
+ * Helper class for processing bundle data sets.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+class BundleDataSetHelper
+{
+    static class BundleRegistrationGlobalState
+    {
+        private final IDataSetHandler delegator;
+
+        private final IEncapsulatedOpenBISService openbisService;
+
+        private final SampleType replicaSampleType;
+
+        private final DataSetTypeWithVocabularyTerms imageDataSetType;
+
+        BundleRegistrationGlobalState(IDataSetHandler delegator,
+                IEncapsulatedOpenBISService openbisService, SampleType replicaSampleType,
+                DataSetTypeWithVocabularyTerms imageDataSetType)
+        {
+            this.delegator = delegator;
+            this.openbisService = openbisService;
+            this.replicaSampleType = replicaSampleType;
+            this.imageDataSetType = imageDataSetType;
+        }
+
+        IDataSetHandler getDelegator()
+        {
+            return delegator;
+        }
+
+        IEncapsulatedOpenBISService getOpenbisService()
+        {
+            return openbisService;
+        }
+
+        SampleType getReplicaSampleType()
+        {
+            return replicaSampleType;
+        }
+
+        DataSetTypeWithVocabularyTerms getImageDataSetType()
+        {
+            return imageDataSetType;
+        }
+    }
+
+    private final BundleRegistrationGlobalState globalState;
+
+    // Invocation-specific State
+    private final String sessionOwnerUserId;
+
+    private final File dataSet;
+
+    private final ArrayList<DataSetInformation> dataSetInformation;
+
+    BundleDataSetHelper(BundleRegistrationGlobalState globalState, String sessionOwnerUserId,
+            File dataSet)
+    {
+        this.globalState = globalState;
+        this.sessionOwnerUserId = sessionOwnerUserId;
+        this.dataSet = dataSet;
+        this.dataSetInformation = new ArrayList<DataSetInformation>();
+    }
+
+    /**
+     *
+     */
+    public void process()
+    {
+        // Register the bundle as one data set
+        List<DataSetInformation> bigDataSet = getDelegator().handleDataSet(dataSet);
+        dataSetInformation.addAll(bigDataSet);
+        if (dataSetInformation.isEmpty())
+        {
+            return;
+        }
+
+        BundleMetadataExtractor bundleMetadata = new BundleMetadataExtractor(dataSet);
+        for (ReplicaMetadataExtractor replicaMetadata : bundleMetadata.getMetadataExtractors())
+        {
+            handleDerivedDataSets(replicaMetadata);
+        }
+    }
+
+    /**
+     * Get all the data set information that has been created as a result of {@link #process}. Only
+     * makes sense to invoke after process has been called
+     */
+    public ArrayList<DataSetInformation> getDataSetInformation()
+    {
+        return dataSetInformation;
+    }
+
+    private void handleDerivedDataSets(ReplicaMetadataExtractor replicaMetadata)
+    {
+        SampleType replicaSampleType = globalState.getReplicaSampleType();
+        long sampleCodeSuffix = getOpenbisService().drawANewUniqueID();
+        String sampleCode =
+                String.format("%s%d", replicaSampleType.getGeneratedCodePrefix(), sampleCodeSuffix);
+        SampleIdentifier parentIdentifier = getBigDataSetInformation().getSampleIdentifier();
+
+        // Register a sample with this ID of type GRID_REPLICA, derived from the GRID_TEMPLATE
+        // registered by the client
+        SampleIdentifier identifier =
+                new SampleIdentifier(parentIdentifier.getSpaceLevel(), sampleCode);
+        NewSample sample =
+                new NewSample(identifier.toString(), replicaSampleType,
+                        parentIdentifier.toString(), "");
+        getOpenbisService().registerSample(sample, sessionOwnerUserId);
+
+        // Register all the data sets derived from this sample
+        for (ImageMetadataExtractor imageMetadata : replicaMetadata.getMetadataExtractors())
+        {
+            handleDerivedDataSet(identifier.toString(), imageMetadata);
+        }
+    }
+
+    private void handleDerivedDataSet(String sampleId, ImageMetadataExtractor imageMetadata)
+    {
+        // Register a data set for the image
+
+    }
+
+    /**
+     * Get the "big data set" -- the one that is the parent of all the derived data sets I register
+     */
+    private DataSetInformation getBigDataSetInformation()
+    {
+        // The big data set is the first one registered.
+        return dataSetInformation.get(0);
+    }
+
+    private IDataSetHandler getDelegator()
+    {
+        return globalState.getDelegator();
+    }
+
+    private IEncapsulatedOpenBISService getOpenbisService()
+    {
+        return globalState.getOpenbisService();
+    }
+}
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleDataSetHandler.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleDataSetHandler.java
new file mode 100644
index 0000000000000000000000000000000000000000..ed4a7ea77045b6de1e3d8111b674781360c2bf34
--- /dev/null
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleDataSetHandler.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2010 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.cina.dss.bundle;
+
+import java.io.File;
+import java.util.List;
+import java.util.Properties;
+
+import ch.systemsx.cisd.cina.dss.bundle.BundleDataSetHelper.BundleRegistrationGlobalState;
+import ch.systemsx.cisd.cina.shared.constants.CinaConstants;
+import ch.systemsx.cisd.etlserver.IDataSetHandler;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetTypeWithVocabularyTerms;
+import ch.systemsx.cisd.openbis.generic.shared.basic.dto.SampleType;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class CinaBundleDataSetHandler implements IDataSetHandler
+{
+    private final IDataSetHandler delegator;
+
+    private final IEncapsulatedOpenBISService openbisService;
+
+    private final BundleRegistrationGlobalState bundleRegistrationGlobalState;
+
+    public CinaBundleDataSetHandler(Properties parentProperties, IDataSetHandler delegator,
+            IEncapsulatedOpenBISService openbisService)
+    {
+        this.delegator = delegator;
+        this.openbisService = openbisService;
+        this.bundleRegistrationGlobalState = createBundleRegistrationGlobalState();
+    }
+
+    public List<DataSetInformation> handleDataSet(File dataSet)
+    {
+        BundleDataSetHelper helper =
+                new BundleDataSetHelper(bundleRegistrationGlobalState, null, dataSet);
+        helper.process();
+        return helper.getDataSetInformation();
+    }
+
+    private BundleRegistrationGlobalState createBundleRegistrationGlobalState()
+    {
+        SampleType replicaSampleType =
+                openbisService.getSampleType(CinaConstants.REPLICA_SAMPLE_TYPE_CODE);
+        DataSetTypeWithVocabularyTerms imageDataSetType =
+                openbisService.getDataSetType(CinaConstants.IMAGE_DATA_SET_TYPE_CODE);
+        return new BundleRegistrationGlobalState(delegator, openbisService, replicaSampleType,
+                imageDataSetType);
+    }
+}
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaDataSetInfoExtractor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleDataSetInfoExtractor.java
similarity index 82%
rename from rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaDataSetInfoExtractor.java
rename to rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleDataSetInfoExtractor.java
index 058b8d0ff31c0370cb19f924cc9cb8973eacaa4b..f4cf67236ec655df0594b1bcc85a88cacdbeae11 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaDataSetInfoExtractor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleDataSetInfoExtractor.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.cina.dss.bundle;
 
 import java.io.File;
+import java.util.Properties;
 
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
@@ -29,14 +30,19 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
  * 
  * @author Chandrasekhar Ramakrishnan
  */
-public class CinaDataSetInfoExtractor implements IDataSetInfoExtractor
+public class CinaBundleDataSetInfoExtractor implements IDataSetInfoExtractor
 {
+    public CinaBundleDataSetInfoExtractor(final Properties globalProperties)
+    {
+
+    }
 
     public DataSetInformation getDataSetInformation(File incomingDataSetPath,
             IEncapsulatedOpenBISService openbisService) throws UserFailureException,
             EnvironmentFailureException
     {
-        return new DataSetInformation();
-    }
+        DataSetInformation result = new DataSetInformation();
 
+        return result;
+    }
 }
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaTypeExtractor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleTypeExtractor.java
similarity index 83%
rename from rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaTypeExtractor.java
rename to rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleTypeExtractor.java
index c0aae4be07f608a9d05a883a1a5bba82ad642b96..cbf21e7c10f37396e9fa7f4a91794ea6d505b2aa 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaTypeExtractor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/bundle/CinaBundleTypeExtractor.java
@@ -17,7 +17,9 @@
 package ch.systemsx.cisd.cina.dss.bundle;
 
 import java.io.File;
+import java.util.Properties;
 
+import ch.systemsx.cisd.cina.shared.constants.CinaConstants;
 import ch.systemsx.cisd.etlserver.ITypeExtractor;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.DataSetType;
 import ch.systemsx.cisd.openbis.generic.shared.basic.dto.FileFormatType;
@@ -26,13 +28,16 @@ import ch.systemsx.cisd.openbis.generic.shared.basic.dto.LocatorType;
 /**
  * @author Chandrasekhar Ramakrishnan
  */
-public class CinaTypeExtractor implements ITypeExtractor
+public class CinaBundleTypeExtractor implements ITypeExtractor
 {
-    private static final String BUNDLE_DATA_SET_TYPE = "BUNDLE";
+    public CinaBundleTypeExtractor(final Properties properties)
+    {
+
+    }
 
     public DataSetType getDataSetType(File incomingDataSetPath)
     {
-        return new DataSetType(BUNDLE_DATA_SET_TYPE);
+        return new DataSetType(CinaConstants.BUNDLE_DATA_SET_TYPE_CODE);
     }
 
     public FileFormatType getFileFormatType(File incomingDataSetPath)
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/info/CinaDataSetInfoExtractor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/info/CinaDataSetInfoExtractor.java
index 31d7f5c8d1115dd9504e5014a50d20f99990a3df..6f9752cfcc7288cdd8685a83244f28c5aa87a849 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/info/CinaDataSetInfoExtractor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/dss/info/CinaDataSetInfoExtractor.java
@@ -36,7 +36,7 @@ import ch.systemsx.cisd.openbis.dss.generic.shared.dto.DataSetInformation;
 
 /**
  * CINA uses the data store server to register experiments and samples in addition to data sets. The
- * CinaDataSetInfoExtractor follows the conventions agreed to by the CINA project to determine if
+ * CinaBundleDataSetInfoExtractor follows the conventions agreed to by the CINA project to determine if
  * the file represents an experiment, sample, or data set and takes according action.
  * <p>
  * In the case of data representing experiments and samples, the extractor may need to register the
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/constants/CinaConstants.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/constants/CinaConstants.java
new file mode 100644
index 0000000000000000000000000000000000000000..ffdc760ba7b4387864f71795e1ea4bd17563a348
--- /dev/null
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/constants/CinaConstants.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2010 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.cina.shared.constants;
+
+/**
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class CinaConstants
+{
+    public static final String BUNDLE_DATA_SET_TYPE_CODE = "BUNDLE";
+
+    public static final String IMAGE_DATA_SET_TYPE_CODE = "IMAGE";
+
+    public final static String REPLICA_SAMPLE_TYPE_CODE = "GRID_REPLICA";
+
+    public static final String DIMENSION_PREFIX = "Dimension";
+
+    public static final String SIZE_PREFIX = "Size";
+
+    // No need to instantiate this class
+    private CinaConstants()
+    {
+
+    }
+}
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ImageMetadataExtractor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ImageMetadataExtractor.java
index b0383e3b7894d269fc078ce0be41b8c893306e08..96c8934c9e3e4d9608a37970aa6f454fd3d5f25e 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ImageMetadataExtractor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ImageMetadataExtractor.java
@@ -20,6 +20,7 @@ import java.io.File;
 import java.util.HashMap;
 import java.util.Map;
 
+import ch.systemsx.cisd.cina.shared.constants.CinaConstants;
 import ch.systemsx.cisd.cina.shared.labview.LVData;
 import ch.systemsx.cisd.cina.shared.labview.LVDataParser;
 
@@ -36,14 +37,14 @@ public class ImageMetadataExtractor
 
     private LVData lvdata;
 
-    private static final String METADATA_FILE_NAME = "metadata.xml";
+    private final static String METADATA_FILE_NAME = "metadata.xml";
 
-    private static final HashMap<String, String> prefixMap;
+    private final static HashMap<String, String> prefixMap;
     static
     {
         prefixMap = new HashMap<String, String>();
-        prefixMap.put("Pixelsize (nm)", "Size");
-        prefixMap.put("Image dimension (px)", "Dimension");
+        prefixMap.put("Pixelsize (nm)", CinaConstants.SIZE_PREFIX);
+        prefixMap.put("Image dimension (px)", CinaConstants.DIMENSION_PREFIX);
     }
 
     public static boolean doesFolderContainImageMetadata(File folder)
@@ -108,6 +109,11 @@ public class ImageMetadataExtractor
         return metadataMap;
     }
 
+    public File getFolder()
+    {
+        return folder;
+    }
+
     private void checkPrepared()
     {
         assert lvdata != null;
diff --git a/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ReplicaMetadataExtractor.java b/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ReplicaMetadataExtractor.java
index 378c7e38bd757a540ee93afea366b7ab8b718fab..938d6c561ae3f9a7dca01efbeb9201f3f8bfce29 100644
--- a/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ReplicaMetadataExtractor.java
+++ b/rtd_cina/source/java/ch/systemsx/cisd/cina/shared/metadata/ReplicaMetadataExtractor.java
@@ -118,6 +118,11 @@ public class ReplicaMetadataExtractor
         return metadataExtractors;
     }
 
+    public File getFolder()
+    {
+        return folder;
+    }
+
     private void checkPrepared()
     {
         assert lvdata != null;