From 5c4a820bd8076a95224de0541f33fbd7c18a3b91 Mon Sep 17 00:00:00 2001
From: kaloyane <kaloyane>
Date: Wed, 9 Nov 2011 16:34:40 +0000
Subject: [PATCH] [LMS-2481] add 'image-datasets-original-dir-name'
 configuration property for screening dropboxes. The property must be
 configured directly on the jython thread.

SVN: 23618
---
 .../cisd/common/filesystem/FileUtilities.java | 34 ++++++++++++++++++
 .../common/filesystem/FileUtilitiesTest.java  | 10 ++++++
 .../etl/jython/JythonPlateDataSetHandler.java | 35 ++++++++++++++++---
 3 files changed, 75 insertions(+), 4 deletions(-)

diff --git a/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java b/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java
index 162a31e0904..625f8354b93 100644
--- a/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java
+++ b/common/source/java/ch/systemsx/cisd/common/filesystem/FileUtilities.java
@@ -2014,4 +2014,38 @@ public final class FileUtilities
         }
     }
 
+    private static String getTempDir()
+    {
+        return System.getProperty("java.io.tmpdir");
+    }
+
+    /**
+     * Return true if <code>fileName</code> is a valid filename.
+     * <p>
+     * The methods works by trying to create a file with the specified name. Thus, the method should
+     * not be called where performance matters.
+     */
+    public static boolean isValidFileName(String fileName)
+    {
+        if (StringUtils.isBlank(fileName) || fileName.contains(File.separator))
+        {
+            return false;
+        }
+
+        File tmpFile = new File(getTempDir(), fileName);
+        try
+        {
+            if (tmpFile.createNewFile())
+            {
+                tmpFile.delete();
+                return true;
+            }
+        } catch (IOException ex)
+        {
+            throw CheckedExceptionTunnel.wrapIfNecessary(ex);
+        }
+
+        return tmpFile.exists();
+    }
+
 }
diff --git a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java
index 2e8419fdd91..df21eec7274 100644
--- a/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java
+++ b/common/sourceTest/java/ch/systemsx/cisd/common/filesystem/FileUtilitiesTest.java
@@ -500,4 +500,14 @@ public final class FileUtilitiesTest extends AbstractFileSystemTestCase
         assertTrue(FileUtilities.isSymbolicLink(linkRelative));
     }
 
+    @Test
+    public void testValidFileName()
+    {
+        assertTrue(FileUtilities.isValidFileName("valid-name1"));
+        assertTrue(FileUtilities.isValidFileName("valid with space and tab\t"));
+        assertTrue(FileUtilities.isValidFileName("valid.dot"));
+        assertFalse(FileUtilities.isValidFileName(""));
+        assertFalse(FileUtilities.isValidFileName("a/b"));
+    }
+
 }
diff --git a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/JythonPlateDataSetHandler.java b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/JythonPlateDataSetHandler.java
index 1d0731ee386..849abd1231f 100644
--- a/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/JythonPlateDataSetHandler.java
+++ b/screening/source/java/ch/systemsx/cisd/openbis/dss/etl/jython/JythonPlateDataSetHandler.java
@@ -11,8 +11,11 @@ import java.util.Properties;
 import org.python.util.PythonInterpreter;
 
 import ch.systemsx.cisd.bds.hcs.Location;
+import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.common.filesystem.FileUtilities;
 import ch.systemsx.cisd.common.utilities.IDelegatedActionWithResult;
+import ch.systemsx.cisd.common.utilities.PropertyUtils;
 import ch.systemsx.cisd.etlserver.ITopLevelDataSetRegistratorDelegate;
 import ch.systemsx.cisd.etlserver.TopLevelDataSetRegistratorGlobalState;
 import ch.systemsx.cisd.etlserver.registrator.DataSetRegistrationDetails;
@@ -49,9 +52,29 @@ import ch.systemsx.cisd.openbis.plugin.screening.shared.basic.dto.ScreeningConst
  */
 public class JythonPlateDataSetHandler extends JythonTopLevelDataSetHandler<DataSetInformation>
 {
+
+    private final String ORIGINAL_DIRNAME_KEY = "image-datasets-original-dir-name";
+
+    private final String originalDirName;
+
     public JythonPlateDataSetHandler(TopLevelDataSetRegistratorGlobalState globalState)
     {
         super(globalState);
+        originalDirName = parseOriginalDir(globalState.getThreadParameters().getThreadProperties());
+    }
+
+    private String parseOriginalDir(Properties threadProperties)
+    {
+        String originalDir =
+                PropertyUtils.getProperty(threadProperties, ORIGINAL_DIRNAME_KEY,
+                        ScreeningConstants.ORIGINAL_DATA_DIR);
+        if (false == FileUtilities.isValidFileName(originalDir))
+        {
+            throw ConfigurationFailureException.fromTemplate(
+                    "Invalid folder name specified in '%s': '%s'.", ORIGINAL_DIRNAME_KEY,
+                    originalDir);
+        }
+        return originalDir;
     }
 
     /**
@@ -278,7 +301,8 @@ public class JythonPlateDataSetHandler extends JythonTopLevelDataSetHandler<Data
                         IDataSetRegistrationDetailsFactory<DataSetInformation> registrationDetailsFactory)
                 {
                     return new ImagingDataSetRegistrationTransaction(rollBackStackParentFolder,
-                            workingDirectory, stagingDirectory, this, registrationDetailsFactory);
+                            workingDirectory, stagingDirectory, this, registrationDetailsFactory,
+                            originalDirName);
                 }
             };
     }
@@ -292,10 +316,13 @@ public class JythonPlateDataSetHandler extends JythonTopLevelDataSetHandler<Data
     {
         private final JythonPlateDatasetFactory registrationDetailsFactory;
 
+        private final String originalDirName;
+
         public ImagingDataSetRegistrationTransaction(File rollBackStackParentFolder,
                 File workingDirectory, File stagingDirectory,
                 DataSetRegistrationService<DataSetInformation> registrationService,
-                IDataSetRegistrationDetailsFactory<DataSetInformation> registrationDetailsFactory)
+                IDataSetRegistrationDetailsFactory<DataSetInformation> registrationDetailsFactory,
+                String originalDirName)
         {
             super(rollBackStackParentFolder, workingDirectory, stagingDirectory,
                     registrationService, registrationDetailsFactory);
@@ -305,6 +332,7 @@ public class JythonPlateDataSetHandler extends JythonTopLevelDataSetHandler<Data
 
             this.registrationDetailsFactory =
                     (JythonPlateDatasetFactory) registrationDetailsFactory;
+            this.originalDirName = originalDirName;
         }
 
         public IDataSet createNewImageDataSet(SimpleImageDataConfig imageDataSet,
@@ -343,8 +371,7 @@ public class JythonPlateDataSetHandler extends JythonTopLevelDataSetHandler<Data
             // create main dataset (with original images)
             IDataSet mainDataset = super.createNewDataSet(imageRegistrationDetails);
             String originalDatasetPathPrefix =
-                    ScreeningConstants.ORIGINAL_DATA_DIR + File.separator
-                            + incomingDirectory.getName();
+                    originalDirName + File.separator + incomingDirectory.getName();
             moveFile(incomingDirectory.getAbsolutePath(), mainDataset, originalDatasetPathPrefix);
             containedDataSetCodes.add(mainDataset.getDataSetCode());
 
-- 
GitLab