From 99909ee8b9ee1ad0f28e714e491657785d553cc9 Mon Sep 17 00:00:00 2001 From: pkupczyk <piotr.kupczyk@id.ethz.ch> Date: Fri, 25 May 2018 20:03:04 +0200 Subject: [PATCH] SSDM-6207 : V3 AS API Batch Imports - UploadServiceServlet Refactoring - introduce AS session workspace and change the AS upload servlet to use it --- .../api/v3/CreateExperimentsImportTest.java | 4 + .../api/v3/CreateMaterialsImportTest.java | 4 + .../api/v3/CreateSamplesImportTest.java | 4 + .../systemtest/api/v3/CustomImportTest.java | 4 + .../systemtest/api/v3/GeneralImportTest.java | 4 + .../systemtest/api/v3/ObjectsImportTest.java | 27 +- .../api/v3/UpdateDataSetsImportTest.java | 4 + .../api/v3/UpdateExperimentsImportTest.java | 4 + .../api/v3/UpdateMaterialsImportTest.java | 4 + .../api/v3/UpdateSamplesImportTest.java | 4 + .../systemtest/api/v3/UploadServletTest.java | 475 ++++++++++++++++++ .../web/server/UploadServiceServlet.java | 31 +- .../client/web/server/UploadedFilesBean.java | 20 +- .../generic/server/AbstractServer.java | 10 +- .../server/ISessionWorkspaceProvider.java | 31 ++ .../generic/server/SessionFactory.java | 8 +- .../server/SessionWorkspaceProvider.java | 107 ++++ .../source/java/genericApplicationContext.xml | 1 + openbis/source/java/service.properties | 2 + .../web/server/UploadServiceServletTest.java | 15 +- 20 files changed, 733 insertions(+), 30 deletions(-) create mode 100644 datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UploadServletTest.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ISessionWorkspaceProvider.java create mode 100644 openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionWorkspaceProvider.java diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateExperimentsImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateExperimentsImportTest.java index 8c5d208d931..546641eb423 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateExperimentsImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateExperimentsImportTest.java @@ -46,6 +46,7 @@ public class CreateExperimentsImportTest extends ObjectsImportTest ImportFile file = new ImportFile("identifier", "DESCRIPTION"); file.addLine(experimentIdentifier.getIdentifier(), "imported description"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Experiment experiment = getObject(sessionToken, experimentIdentifier); assertNull(experiment); @@ -75,6 +76,9 @@ public class CreateExperimentsImportTest extends ObjectsImportTest assertEquals("1 experiment(s) found and registered.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { ExperimentDeletionOptions options = new ExperimentDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateMaterialsImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateMaterialsImportTest.java index c507327c7ba..4c842d79324 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateMaterialsImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateMaterialsImportTest.java @@ -45,6 +45,7 @@ public class CreateMaterialsImportTest extends ObjectsImportTest ImportFile file = new ImportFile("code", "DESCRIPTION"); file.addLine(materialPermId.getCode(), "imported description"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Material material = getObject(sessionToken, materialPermId); assertNull(material); @@ -75,6 +76,9 @@ public class CreateMaterialsImportTest extends ObjectsImportTest assertEquals("Registration/update of 1 material(s) is complete.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { MaterialDeletionOptions options = new MaterialDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateSamplesImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateSamplesImportTest.java index 83f7a31f810..c4f23a444ec 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateSamplesImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CreateSamplesImportTest.java @@ -46,6 +46,7 @@ public class CreateSamplesImportTest extends ObjectsImportTest ImportFile file = new ImportFile("identifier", "COMMENT"); file.addLine(sampleIdentifier.getIdentifier(), "imported comment"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Sample sample = getObject(sessionToken, sampleIdentifier); assertNull(sample); @@ -76,6 +77,9 @@ public class CreateSamplesImportTest extends ObjectsImportTest assertEquals("Registration of 1 sample(s) is complete.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { SampleDeletionOptions options = new SampleDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CustomImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CustomImportTest.java index ce545c8b938..165a7af966d 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CustomImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/CustomImportTest.java @@ -51,6 +51,7 @@ public class CustomImportTest extends ObjectsImportTest multiPart.close(); uploadFiles(sessionToken, TEST_UPLOAD_KEY, multiPart); + assertUploadedFiles(sessionToken, "test-file-content"); DataSet dataSet = getObject(sessionToken, dataSetPermId); assertNull(dataSet); @@ -80,6 +81,9 @@ public class CustomImportTest extends ObjectsImportTest assertEquals("Import successfully completed.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { DataSetDeletionOptions options = new DataSetDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/GeneralImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/GeneralImportTest.java index 8fa63d6701d..ac838263e91 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/GeneralImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/GeneralImportTest.java @@ -66,6 +66,7 @@ public class GeneralImportTest extends ObjectsImportTest multiPart.close(); uploadFiles(sessionToken, TEST_UPLOAD_KEY, multiPart); + assertUploadedFiles(sessionToken, FileUtils.readFileToString(materialsFile)); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put(PARAM_UPLOAD_KEY, TEST_UPLOAD_KEY); @@ -95,6 +96,9 @@ public class GeneralImportTest extends ObjectsImportTest assertEquals("Registration/update of 2 material(s) is complete.\nRegistration of 0 sample(s) is complete.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { deleteMaterials(sessionToken, materialPermId1, materialPermId2); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/ObjectsImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/ObjectsImportTest.java index b41d7e9b677..97808fd9202 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/ObjectsImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/ObjectsImportTest.java @@ -16,6 +16,7 @@ package ch.ethz.sis.openbis.generic.dss.systemtest.api.v3; +import java.io.File; import java.util.ArrayList; import java.util.Arrays; import java.util.List; @@ -23,6 +24,7 @@ import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeoutException; +import org.apache.commons.io.FileUtils; import org.eclipse.jetty.client.HttpClient; import org.eclipse.jetty.client.api.ContentProvider; import org.eclipse.jetty.client.api.ContentResponse; @@ -85,7 +87,7 @@ public class ObjectsImportTest extends AbstractFileTest protected static final String PARAM_UPDATE_EXISTING = "updateExisting"; protected static final String PARAM_IGNORE_UNREGISTERED = "ignoreUnregistered"; - + protected static final String PARAM_CUSTOM_IMPORT_CODE = "customImportCode"; protected IApplicationServerApi as; @@ -129,6 +131,29 @@ public class ObjectsImportTest extends AbstractFileTest return uploadFiles(sessionToken, uploadSessionKey, multiPart); } + protected void assertUploadedFiles(String sessionToken, String... fileContents) throws Exception + { + File sessionWorkspaceRootDir = new File("targets/sessionWorkspace"); + File sessionWorkspace = new File(sessionWorkspaceRootDir, sessionToken); + File[] files = sessionWorkspace.listFiles(); + + List<String> expectedContents = new ArrayList<String>(Arrays.asList(fileContents)); + List<String> actualContents = new ArrayList<String>(); + + if (files != null) + { + for (File file : files) + { + actualContents.add(FileUtils.readFileToString(file)); + } + } + + expectedContents.sort(String.CASE_INSENSITIVE_ORDER); + actualContents.sort(String.CASE_INSENSITIVE_ORDER); + + assertEquals(expectedContents, actualContents); + } + protected String executeImport(String sessionToken, String operation, Map<String, Object> parameters) { CustomASServiceCode serviceId = new CustomASServiceCode("import-test"); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateDataSetsImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateDataSetsImportTest.java index a18bb9e0d9a..5c86b06f0f6 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateDataSetsImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateDataSetsImportTest.java @@ -78,6 +78,7 @@ public class UpdateDataSetsImportTest extends ObjectsImportTest ImportFile file = new ImportFile("code", "COMMENT"); file.addLine(dataSetPermId.getPermId(), "imported comment"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put(PARAM_UPLOAD_KEY, TEST_UPLOAD_KEY); @@ -104,6 +105,9 @@ public class UpdateDataSetsImportTest extends ObjectsImportTest assertEquals("1 data set(s) found and registered.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { DataSetDeletionOptions options = new DataSetDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateExperimentsImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateExperimentsImportTest.java index 094fb142295..c907b907b6c 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateExperimentsImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateExperimentsImportTest.java @@ -63,6 +63,7 @@ public class UpdateExperimentsImportTest extends ObjectsImportTest ImportFile file = new ImportFile("identifier", "DESCRIPTION"); file.addLine(experimentIdentifier.getIdentifier(), "imported description"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put(PARAM_UPLOAD_KEY, TEST_UPLOAD_KEY); @@ -89,6 +90,9 @@ public class UpdateExperimentsImportTest extends ObjectsImportTest assertEquals("Update of 1 experiment(s) is complete.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { ExperimentDeletionOptions options = new ExperimentDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateMaterialsImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateMaterialsImportTest.java index d3a8e817b86..07f9e790eab 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateMaterialsImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateMaterialsImportTest.java @@ -60,6 +60,7 @@ public class UpdateMaterialsImportTest extends ObjectsImportTest ImportFile file = new ImportFile("code", "DESCRIPTION"); file.addLine(materialPermId.getCode(), "imported description"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put(PARAM_UPLOAD_KEY, TEST_UPLOAD_KEY); @@ -87,6 +88,9 @@ public class UpdateMaterialsImportTest extends ObjectsImportTest assertEquals("1 material(s) updated.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { MaterialDeletionOptions options = new MaterialDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateSamplesImportTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateSamplesImportTest.java index 01effa654c5..1c873ede746 100644 --- a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateSamplesImportTest.java +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UpdateSamplesImportTest.java @@ -63,6 +63,7 @@ public class UpdateSamplesImportTest extends ObjectsImportTest ImportFile file = new ImportFile("identifier", "COMMENT"); file.addLine(sampleIdentifier.getIdentifier(), "imported comment"); uploadFiles(sessionToken, TEST_UPLOAD_KEY, file.toString()); + assertUploadedFiles(sessionToken, file.toString()); Map<String, Object> parameters = new HashMap<String, Object>(); parameters.put(PARAM_UPLOAD_KEY, TEST_UPLOAD_KEY); @@ -90,6 +91,9 @@ public class UpdateSamplesImportTest extends ObjectsImportTest assertEquals("Update of 1 sample(s) is complete.", message); assertNoEmails(timestamp); } + + assertUploadedFiles(sessionToken); + } finally { SampleDeletionOptions options = new SampleDeletionOptions(); diff --git a/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UploadServletTest.java b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UploadServletTest.java new file mode 100644 index 00000000000..d81b844f018 --- /dev/null +++ b/datastore_server/sourceTest/java/ch/ethz/sis/openbis/generic/dss/systemtest/api/v3/UploadServletTest.java @@ -0,0 +1,475 @@ +/* + * Copyright 2018 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.sis.openbis.generic.dss.systemtest.api.v3; + +import java.io.File; +import java.io.FileFilter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import org.apache.commons.io.FileUtils; +import org.eclipse.jetty.client.HttpClient; +import org.eclipse.jetty.client.api.ContentResponse; +import org.eclipse.jetty.client.api.Request; +import org.eclipse.jetty.client.util.MultiPartContentProvider; +import org.eclipse.jetty.client.util.StringContentProvider; +import org.eclipse.jetty.http.HttpMethod; +import org.testng.annotations.BeforeClass; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.DataProvider; +import org.testng.annotations.Test; + +import ch.ethz.sis.openbis.generic.asapi.v3.IApplicationServerApi; +import ch.systemsx.cisd.common.http.JettyHttpClientFactory; +import ch.systemsx.cisd.openbis.datastoreserver.systemtests.SystemTestCase; +import ch.systemsx.cisd.openbis.generic.client.web.server.UploadedFilesBean; +import ch.systemsx.cisd.openbis.generic.shared.util.TestInstanceHostUtils; + +/** + * @author pkupczyk + */ +public class UploadServletTest extends SystemTestCase +{ + + private static final String SERVICE_URL = TestInstanceHostUtils.getOpenBISUrl() + "/openbis/upload"; + + private static final String PARAM_SESSION_ID = "sessionID"; + + private static final String PARAM_SESSION_KEY_PREFIX = "sessionKey_"; + + private static final String PARAM_SESSION_KEYS_NUMBER = "sessionKeysNumber"; + + private static final String USER = "test"; + + private static final String PASSWORD = "password"; + + private static final String FALSE_TRUE_PROVIDER = "false-true-provider"; + + private IApplicationServerApi as; + + @BeforeClass + private void beforeClass() throws Exception + { + as = applicationContext.getBean(IApplicationServerApi.class); + } + + @BeforeMethod + private void beforeMethod() + { + JettyHttpClientFactory.getHttpClient().getCookieStore().removeAll(); + } + + @Test(dataProvider = FALSE_TRUE_PROVIDER) + public void testUploadSingleFile(boolean withSessionToken) throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + if (withSessionToken) + { + cleanSessionWorkspace(sessionToken); + } else + { + initHttpSession(sessionToken); + cleanOSTempFolder(); + } + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + if (withSessionToken) + { + request.param(PARAM_SESSION_ID, sessionToken); + } + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + request.send(); + + if (withSessionToken) + { + assertSessionWorkspaceFiles(sessionToken, "testContent"); + } else + { + assertOSTempFolderFiles("testContent"); + } + } + + @Test(dataProvider = FALSE_TRUE_PROVIDER) + public void testUploadMultipleFilesUnderOneSessionKey(boolean withSessionToken) throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + if (withSessionToken) + { + cleanSessionWorkspace(sessionToken); + } else + { + initHttpSession(sessionToken); + cleanOSTempFolder(); + } + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName1", "testFileName1", new StringContentProvider("testContent1"), null); + multipart.addFilePart("testFieldName2", "testFileName2", new StringContentProvider("testContent2"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + if (withSessionToken) + { + request.param(PARAM_SESSION_ID, sessionToken); + } + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + request.send(); + + if (withSessionToken) + { + assertSessionWorkspaceFiles(sessionToken, "testContent1", "testContent2"); + } else + { + assertOSTempFolderFiles("testContent1", "testContent2"); + } + } + + @Test(dataProvider = FALSE_TRUE_PROVIDER) + public void testUploadMultipleFilesUnderMultipleSessionKeys(boolean withSessionToken) throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + if (withSessionToken) + { + cleanSessionWorkspace(sessionToken); + } else + { + initHttpSession(sessionToken); + cleanOSTempFolder(); + } + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName1", "testFileName1", new StringContentProvider("testContent1"), null); + multipart.addFilePart("testFieldName2", "testFileName2", new StringContentProvider("testContent2"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + if (withSessionToken) + { + request.param(PARAM_SESSION_ID, sessionToken); + } + request.param(PARAM_SESSION_KEYS_NUMBER, "2"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName1"); + request.param(PARAM_SESSION_KEY_PREFIX + "1", "testFieldName2"); + request.content(multipart); + + request.send(); + + if (withSessionToken) + { + assertSessionWorkspaceFiles(sessionToken, "testContent1", "testContent2"); + } else + { + assertOSTempFolderFiles("testContent1", "testContent2"); + } + } + + @Test + public void testUploadWithHttpSessionAndWithoutSessionToken() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + initHttpSession(sessionToken); + + cleanSessionWorkspace(sessionToken); + cleanOSTempFolder(); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + request.send(); + + assertSessionWorkspaceFiles(sessionToken); + assertOSTempFolderFiles("testContent"); + } + + @Test + public void testUploadWithoutHttpSessionAndWithoutSessionToken() throws Exception + { + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + ContentResponse response = request.send(); + assertEquals("<message type=\"error\">Pre-existing session required but none found</message>", response.getContentAsString()); + } + + @Test + public void testUploadWithoutHttpSessionAndWithSessionToken() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + cleanSessionWorkspace(sessionToken); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + request.send(); + + assertSessionWorkspaceFiles(sessionToken, "testContent"); + } + + @Test + public void testUploadWithoutSessionKeysNumber() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + ContentResponse response = request.send(); + assertEquals("<message type=\"error\">No form field 'sessionKeysNumber' could be found in the transmitted form.</message>", + response.getContentAsString()); + } + + @Test + public void testUploadWithIncorrectSessionKeysNumberFormat() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEYS_NUMBER, "thisShouldBeANumber"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + ContentResponse response = request.send(); + assertEquals("<message type=\"error\">For input string: \"thisShouldBeANumber\"</message>", + response.getContentAsString()); + } + + @Test + public void testUploadWithoutSessionKeyPrefix() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.content(multipart); + + ContentResponse response = request.send(); + + assertEquals("<message type=\"error\">No field '" + PARAM_SESSION_KEY_PREFIX + "0' could be found in the transmitted form.</message>", + response.getContentAsString()); + } + + @Test + public void testUploadWithTooFewSessionKeyPrefixes() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEYS_NUMBER, "2"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + ContentResponse response = request.send(); + + assertEquals("<message type=\"error\">No field '" + PARAM_SESSION_KEY_PREFIX + "1' could be found in the transmitted form.</message>", + response.getContentAsString()); + } + + @Test + public void testUploadWithLogout() throws Exception + { + String sessionToken = as.login(USER, PASSWORD); + + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("testFieldName", "testFileName", new StringContentProvider("testContent"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "testFieldName"); + request.content(multipart); + + request.send(); + + assertSessionWorkspaceFiles(sessionToken, "testContent"); + + as.logout(sessionToken); + + assertSessionWorkspaceFiles(sessionToken); + } + + private File getSessionWorkspace(String sessionToken) throws Exception + { + File sessionWorkspaceRootDir = new File("targets/sessionWorkspace"); + return new File(sessionWorkspaceRootDir, sessionToken); + } + + private void cleanSessionWorkspace(String sessionToken) throws Exception + { + File sessionWorkspace = getSessionWorkspace(sessionToken); + + if (sessionWorkspace.exists()) + { + FileUtils.deleteQuietly(sessionWorkspace); + } + + assertSessionWorkspaceFiles(sessionToken); + } + + private void assertSessionWorkspaceFiles(String sessionToken, String... fileContents) throws Exception + { + assertFiles(getSessionWorkspace(sessionToken).listFiles(), fileContents); + } + + private void initHttpSession(String sessionToken) throws Exception + { + // upload a dummy file to initialize HTTP session + MultiPartContentProvider multipart = new MultiPartContentProvider(); + multipart.addFilePart("initHttpSession", "initHttpSession", new StringContentProvider("initHttpSession"), null); + multipart.close(); + + HttpClient client = JettyHttpClientFactory.getHttpClient(); + Request request = client.newRequest(SERVICE_URL).method(HttpMethod.POST); + request.param(PARAM_SESSION_ID, sessionToken); + request.param(PARAM_SESSION_KEYS_NUMBER, "1"); + request.param(PARAM_SESSION_KEY_PREFIX + "0", "initHttpSession"); + request.content(multipart); + + request.send(); + } + + private File getOSTempFolder() throws Exception + { + return new File(System.getProperty("java.io.tmpdir")); + } + + private void cleanOSTempFolder() throws Exception + { + File tempFolder = getOSTempFolder(); + + if (tempFolder.exists()) + { + File[] files = tempFolder.listFiles(new OSTempFolderFileFilter()); + + for (File file : files) + { + FileUtils.deleteQuietly(file); + } + } + + assertOSTempFolderFiles(); + } + + private void assertOSTempFolderFiles(String... fileContents) throws Exception + { + assertFiles(getOSTempFolder().listFiles(new OSTempFolderFileFilter()), fileContents); + } + + private void assertFiles(File[] files, String... fileContents) throws Exception + { + List<String> expectedContents = new ArrayList<String>(Arrays.asList(fileContents)); + List<String> actualContents = new ArrayList<String>(); + + if (files != null) + { + for (File file : files) + { + actualContents.add(FileUtils.readFileToString(file)); + } + } + + expectedContents.sort(String.CASE_INSENSITIVE_ORDER); + actualContents.sort(String.CASE_INSENSITIVE_ORDER); + + assertEquals(expectedContents, actualContents); + } + + private static class OSTempFolderFileFilter implements FileFilter + { + + @Override + public boolean accept(File file) + { + return file.getName().startsWith(UploadedFilesBean.class.getSimpleName()); + } + + } + + @DataProvider(name = FALSE_TRUE_PROVIDER) + public static Object[][] provideFalseTrue() + { + return new Object[][] { { false }, { true } }; + } + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServlet.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServlet.java index 2653065254d..660b9952ab3 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServlet.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServlet.java @@ -29,6 +29,7 @@ import javax.servlet.http.HttpSession; import org.apache.commons.lang.StringUtils; import org.apache.log4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.HttpSessionRequiredException; import org.springframework.web.bind.annotation.RequestMapping; @@ -43,6 +44,7 @@ import ch.systemsx.cisd.common.exceptions.UserFailureException; import ch.systemsx.cisd.common.logging.LogCategory; import ch.systemsx.cisd.common.logging.LogFactory; import ch.systemsx.cisd.openbis.generic.server.ComponentNames; +import ch.systemsx.cisd.openbis.generic.server.ISessionWorkspaceProvider; import ch.systemsx.cisd.openbis.generic.server.SessionConstants; import ch.systemsx.cisd.openbis.generic.shared.IOpenBisSessionManager; import ch.systemsx.cisd.openbis.generic.shared.dto.Session; @@ -65,8 +67,7 @@ import ch.systemsx.cisd.openbis.generic.shared.dto.Session; * @author Christian Ribeaud */ @Controller -@RequestMapping( -{ "/upload", "/openbis/upload" }) +@RequestMapping({ "/upload", "/openbis/upload" }) public final class UploadServiceServlet extends AbstractController { private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, @@ -77,6 +78,9 @@ public final class UploadServiceServlet extends AbstractController @Resource(name = ComponentNames.SESSION_MANAGER) protected IOpenBisSessionManager sessionManager; + @Autowired + private ISessionWorkspaceProvider sessionWorkspaceProvider; + @Private UploadServiceServlet(ISessionFilesSetter sessionFilesSetter) { @@ -91,8 +95,7 @@ public final class UploadServiceServlet extends AbstractController this(new SessionFilesSetter()); } - @SuppressWarnings( - { "unchecked", "rawtypes" }) + @SuppressWarnings({ "unchecked", "rawtypes" }) private final static Iterator<String> cast(final Iterator iterator) { return iterator; @@ -208,7 +211,7 @@ public final class UploadServiceServlet extends AbstractController { // Note: addFilesToSession has a side effect - adds extracted files to the session boolean fileExtracted = - sessionFilesSetter.addFilesToSession(session, multipartRequest, sessionKey); + sessionFilesSetter.addFilesToSession(sessionToken, session, multipartRequest, sessionKey, sessionWorkspaceProvider); atLeastOneFileUploaded = atLeastOneFileUploaded || fileExtracted; } if (atLeastOneFileUploaded == false) @@ -246,25 +249,25 @@ public final class UploadServiceServlet extends AbstractController * * @return <code>true</code> if at least one file has been found and added */ - public boolean addFilesToSession(final HttpSession session, - final MultipartHttpServletRequest multipartRequest, String sessionKey); + public boolean addFilesToSession(String sessionToken, final HttpSession session, + final MultipartHttpServletRequest multipartRequest, String sessionKey, ISessionWorkspaceProvider sessionWorkspaceProvider); } @Private static class SessionFilesSetter implements ISessionFilesSetter { @Override - public boolean addFilesToSession(final HttpSession session, - final MultipartHttpServletRequest multipartRequest, String sessionKey) + public boolean addFilesToSession(String sessionToken, final HttpSession session, + final MultipartHttpServletRequest multipartRequest, String sessionKey, ISessionWorkspaceProvider sessionWorkspaceProvider) { - return addFilesToSessionUsingBean(session, multipartRequest, sessionKey, - new UploadedFilesBean()); + return addFilesToSessionUsingBean(sessionToken, session, multipartRequest, sessionKey, + new UploadedFilesBean(), sessionWorkspaceProvider); } @Private - boolean addFilesToSessionUsingBean(final HttpSession session, + boolean addFilesToSessionUsingBean(String sessionToken, final HttpSession session, final MultipartHttpServletRequest multipartRequest, String sessionKey, - final UploadedFilesBean uploadedFiles) + final UploadedFilesBean uploadedFiles, ISessionWorkspaceProvider sessionWorkspaceProvider) { assert StringUtils.isBlank(sessionKey) == false; boolean fileUploaded = false; @@ -277,7 +280,7 @@ public final class UploadServiceServlet extends AbstractController final MultipartFile multipartFile = multipartRequest.getFile(fileName); if (multipartFile.isEmpty() == false) { - uploadedFiles.addMultipartFile(multipartFile); + uploadedFiles.addMultipartFile(sessionToken, multipartFile, sessionWorkspaceProvider); fileUploaded = true; } } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadedFilesBean.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadedFilesBean.java index 37d717f3429..408d55ee7cb 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadedFilesBean.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadedFilesBean.java @@ -26,8 +26,10 @@ import org.apache.commons.io.FileUtils; import org.springframework.web.multipart.MultipartFile; import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked; +import ch.systemsx.cisd.common.shared.basic.string.StringUtils; import ch.systemsx.cisd.openbis.common.spring.IUncheckedMultipartFile; import ch.systemsx.cisd.openbis.common.spring.MultipartFileAdapter; +import ch.systemsx.cisd.openbis.generic.server.ISessionWorkspaceProvider; /** * A bean that contains the uploaded files. @@ -40,19 +42,31 @@ public final class UploadedFilesBean private List<IUncheckedMultipartFile> multipartFiles = new ArrayList<IUncheckedMultipartFile>(); - private final File createTempFile() throws IOException + private final File createTempFile(String sessionToken, ISessionWorkspaceProvider sessionWorkspaceProvider) throws IOException { - final File tempFile = File.createTempFile(CLASS_SIMPLE_NAME, null); + File tempFolder = null; + + if (false == StringUtils.isBlank(sessionToken) && sessionWorkspaceProvider != null) + { + tempFolder = sessionWorkspaceProvider.getSessionWorkspace(sessionToken); + } + + final File tempFile = File.createTempFile(CLASS_SIMPLE_NAME, null, tempFolder); tempFile.deleteOnExit(); return tempFile; } public final void addMultipartFile(final MultipartFile multipartFile) + { + addMultipartFile(null, multipartFile, null); + } + + public final void addMultipartFile(String sessionToken, final MultipartFile multipartFile, ISessionWorkspaceProvider sessionWorkspaceProvider) { assert multipartFile != null : "Unspecified multipart file."; try { - final File tempFile = createTempFile(); + final File tempFile = createTempFile(sessionToken, sessionWorkspaceProvider); multipartFile.transferTo(tempFile); final FileMultipartFileAdapter multipartFileAdapter = new FileMultipartFileAdapter(multipartFile, tempFile); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java index 8a889f811ab..c3fb261e0c7 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/AbstractServer.java @@ -171,6 +171,9 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp @Autowired private IAuthorizationConfig authorizationConfig; + @Autowired + private ISessionWorkspaceProvider sessionWorkspaceProvider; + private IApplicationServerApi v3Api; protected String CISDHelpdeskEmail; @@ -407,6 +410,7 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp try { sessionManager.closeSession(sessionToken); + sessionWorkspaceProvider.deleteSessionWorkspace(sessionToken); SessionFactory.cleanUpSessionOnDataStoreServers(sessionToken, daoFactory.getDataStoreDAO(), dssFactory); } catch (InvalidSessionException e) @@ -422,6 +426,7 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp try { sessionManager.expireSession(sessionToken); + sessionWorkspaceProvider.deleteSessionWorkspace(sessionToken); SessionFactory.cleanUpSessionOnDataStoreServers(sessionToken, daoFactory.getDataStoreDAO(), dssFactory); } catch (InvalidSessionException e) @@ -929,8 +934,9 @@ public abstract class AbstractServer<T> extends AbstractServiceWithLogger<T> imp if (person != null) { SpacePE homeGroup = - groupIdOrNull == null ? null : getDAOFactory().getSpaceDAO().getByTechId( - groupIdOrNull); + groupIdOrNull == null ? null + : getDAOFactory().getSpaceDAO().getByTechId( + groupIdOrNull); person.setHomeSpace(homeGroup); getDAOFactory().getPersonDAO().updatePerson(person); } diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ISessionWorkspaceProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ISessionWorkspaceProvider.java new file mode 100644 index 00000000000..5f127a53e37 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/ISessionWorkspaceProvider.java @@ -0,0 +1,31 @@ +/* + * Copyright 2018 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.openbis.generic.server; + +import java.io.File; + +/** + * @author pkupczyk + */ +public interface ISessionWorkspaceProvider +{ + + File getSessionWorkspace(String sessionToken); + + void deleteSessionWorkspace(String sessionToken); + +} diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java index 501d8045536..d16c72b71c5 100644 --- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionFactory.java @@ -45,15 +45,18 @@ public final class SessionFactory implements ISessionFactory<Session> private final IDataStoreServiceFactory dssFactory; + private final ISessionWorkspaceProvider sessionWorkspaceProvider; + public SessionFactory() { - this(null, null); + this(null, null, null); } - public SessionFactory(IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory) + public SessionFactory(IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory, ISessionWorkspaceProvider sessionWorkspaceProvider) { this.datastoreDAO = (daoFactory != null) ? daoFactory.getDataStoreDAO() : null; this.dssFactory = dssFactory; + this.sessionWorkspaceProvider = sessionWorkspaceProvider; } // @@ -75,6 +78,7 @@ public final class SessionFactory implements ISessionFactory<Session> @Override public void cleanup() { + sessionWorkspaceProvider.deleteSessionWorkspace(sessionToken); cleanUpSessionOnDataStoreServers(sessionToken, datastoreDAO, dssFactory); } }); diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionWorkspaceProvider.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionWorkspaceProvider.java new file mode 100644 index 00000000000..3d447f134c0 --- /dev/null +++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/SessionWorkspaceProvider.java @@ -0,0 +1,107 @@ +/* + * Copyright 2018 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.openbis.generic.server; + +import java.io.File; +import java.util.Properties; + +import javax.annotation.PostConstruct; +import javax.annotation.Resource; + +import org.apache.log4j.Logger; +import org.springframework.stereotype.Component; + +import ch.systemsx.cisd.common.filesystem.QueueingPathRemoverService; +import ch.systemsx.cisd.common.logging.LogCategory; +import ch.systemsx.cisd.common.logging.LogFactory; +import ch.systemsx.cisd.common.properties.PropertyUtils; +import ch.systemsx.cisd.common.spring.ExposablePropertyPlaceholderConfigurer; + +/** + * @author pkupczyk + */ +@Component(value = "session-workspace-provider") +public class SessionWorkspaceProvider implements ISessionWorkspaceProvider +{ + + private static final String SESSION_WORKSPACE_ROOT_DIR_KEY = "session-workspace-root-dir"; + + private static final String SESSION_WORKSPACE_ROOT_DIR_DEFAULT = "sessionWorkspace"; + + private static final String SESSION_WORKSPACE_SHREDDER_QUEUE_FILE = ".shredder"; + + private static final Logger operationLog = LogFactory.getLogger(LogCategory.OPERATION, SessionWorkspaceProvider.class); + + @Resource(name = ExposablePropertyPlaceholderConfigurer.PROPERTY_CONFIGURER_BEAN_NAME) + private ExposablePropertyPlaceholderConfigurer servicePropertiesPlaceholder; + + private File sessionWorkspaceRootDir; + + @PostConstruct + private void init() throws Exception + { + Properties serviceProperties = servicePropertiesPlaceholder.getResolvedProps(); + + String sessionWorkspaceRootDirString = + PropertyUtils.getProperty(serviceProperties, SESSION_WORKSPACE_ROOT_DIR_KEY, SESSION_WORKSPACE_ROOT_DIR_DEFAULT); + sessionWorkspaceRootDir = new File(sessionWorkspaceRootDirString); + + operationLog.info("Session workspace root dir '" + sessionWorkspaceRootDir.getCanonicalPath() + "'"); + + if (false == sessionWorkspaceRootDir.exists()) + { + sessionWorkspaceRootDir.mkdirs(); + } + + QueueingPathRemoverService.start(sessionWorkspaceRootDir, new File(SESSION_WORKSPACE_SHREDDER_QUEUE_FILE)); + + operationLog.info("Session workspace shredder service started"); + } + + @Override + public File getSessionWorkspace(String sessionToken) + { + File sessionWorkspace = new File(sessionWorkspaceRootDir, sessionToken); + + if (false == sessionWorkspace.exists()) + { + sessionWorkspace.mkdirs(); + operationLog.info("Session workspace '" + sessionToken + "' created"); + } + + return sessionWorkspace; + } + + @Override + public void deleteSessionWorkspace(String sessionToken) + { + try + { + File sessionWorkspace = new File(sessionWorkspaceRootDir, sessionToken); + + if (sessionWorkspace.exists()) + { + QueueingPathRemoverService.removeRecursively(sessionWorkspace); + operationLog.info("Session workspace '" + sessionToken + "' added to shredder queue"); + } + } catch (Exception e) + { + operationLog.warn("Session workspace '" + sessionToken + "' could not be shredded", e); + } + } + +} diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml index 362ea3aeb07..331b1366310 100644 --- a/openbis/source/java/genericApplicationContext.xml +++ b/openbis/source/java/genericApplicationContext.xml @@ -130,6 +130,7 @@ <bean class="ch.systemsx.cisd.openbis.generic.server.SessionFactory"> <constructor-arg ref="dao-factory" /> <constructor-arg ref="dss-factory" /> + <constructor-arg ref="session-workspace-provider" /> </bean> </constructor-arg> <constructor-arg> diff --git a/openbis/source/java/service.properties b/openbis/source/java/service.properties index 568792007cb..3aa53d02629 100644 --- a/openbis/source/java/service.properties +++ b/openbis/source/java/service.properties @@ -20,6 +20,8 @@ create-continuous-sample-codes = false data-set-types-with-no-experiment-needed = (?!REQUIRES\\_EXPERIMENT).* +session-workspace-root-dir = targets/sessionWorkspace + # Supported: currently only 'postgresql' is supported database.engine = postgresql database.create-from-scratch = false diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServletTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServletTest.java index 24d96d6c23b..18884125e7b 100644 --- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServletTest.java +++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/client/web/server/UploadServiceServletTest.java @@ -39,8 +39,7 @@ import ch.systemsx.cisd.openbis.generic.client.web.server.UploadServiceServlet.S * * @author Izabela Adamczyk */ -@Friend(toClasses = -{ UploadServiceServlet.class, ISessionFilesSetter.class, SessionFilesSetter.class }) +@Friend(toClasses = { UploadServiceServlet.class, ISessionFilesSetter.class, SessionFilesSetter.class }) public final class UploadServiceServletTest extends AssertJUnit { @@ -231,8 +230,8 @@ public final class UploadServiceServletTest extends AssertJUnit one(multipartHttpServletRequest).getParameter(SESSION_KEY_PREFIX + i); will(returnValue(sessionKey)); - one(sessionFilesSetter).addFilesToSession(httpSession, - multipartHttpServletRequest, sessionKey); + one(sessionFilesSetter).addFilesToSession("", httpSession, + multipartHttpServletRequest, sessionKey, null); will(returnValue(false)); } @@ -269,8 +268,8 @@ public final class UploadServiceServletTest extends AssertJUnit one(multipartHttpServletRequest).getParameter(SESSION_KEY_PREFIX + i); will(returnValue(sessionKey)); - one(sessionFilesSetter).addFilesToSession(httpSession, - multipartHttpServletRequest, sessionKey); + one(sessionFilesSetter).addFilesToSession("", httpSession, + multipartHttpServletRequest, sessionKey, null); will(returnValue(true)); } expectSendResponse(this); @@ -299,8 +298,8 @@ public final class UploadServiceServletTest extends AssertJUnit one(multipartHttpServletRequest).getParameter(SESSION_KEY_PREFIX + i); will(returnValue(sessionKey)); - one(sessionFilesSetter).addFilesToSession(httpSession, - multipartHttpServletRequest, sessionKey); + one(sessionFilesSetter).addFilesToSession("", httpSession, + multipartHttpServletRequest, sessionKey, null); will(returnValue(i != numberOfSessionKeys - 1)); } expectSendResponse(this); -- GitLab