From 5a28903d731e7181ca08c1a718a6245619537a0f Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Tue, 11 Jan 2011 09:34:51 +0000
Subject: [PATCH] LMS-1966 Refactoring DSS to make alternate top-level data set
 handlers possible.

SVN: 19348
---
 .../AbstractTopLevelDataSetRegistrator.java   |  38 ++++++
 .../ch/systemsx/cisd/etlserver/ETLDaemon.java |  28 +++--
 .../etlserver/ETLServerPluginFactory.java     |  42 +++++++
 .../ITopLevelDataSetRegistrator.java          |  32 +++++
 .../cisd/etlserver/ThreadParameters.java      |  32 +++--
 ...TopLevelDataSetRegistratorGlobalState.java | 117 ++++++++++++++++++
 .../etlserver/TransferredDataSetHandler.java  | 107 ++++++++++------
 .../api/v1/DataSetTypeToPluginMapper.java     |  10 +-
 .../etlserver/api/v1/PutDataSetService.java   |   3 +-
 .../TransferredDataSetHandlerTest.java        |  37 ++++--
 10 files changed, 377 insertions(+), 69 deletions(-)
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractTopLevelDataSetRegistrator.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLServerPluginFactory.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/etlserver/ITopLevelDataSetRegistrator.java
 create mode 100644 datastore_server/source/java/ch/systemsx/cisd/etlserver/TopLevelDataSetRegistratorGlobalState.java

diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractTopLevelDataSetRegistrator.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractTopLevelDataSetRegistrator.java
new file mode 100644
index 00000000000..6eef219af4e
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/AbstractTopLevelDataSetRegistrator.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 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.etlserver;
+
+/**
+ * Abstract superclass for top level data set registrators.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public abstract class AbstractTopLevelDataSetRegistrator implements ITopLevelDataSetRegistrator
+{
+    private final TopLevelDataSetRegistratorGlobalState globalState;
+
+    protected AbstractTopLevelDataSetRegistrator(TopLevelDataSetRegistratorGlobalState globalState)
+    {
+        this.globalState = globalState;
+    }
+
+    public TopLevelDataSetRegistratorGlobalState getGlobalState()
+    {
+        return globalState;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLDaemon.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLDaemon.java
index 42b2ecfba2c..df8d9a56b9e 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLDaemon.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLDaemon.java
@@ -55,6 +55,7 @@ import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.mail.MailClient;
 import ch.systemsx.cisd.common.maintenance.MaintenanceTaskUtils;
+import ch.systemsx.cisd.common.utilities.ClassUtils;
 import ch.systemsx.cisd.common.utilities.IExitHandler;
 import ch.systemsx.cisd.common.utilities.ISelfTestable;
 import ch.systemsx.cisd.common.utilities.IStopSignaler;
@@ -276,8 +277,8 @@ public final class ETLDaemon
             final IDataSetValidator dataSetValidator, final boolean notifySuccessfulRegistration)
     {
         final File incomingDataDirectory = threadParameters.getIncomingDataDirectory();
-        final TransferredDataSetHandler pathHandler =
-                createDataSetHandler(parameters.getProperties(), threadParameters,
+        final ITopLevelDataSetRegistrator pathHandler =
+                createTopLevelDataSetRegistrator(parameters.getProperties(), threadParameters,
                         authorizedLimsService, mailClient, dataSetValidator,
                         notifySuccessfulRegistration);
         final HighwaterMarkDirectoryScanningHandler directoryScanningHandler =
@@ -298,23 +299,25 @@ public final class ETLDaemon
                 threadParameters.getThreadName());
     }
 
-    public static TransferredDataSetHandler createDataSetHandler(final Properties properties,
-            final ThreadParameters threadParameters,
+    public static ITopLevelDataSetRegistrator createTopLevelDataSetRegistrator(
+            final Properties properties, final ThreadParameters threadParameters,
             final IEncapsulatedOpenBISService openBISService, final IMailClient mailClient,
             final IDataSetValidator dataSetValidator, final boolean notifySuccessfulRegistration)
     {
-        final IETLServerPlugin plugin = threadParameters.getPlugin();
+        final IETLServerPlugin plugin = ETLServerPluginFactory.getPluginForThread(threadParameters);
         final File storeRootDir = DssPropertyParametersUtil.getStoreRootDir(properties);
         migrateStoreRootDir(storeRootDir, openBISService.getHomeDatabaseInstance());
         plugin.getStorageProcessor().setStoreRootDirectory(storeRootDir);
         String dssCode = DssPropertyParametersUtil.getDataStoreCode(properties);
-        boolean deleteUnidentified = threadParameters.deleteUnidentified();
+        TopLevelDataSetRegistratorGlobalState globalState =
+                new TopLevelDataSetRegistratorGlobalState(dssCode, openBISService, mailClient,
+                        dataSetValidator, notifySuccessfulRegistration, threadParameters);
+
+        ITopLevelDataSetRegistrator registrator =
+                ClassUtils.create(ITopLevelDataSetRegistrator.class,
+                        threadParameters.getTopLevelDataSetRegistratorClass(), globalState);
 
-        return new TransferredDataSetHandler(dssCode, plugin, openBISService, mailClient,
-                dataSetValidator, notifySuccessfulRegistration,
-                threadParameters.useIsFinishedMarkerFile(), deleteUnidentified,
-                threadParameters.tryGetPreRegistrationScript(),
-                threadParameters.tryGetPostRegistrationScript());
+        return registrator;
     }
 
     private static FileFilter createFileFilter(File incomingDataDirectory,
@@ -352,7 +355,8 @@ public final class ETLDaemon
     }
 
     private static void addShutdownHookForCleanup(final Timer workerTimer,
-            final TransferredDataSetHandler mover, final long timeoutMillis, final String threadName)
+            final ITopLevelDataSetRegistrator mover, final long timeoutMillis,
+            final String threadName)
     {
         Runtime.getRuntime().addShutdownHook(new Thread(new Runnable()
             {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLServerPluginFactory.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLServerPluginFactory.java
new file mode 100644
index 00000000000..5a015b9bbf7
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ETLServerPluginFactory.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright 2011 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.etlserver;
+
+import java.util.HashMap;
+
+/**
+ * A factory for creating IETLServerPlugin objects from ThreadParameters objects.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class ETLServerPluginFactory
+{
+    private static final HashMap<ThreadParameters, IETLServerPlugin> parametersToPluginsMap =
+            new HashMap<ThreadParameters, IETLServerPlugin>();
+
+    public static synchronized IETLServerPlugin getPluginForThread(ThreadParameters threadParameters)
+    {
+
+        IETLServerPlugin plugin = parametersToPluginsMap.get(threadParameters);
+        if (null == plugin)
+        {
+            plugin = new PropertiesBasedETLServerPlugin(threadParameters.getThreadProperties());
+            parametersToPluginsMap.put(threadParameters, plugin);
+        }
+        return plugin;
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/ITopLevelDataSetRegistrator.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ITopLevelDataSetRegistrator.java
new file mode 100644
index 00000000000..e9806fa3db7
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ITopLevelDataSetRegistrator.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2011 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.etlserver;
+
+import java.util.concurrent.locks.Lock;
+
+import ch.systemsx.cisd.common.filesystem.IPathHandler;
+import ch.systemsx.cisd.common.utilities.ISelfTestable;
+
+/**
+ * A path handler that registers data sets.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public interface ITopLevelDataSetRegistrator extends IPathHandler, ISelfTestable
+{
+    public Lock getRegistrationLock();
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/ThreadParameters.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ThreadParameters.java
index 65b08e0804b..092108d9168 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/ThreadParameters.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/ThreadParameters.java
@@ -71,11 +71,13 @@ public final class ThreadParameters
     private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION,
             ThreadParameters.class);
 
-    private static final String INCOMING_DIR = "incoming-dir";
+    @Private
+    static final String INCOMING_DIR = "incoming-dir";
 
     private static final String INCOMING_DIR_CREATE = "incoming-dir-create";
 
-    private static final String DELETE_UNIDENTIFIED_KEY = "delete-unidentified";
+    @Private
+    static final String DELETE_UNIDENTIFIED_KEY = "delete-unidentified";
 
     private static final String REPROCESS_FAULTY_DATASETS_NAME = "reprocess-faulty-datasets";
 
@@ -87,7 +89,9 @@ public final class ThreadParameters
 
     private final boolean createIncomingDirectories;
 
-    private final IETLServerPlugin plugin;
+    private final Properties threadProperties;
+
+    private final Class<?> topLevelDataSetRegistratorClass;
 
     private final String threadName;
 
@@ -112,7 +116,8 @@ public final class ThreadParameters
         this.incomingDataDirectory = extractIncomingDataDir(threadProperties);
         this.createIncomingDirectories =
                 PropertyUtils.getBoolean(threadProperties, INCOMING_DIR_CREATE, false);
-        this.plugin = new PropertiesBasedETLServerPlugin(threadProperties);
+        this.threadProperties = threadProperties;
+        this.topLevelDataSetRegistratorClass = TransferredDataSetHandler.class;
         this.groupCode = tryGetGroupCode(threadProperties);
         this.preRegistrationScript = tryGetPreRegistrationScript(threadProperties);
         this.postRegistrationScript = tryGetPostRegistartionScript(threadProperties);
@@ -232,9 +237,14 @@ public final class ThreadParameters
         return incomingDataDirectory;
     }
 
-    public final IETLServerPlugin getPlugin()
+    public Class<?> getTopLevelDataSetRegistratorClass()
+    {
+        return topLevelDataSetRegistratorClass;
+    }
+
+    public Properties getThreadProperties()
     {
-        return plugin;
+        return threadProperties;
     }
 
     /**
@@ -244,8 +254,14 @@ public final class ThreadParameters
     {
         if (operationLog.isInfoEnabled())
         {
-            logLine("Code extractor: '%s'", plugin.getDataSetInfoExtractor().getClass().getName());
-            logLine("Type extractor: '%s'", plugin.getTypeExtractor().getClass().getName());
+            logLine("Top-level registrator: '%s'", topLevelDataSetRegistratorClass.getName());
+            if (TransferredDataSetHandler.class == topLevelDataSetRegistratorClass)
+            {
+                IETLServerPlugin plugin = ETLServerPluginFactory.getPluginForThread(this);
+                logLine("Code extractor: '%s'", plugin.getDataSetInfoExtractor().getClass()
+                        .getName());
+                logLine("Type extractor: '%s'", plugin.getTypeExtractor().getClass().getName());
+            }
             logLine("Incoming data directory: '%s'.", getIncomingDataDirectory().getAbsolutePath());
             if (groupCode != null)
             {
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TopLevelDataSetRegistratorGlobalState.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TopLevelDataSetRegistratorGlobalState.java
new file mode 100644
index 00000000000..7f4d2c41812
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TopLevelDataSetRegistratorGlobalState.java
@@ -0,0 +1,117 @@
+/*
+ * Copyright 2011 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.etlserver;
+
+import ch.systemsx.cisd.common.mail.IMailClient;
+import ch.systemsx.cisd.etlserver.validation.IDataSetValidator;
+import ch.systemsx.cisd.openbis.dss.generic.shared.IEncapsulatedOpenBISService;
+
+/**
+ * Global state needed by top level data set registrators.
+ * 
+ * @author Chandrasekhar Ramakrishnan
+ */
+public class TopLevelDataSetRegistratorGlobalState
+{
+    private final String dssCode;
+
+    private final IEncapsulatedOpenBISService openBisService;
+
+    private final IMailClient mailClient;
+
+    private final IDataSetValidator dataSetValidator;
+
+    private final boolean notifySuccessfulRegistration;
+
+    private final ThreadParameters threadParameters;
+
+    private final boolean useIsFinishedMarkerFile;
+
+    private final boolean deleteUnidentified;
+
+    private final String preRegistrationScriptOrNull;
+
+    private final String postRegistrationScriptOrNull;
+
+    public TopLevelDataSetRegistratorGlobalState(String dssCode,
+            IEncapsulatedOpenBISService openBisService, IMailClient mailClient,
+            IDataSetValidator dataSetValidator, boolean notifySuccessfulRegistration,
+            ThreadParameters threadParameters)
+
+    {
+        this.dssCode = dssCode;
+        this.openBisService = openBisService;
+        this.mailClient = mailClient;
+        this.dataSetValidator = dataSetValidator;
+        this.notifySuccessfulRegistration = notifySuccessfulRegistration;
+        this.threadParameters = threadParameters;
+        this.useIsFinishedMarkerFile = threadParameters.useIsFinishedMarkerFile();
+        this.deleteUnidentified = threadParameters.deleteUnidentified();
+        this.preRegistrationScriptOrNull = threadParameters.tryGetPreRegistrationScript();
+        this.postRegistrationScriptOrNull = threadParameters.tryGetPostRegistrationScript();
+    }
+
+    public String getDssCode()
+    {
+        return dssCode;
+    }
+
+    public IEncapsulatedOpenBISService getOpenBisService()
+    {
+        return openBisService;
+    }
+
+    public IMailClient getMailClient()
+    {
+        return mailClient;
+    }
+
+    public IDataSetValidator getDataSetValidator()
+    {
+        return dataSetValidator;
+    }
+
+    public boolean isNotifySuccessfulRegistration()
+    {
+        return notifySuccessfulRegistration;
+    }
+
+    public ThreadParameters getThreadParameters()
+    {
+        return threadParameters;
+    }
+
+    public boolean isUseIsFinishedMarkerFile()
+    {
+        return useIsFinishedMarkerFile;
+    }
+
+    public boolean isDeleteUnidentified()
+    {
+        return deleteUnidentified;
+    }
+
+    public String getPreRegistrationScriptOrNull()
+    {
+        return preRegistrationScriptOrNull;
+    }
+
+    public String getPostRegistrationScriptOrNull()
+    {
+        return postRegistrationScriptOrNull;
+    }
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java
index 46c92c35c8b..326356d0422 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandler.java
@@ -32,13 +32,11 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.filesystem.FileOperations;
 import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.filesystem.IFileOperations;
-import ch.systemsx.cisd.common.filesystem.IPathHandler;
 import ch.systemsx.cisd.common.logging.Log4jSimpleLogger;
 import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.utilities.IDelegatedActionWithResult;
-import ch.systemsx.cisd.common.utilities.ISelfTestable;
 import ch.systemsx.cisd.etlserver.IStorageProcessor.UnstoreDataAction;
 import ch.systemsx.cisd.etlserver.utils.PostRegistrationExecutor;
 import ch.systemsx.cisd.etlserver.utils.PreRegistrationExecutor;
@@ -53,7 +51,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.NewExternalData;
  * 
  * @author Bernd Rinn
  */
-public final class TransferredDataSetHandler implements IPathHandler, ISelfTestable,
+public final class TransferredDataSetHandler extends AbstractTopLevelDataSetRegistrator implements
         IDataSetHandler, IExtensibleDataSetHandler
 {
 
@@ -108,41 +106,77 @@ public final class TransferredDataSetHandler implements IPathHandler, ISelfTesta
     private final IPostRegistrationAction postRegistrationAction;
 
     /**
-     * @param dataSetValidator
-     * @param useIsFinishedMarkerFile if true, file/directory is processed when a marker file for it
-     *            appears. Otherwise processing starts if the file/directory is not modified for a
-     *            certain amount of time (so called "quiet period").
-     * @param postRegistrationScriptOrNull
+     * The designated constructor.
+     * 
+     * @param globalState
      */
-    public TransferredDataSetHandler(String dssCode, final IETLServerPlugin plugin,
-            final IEncapsulatedOpenBISService limsService, final IMailClient mailClient,
-            IDataSetValidator dataSetValidator, final boolean notifySuccessfulRegistration,
-            boolean useIsFinishedMarkerFile, boolean deleteUnidentified,
-            String preRegistrationScriptOrNull, String postRegistrationScriptOrNull)
-
+    public TransferredDataSetHandler(TopLevelDataSetRegistratorGlobalState globalState)
     {
-        this(dssCode, plugin.getStorageProcessor(), plugin, limsService, mailClient,
-                dataSetValidator, notifySuccessfulRegistration, useIsFinishedMarkerFile,
-                deleteUnidentified, preRegistrationScriptOrNull, postRegistrationScriptOrNull);
-    }
+        super(globalState);
+
+        this.dssCode = globalState.getDssCode();
+        assert dssCode != null : "Unspecified data store code";
 
-    TransferredDataSetHandler(String dssCode,
-            final IStoreRootDirectoryHolder storeRootDirectoryHolder,
-            final IETLServerPlugin plugin, final IEncapsulatedOpenBISService limsService,
-            final IMailClient mailClient, IDataSetValidator dataSetValidator,
-            final boolean notifySuccessfulRegistration, boolean useIsFinishedMarkerFile,
-            boolean deleteUnidentified, String preRegistrationScriptOrNull,
-            String postRegistrationScriptOrNull)
+        IETLServerPlugin plugin =
+                ETLServerPluginFactory.getPluginForThread(globalState.getThreadParameters());
+        assert plugin != null : "IETLServerPlugin implementation can not be null.";
+
+        storeRootDirectoryHolder = plugin.getStorageProcessor();
+        assert storeRootDirectoryHolder != null : "Given store root directory holder can not be null.";
+
+        this.limsService = globalState.getOpenBisService();
+        assert limsService != null : "IEncapsulatedLimsService implementation can not be null.";
 
+        this.mailClient = globalState.getMailClient();
+        assert mailClient != null : "IMailClient implementation can not be null.";
+
+        this.dataSetInfoExtractor = plugin.getDataSetInfoExtractor();
+        this.typeExtractor = plugin.getTypeExtractor();
+        this.storageProcessor = plugin.getStorageProcessor();
+        dataSetHandler = plugin.getDataSetHandler(this, limsService);
+        if (dataSetHandler instanceof IDataSetHandlerWithMailClient)
+        {
+            ((IDataSetHandlerWithMailClient) dataSetHandler).initializeMailClient(mailClient);
+        }
+        this.dataSetValidator = globalState.getDataSetValidator();
+        this.dataStrategyStore = new DataStrategyStore(this.limsService, mailClient);
+        this.notifySuccessfulRegistration = globalState.isNotifySuccessfulRegistration();
+        this.registrationLock = new ReentrantLock();
+        this.fileOperations = FileOperations.getMonitoredInstanceForCurrentThread();
+        this.useIsFinishedMarkerFile = globalState.isUseIsFinishedMarkerFile();
+        this.deleteUnidentified = globalState.isDeleteUnidentified();
+        this.preRegistrationAction =
+                PreRegistrationExecutor.create(globalState.getPreRegistrationScriptOrNull());
+        this.postRegistrationAction =
+                PostRegistrationExecutor.create(globalState.getPostRegistrationScriptOrNull());
+
+    }
+
+    /**
+     * A constructor used for testing.
+     * 
+     * @param globalState
+     * @param plugin
+     */
+    TransferredDataSetHandler(TopLevelDataSetRegistratorGlobalState globalState,
+            IETLServerPlugin plugin)
     {
+        super(globalState);
+
+        this.dssCode = globalState.getDssCode();
         assert dssCode != null : "Unspecified data store code";
-        assert storeRootDirectoryHolder != null : "Given store root directory holder can not be null.";
+
         assert plugin != null : "IETLServerPlugin implementation can not be null.";
+
+        storeRootDirectoryHolder = plugin.getStorageProcessor();
+        assert storeRootDirectoryHolder != null : "Given store root directory holder can not be null.";
+
+        this.limsService = globalState.getOpenBisService();
         assert limsService != null : "IEncapsulatedLimsService implementation can not be null.";
+
+        this.mailClient = globalState.getMailClient();
         assert mailClient != null : "IMailClient implementation can not be null.";
 
-        this.dssCode = dssCode;
-        this.storeRootDirectoryHolder = storeRootDirectoryHolder;
         this.dataSetInfoExtractor = plugin.getDataSetInfoExtractor();
         this.typeExtractor = plugin.getTypeExtractor();
         this.storageProcessor = plugin.getStorageProcessor();
@@ -151,17 +185,18 @@ public final class TransferredDataSetHandler implements IPathHandler, ISelfTesta
         {
             ((IDataSetHandlerWithMailClient) dataSetHandler).initializeMailClient(mailClient);
         }
-        this.dataSetValidator = dataSetValidator;
-        this.limsService = limsService;
-        this.mailClient = mailClient;
+        this.dataSetValidator = globalState.getDataSetValidator();
         this.dataStrategyStore = new DataStrategyStore(this.limsService, mailClient);
-        this.notifySuccessfulRegistration = notifySuccessfulRegistration;
+        this.notifySuccessfulRegistration = globalState.isNotifySuccessfulRegistration();
         this.registrationLock = new ReentrantLock();
         this.fileOperations = FileOperations.getMonitoredInstanceForCurrentThread();
-        this.useIsFinishedMarkerFile = useIsFinishedMarkerFile;
-        this.deleteUnidentified = deleteUnidentified;
-        this.preRegistrationAction = PreRegistrationExecutor.create(preRegistrationScriptOrNull);
-        this.postRegistrationAction = PostRegistrationExecutor.create(postRegistrationScriptOrNull);
+        this.useIsFinishedMarkerFile = globalState.isUseIsFinishedMarkerFile();
+        this.deleteUnidentified = globalState.isDeleteUnidentified();
+        this.preRegistrationAction =
+                PreRegistrationExecutor.create(globalState.getPreRegistrationScriptOrNull());
+        this.postRegistrationAction =
+                PostRegistrationExecutor.create(globalState.getPostRegistrationScriptOrNull());
+
     }
 
     /**
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/DataSetTypeToPluginMapper.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/DataSetTypeToPluginMapper.java
index a325a99cb79..e26821022f6 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/DataSetTypeToPluginMapper.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/DataSetTypeToPluginMapper.java
@@ -21,6 +21,7 @@ import java.util.HashMap;
 import java.util.Properties;
 
 import ch.systemsx.cisd.common.utilities.ExtendedProperties;
+import ch.systemsx.cisd.etlserver.ETLServerPluginFactory;
 import ch.systemsx.cisd.etlserver.IETLServerPlugin;
 import ch.systemsx.cisd.etlserver.Parameters;
 import ch.systemsx.cisd.etlserver.ThreadParameters;
@@ -111,16 +112,16 @@ class DataSetTypeToPluginMapper
             String defaultThreadName = section.getProperty(DEFAULT_THREAD_KEY);
             if (null == defaultThreadName)
             {
-                return firstThread.getPlugin();
+                return ETLServerPluginFactory.getPluginForThread(firstThread);
             }
 
             ThreadParameters defaultThread = threadParamMap.get(defaultThreadName);
             if (null == defaultThread)
             {
-                return firstThread.getPlugin();
+                return ETLServerPluginFactory.getPluginForThread(firstThread);
             }
 
-            return defaultThread.getPlugin();
+            return ETLServerPluginFactory.getPluginForThread(defaultThread);
         }
 
         public HashMap<String, IETLServerPlugin> getPluginMap()
@@ -136,7 +137,8 @@ class DataSetTypeToPluginMapper
                 ThreadParameters threadParams = threadParamMap.get(threadName);
                 if (null != threadParams)
                 {
-                    map.put(key.toUpperCase(), threadParams.getPlugin());
+                    map.put(key.toUpperCase(),
+                            ETLServerPluginFactory.getPluginForThread(threadParams));
                 }
             }
             return map;
diff --git a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetService.java b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetService.java
index 343b8263e34..937dbd61724 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/etlserver/api/v1/PutDataSetService.java
@@ -31,6 +31,7 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.mail.MailClient;
 import ch.systemsx.cisd.etlserver.DataStrategyStore;
+import ch.systemsx.cisd.etlserver.ETLServerPluginFactory;
 import ch.systemsx.cisd.etlserver.IETLServerPlugin;
 import ch.systemsx.cisd.etlserver.Parameters;
 import ch.systemsx.cisd.etlserver.ThreadParameters;
@@ -287,7 +288,7 @@ class PutDataSetServiceInitializer
     IETLServerPlugin getPlugin()
     {
         ThreadParameters[] threadParams = params.getThreads();
-        return threadParams[0].getPlugin();
+        return ETLServerPluginFactory.getPluginForThread(threadParams[0]);
     }
 
     String getDataStoreCode()
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java
index 3bea95ced83..fd92f9e6f69 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/etlserver/TransferredDataSetHandlerTest.java
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
+import java.util.Properties;
 import java.util.regex.Pattern;
 
 import org.apache.commons.io.FileUtils;
@@ -267,10 +268,20 @@ public final class TransferredDataSetHandlerTest extends AbstractFileSystemTestC
         authorizedLimsService.setPassword("p");
         authorizedLimsService.setDownloadUrl("url");
         dataSetValidator = context.mock(IDataSetValidator.class);
-        handler =
-                new TransferredDataSetHandler("dss", storageProcessor, plugin,
-                        authorizedLimsService, mailClient, dataSetValidator, true, true, false,
-                        null, null);
+
+        Properties threadProperties = new Properties();
+        threadProperties.put(ThreadParameters.INCOMING_DIR, "incoming");
+        threadProperties.put(ThreadParameters.INCOMING_DATA_COMPLETENESS_CONDITION,
+                ThreadParameters.INCOMING_DATA_COMPLETENESS_CONDITION_MARKER_FILE);
+        threadProperties.put(ThreadParameters.DELETE_UNIDENTIFIED_KEY, "false");
+        ThreadParameters threadParameters =
+                new ThreadParameters(threadProperties, "pre-registration-script-test");
+
+        TopLevelDataSetRegistratorGlobalState globalState =
+                new TopLevelDataSetRegistratorGlobalState("dss", authorizedLimsService, mailClient,
+                        dataSetValidator, true, threadParameters);
+
+        handler = new TransferredDataSetHandler(globalState, plugin);
 
         dataSetInformation = new DataSetInformation();
         dataSetInformation.setDataSetType(DATA_SET_TYPE);
@@ -759,10 +770,20 @@ public final class TransferredDataSetHandlerTest extends AbstractFileSystemTestC
     @Test
     public void testPreRegistrationScript()
     {
-        handler =
-                new TransferredDataSetHandler("dss", storageProcessor, plugin,
-                        authorizedLimsService, mailClient, dataSetValidator, true, true, false,
-                        "sourceTest/java/ch/systemsx/cisd/etlserver/utils/test-script.sh", null);
+        Properties threadProperties = new Properties();
+        threadProperties.put(ThreadParameters.INCOMING_DIR, "incoming");
+        threadProperties.put(ThreadParameters.INCOMING_DATA_COMPLETENESS_CONDITION,
+                ThreadParameters.INCOMING_DATA_COMPLETENESS_CONDITION_MARKER_FILE);
+        threadProperties.put(ThreadParameters.DELETE_UNIDENTIFIED_KEY, "false");
+        threadProperties.put(ThreadParameters.PRE_REGISTRATION_SCRIPT_KEY,
+                "sourceTest/java/ch/systemsx/cisd/etlserver/utils/test-script.sh");
+        ThreadParameters threadParameters =
+                new ThreadParameters(threadProperties, "pre-registration-script-test");
+
+        TopLevelDataSetRegistratorGlobalState globalState =
+                new TopLevelDataSetRegistratorGlobalState("dss", authorizedLimsService, mailClient,
+                        dataSetValidator, true, threadParameters);
+        handler = new TransferredDataSetHandler(globalState, plugin);
 
         final Sample baseSample = createBaseSample(dataSetInformation);
         final Experiment baseExperiment = baseSample.getExperiment();
-- 
GitLab