diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
index 5419d242e6727f0d7a07f5182cc198460503560e..8a05aa1779f8972b298edeee6ceb2240b00ea24c 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreService.java
@@ -33,6 +33,7 @@ import ch.systemsx.cisd.cifex.rpc.client.ICIFEXComponent;
 import ch.systemsx.cisd.common.exceptions.ConfigurationFailureException;
 import ch.systemsx.cisd.common.exceptions.InvalidAuthenticationException;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
+import ch.systemsx.cisd.common.filesystem.QueueingPathRemoverService;
 import ch.systemsx.cisd.common.mail.IMailClient;
 import ch.systemsx.cisd.common.mail.MailClient;
 import ch.systemsx.cisd.common.mail.MailClientParameters;
@@ -82,7 +83,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
 
     private final MailClientParameters mailClientParameters;
 
-    private final PluginTaskInfoProvider pluginTaskParameters;
+    private final PluginTaskInfoProvider pluginTaskInfoProvider;
 
     private IHierarchicalContentProvider hierarchicalContentProvider;
 
@@ -120,7 +121,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
         this.sessionTokenManager = sessionTokenManager;
         this.commandExecutorFactory = commandExecutorFactory;
         this.mailClientParameters = mailClientParameters;
-        this.pluginTaskParameters = pluginTaskParameters;
+        this.pluginTaskInfoProvider = pluginTaskParameters;
         storeRoot = pluginTaskParameters.getStoreRoot();
     }
 
@@ -320,7 +321,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
         sessionTokenManager.assertValidSessionToken(sessionToken);
 
         PluginTaskProvider<IReportingPluginTask> reportingPlugins =
-                pluginTaskParameters.getReportingPluginsProvider();
+                pluginTaskInfoProvider.getReportingPluginsProvider();
         IReportingPluginTask task = reportingPlugins.getPluginInstance(serviceKey);
         IShareIdManager manager = getShareIdManager();
         try
@@ -330,10 +331,16 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
                 manager.lock(dataSet.getDataSetCode());
             }
             IMailClient mailClient = createEMailClient();
-            return task.createReport(datasets, new DataSetProcessingContext(
-                    getHierarchicalContentProvider(), new DataSetDirectoryProvider(storeRoot,
-                            manager), new HashMap<String, String>(), mailClient, userEmailOrNull,
-                    userSessionToken));
+            return task.createReport(
+                    datasets,
+                    new DataSetProcessingContext(
+                            getHierarchicalContentProvider(), new DataSetDirectoryProvider(
+                                    storeRoot,
+                                    manager), new SessionWorkspaceProvider(pluginTaskInfoProvider
+                                    .getSessionWorkspaceRootDir(),
+                                    userSessionToken),
+                            new HashMap<String, String>(), mailClient, userEmailOrNull,
+                            userSessionToken));
 
         } finally
         {
@@ -349,7 +356,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
         sessionTokenManager.assertValidSessionToken(sessionToken);
 
         PluginTaskProvider<IProcessingPluginTask> plugins =
-                pluginTaskParameters.getProcessingPluginsProvider();
+                pluginTaskInfoProvider.getProcessingPluginsProvider();
 
         IProcessingPluginTask task = plugins.getPluginInstance(serviceKey);
         DatastoreServiceDescription pluginDescription = plugins.getPluginDescription(serviceKey);
@@ -381,7 +388,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
     @Override
     public IArchiverPlugin getArchiverPlugin()
     {
-        ArchiverPluginFactory factory = pluginTaskParameters.getArchiverPluginFactory();
+        ArchiverPluginFactory factory = pluginTaskInfoProvider.getArchiverPluginFactory();
         return factory.createInstance(storeRoot);
     }
 
@@ -398,16 +405,22 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
     {
         sessionTokenManager.assertValidSessionToken(sessionToken);
         PluginTaskProvider<IReportingPluginTask> reportingPlugins =
-                pluginTaskParameters.getReportingPluginsProvider();
+                pluginTaskInfoProvider.getReportingPluginsProvider();
         IReportingPluginTask task = reportingPlugins.getPluginInstance(serviceKey);
         IShareIdManager manager = getShareIdManager();
         try
         {
             IMailClient mailClient = createEMailClient();
-            return task.createAggregationReport(parameters, new DataSetProcessingContext(
-                    getHierarchicalContentProvider(), new DataSetDirectoryProvider(storeRoot,
-                            manager), new HashMap<String, String>(), mailClient, userEmailOrNull,
-                    userSessionToken));
+            return task.createAggregationReport(
+                    parameters,
+                    new DataSetProcessingContext(
+                            getHierarchicalContentProvider(), new DataSetDirectoryProvider(
+                                    storeRoot,
+                                    manager), new SessionWorkspaceProvider(pluginTaskInfoProvider
+                                    .getSessionWorkspaceRootDir(),
+                                    userSessionToken),
+                            new HashMap<String, String>(), mailClient, userEmailOrNull,
+                            userSessionToken));
 
         } finally
         {
@@ -492,7 +505,7 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
         sessionTokenManager.assertValidSessionToken(sessionToken);
 
         PluginTaskProvider<IReportingPluginTask> reportingPlugins =
-                pluginTaskParameters.getReportingPluginsProvider();
+                pluginTaskInfoProvider.getReportingPluginsProvider();
         IReportingPluginTask task = reportingPlugins.getPluginInstance(serviceKey);
         return task.createLink(dataSet);
     }
@@ -511,6 +524,17 @@ public class DataStoreService extends AbstractServiceWithLogger<IDataStoreServic
         return service.putDataSet(sessionToken, dropboxName, customImportFile);
     }
 
+    @Override
+    public void cleanupSession(String userSessionToken)
+    {
+        final File sessionWorkspace =
+                new File(pluginTaskInfoProvider.getSessionWorkspaceRootDir(), userSessionToken);
+        if (sessionWorkspace.exists())
+        {
+            QueueingPathRemoverService.removeRecursively(sessionWorkspace);
+        }
+    }
+
     private PutDataSetService getPutDataSetService()
     {
         if (putService == null)
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
index 39b74ad44d339547f79fd1d7cf84bea8f6d9dab9..2ad2542bb904578b31facd2dc906a59acacbbc9a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DataStoreServiceLogger.java
@@ -193,4 +193,10 @@ class DataStoreServiceLogger implements IDataStoreService, IInitializable
         log("putDataSet", "DROPBOX_NAME(%s), CUSTOM_IMPORT_FILE(%s)", dropboxName, customImportFile);
         return null;
     }
+
+    @Override
+    public void cleanupSession(String userSessionToken)
+    {
+        log("cleanupSession", "USER_SESSION(%s)", userSessionToken);
+    }
 }
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ISessionWorkspaceProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ISessionWorkspaceProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..b236fadfb93b0aaee33ddc9ba8e560b36e50d57b
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/ISessionWorkspaceProvider.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2012 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.dss.generic.server;
+
+import java.io.File;
+
+/**
+ * A provider for a workspace directory with the lifetime of a user session.
+ * 
+ * @author Bernd Rinn
+ */
+public interface ISessionWorkspaceProvider
+{
+
+    /**
+     * Returns the directory representing this user session's workspace.
+     * <p>
+     * Files put in this directory will be available during the user session and will be
+     * automatically cleaned up when the user session is closed (or expires).
+     */
+    public File getSessionWorkspace();
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/SessionWorkspaceProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/SessionWorkspaceProvider.java
new file mode 100644
index 0000000000000000000000000000000000000000..6db05f12b56e1d0a821f5878521f6d099d14b7b7
--- /dev/null
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/SessionWorkspaceProvider.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright 2012 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.dss.generic.server;
+
+import java.io.File;
+
+/**
+ * A provider for the session workspace directory.
+ * 
+ * @author Bernd Rinn
+ */
+public class SessionWorkspaceProvider implements ISessionWorkspaceProvider
+{
+    private final String sessionToken;
+
+    private final File sessionWorkspace;
+
+    public SessionWorkspaceProvider(File sessionWorkspaceRootDirectory, String userSessionToken)
+    {
+        this.sessionToken = userSessionToken;
+        this.sessionWorkspace = new File(sessionWorkspaceRootDirectory, sessionToken);
+    }
+
+    @Override
+    public File getSessionWorkspace()
+    {
+        if (sessionWorkspace.exists() == false)
+        {
+            sessionWorkspace.mkdirs();
+        }
+        return sessionWorkspace;
+    }
+
+}
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/jython/PluginScriptRunnerFactory.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/jython/PluginScriptRunnerFactory.java
index 0d490b06febe67bb9a453e77aa61d1c6e2689672..55f7e46a09194af79d497511004ab2b19d1fb9c6 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/jython/PluginScriptRunnerFactory.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/jython/PluginScriptRunnerFactory.java
@@ -32,6 +32,7 @@ import ch.systemsx.cisd.common.logging.LogCategory;
 import ch.systemsx.cisd.common.logging.LogFactory;
 import ch.systemsx.cisd.common.shared.basic.utils.StringUtils;
 import ch.systemsx.cisd.etlserver.registrator.api.v2.IDataSetRegistrationTransactionV2;
+import ch.systemsx.cisd.openbis.dss.generic.server.ISessionWorkspaceProvider;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython.api.IDataSet;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.jython.api.IMailService;
 import ch.systemsx.cisd.openbis.dss.generic.shared.DataSetProcessingContext;
@@ -66,6 +67,8 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
     private final static String AUTHORIZATION_SERVICE = "authorizationService";
 
     private static final String CONTENT_PROVIDER_VARIABLE_NAME = "contentProvider";
+    
+    private static final String SESSION_WORKSPACE_PROVIDER_NAME = "sessionWorkspaceProvider";
 
     private final String scriptPath;
 
@@ -187,6 +190,11 @@ public class PluginScriptRunnerFactory implements IPluginScriptRunnerFactory
         evaluator.set(MAIL_SERVICE_VARIABLE_NAME, createMailService(context));
         evaluator.set(DATA_SOURCE_QUERY_SERVICE_VARIABLE_NAME, createDataSourceQueryService());
         evaluator.set(AUTHORIZATION_SERVICE, createAuthorizationService());
+        final ISessionWorkspaceProvider workspaceProvider = context.tryGetSessionWorkspaceProvider();
+        if (workspaceProvider != null)
+        {
+            evaluator.set(SESSION_WORKSPACE_PROVIDER_NAME, workspaceProvider);
+        }
         return evaluator;
     }
 
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java
index df99ca820842bb771d0340b8c7dc3fe569619e58..ca03d064ae3471e0065dc7857054ef3622318632 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/plugins/tasks/PluginTaskInfoProvider.java
@@ -37,6 +37,10 @@ public class PluginTaskInfoProvider
 {
     public static final String STOREROOT_DIR_KEY = "storeroot-dir";
 
+    private static final String SESSION_WORKSPACE_ROOT_DIR_KEY = "session-workspace-root-dir";
+
+    private static final String SESSION_WORKSPACE_ROOT_DIR_DEFAULT = "sessionWorkspace";
+
     /** name of archiver properties section */
     @Private
     static final String ARCHIVER_SECTION_NAME = "archiver";
@@ -49,6 +53,8 @@ public class PluginTaskInfoProvider
 
     private final File storeRoot;
 
+    private final File sessionWorkspaceRootDir;
+
     /** for external injections */
     public static PluginTaskInfoProvider create()
     {
@@ -56,8 +62,13 @@ public class PluginTaskInfoProvider
         Properties properties = DssPropertyParametersUtil.loadServiceProperties();
         final String storeRootDir = properties.getProperty(STOREROOT_DIR_KEY);
         final File storeRoot = new File(storeRootDir);
-        final PluginTaskInfoProvider providers =
-                new PluginTaskInfoProvider(properties, servletPropertiesManager, storeRoot);
+        final String workspaceRootDir =
+                properties.getProperty(SESSION_WORKSPACE_ROOT_DIR_KEY,
+                        SESSION_WORKSPACE_ROOT_DIR_DEFAULT);
+        final File workspaceRoot = new File(workspaceRootDir);
+        PluginTaskInfoProvider providers =
+                new PluginTaskInfoProvider(properties, servletPropertiesManager, storeRoot,
+                        workspaceRoot);
         providers.check();
         providers.logConfigurations();
         return providers;
@@ -66,9 +77,11 @@ public class PluginTaskInfoProvider
     @Private
     // public only for tests
     public PluginTaskInfoProvider(Properties serviceProperties,
-            IServletPropertiesManager servletPropertiesManager, File storeRoot)
+            IServletPropertiesManager servletPropertiesManager, File storeRoot,
+            File sessionWorkspaceRoot)
     {
         this.storeRoot = storeRoot;
+        this.sessionWorkspaceRootDir = sessionWorkspaceRoot;
         String datastoreCode = DssPropertyParametersUtil.getDataStoreCode(serviceProperties);
         this.reportingPlugins =
                 createReportingPluginsFactories(serviceProperties, servletPropertiesManager,
@@ -87,6 +100,14 @@ public class PluginTaskInfoProvider
         return storeRoot;
     }
 
+    /**
+     * Returns the root directory of session workspaces.
+     */
+    public File getSessionWorkspaceRootDir()
+    {
+        return sessionWorkspaceRootDir;
+    }
+
     public PluginTaskProvider<IReportingPluginTask> getReportingPluginsProvider()
     {
         return reportingPlugins;
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/DataSetProcessingContext.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/DataSetProcessingContext.java
index 233bdb72fa14705cd5caf37a51b22cba07d4c68d..b03d2264b9f49ec7ea869af7b9597993cd33291d 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/DataSetProcessingContext.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/shared/DataSetProcessingContext.java
@@ -19,6 +19,7 @@ package ch.systemsx.cisd.openbis.dss.generic.shared;
 import java.util.Map;
 
 import ch.systemsx.cisd.common.mail.IMailClient;
+import ch.systemsx.cisd.openbis.dss.generic.server.ISessionWorkspaceProvider;
 import ch.systemsx.cisd.openbis.dss.generic.server.plugins.tasks.IProcessingPluginTask;
 
 /**
@@ -40,6 +41,8 @@ public class DataSetProcessingContext
 
     private final String sessionTokenOrNull;
 
+    private final ISessionWorkspaceProvider sessionWorkspaceProviderOrNull;
+
     /**
      * Creates an instance for specified directory provider, parameter bindings, e-mail client, and
      * optional user e-mail address and sessionToken.
@@ -59,6 +62,20 @@ public class DataSetProcessingContext
     public DataSetProcessingContext(IHierarchicalContentProvider contentProvider,
             IDataSetDirectoryProvider directoryProvider, Map<String, String> parameterBindings,
             IMailClient mailClient, String userEmailOrNull, String sessionTokenOrNull)
+    {
+        this(contentProvider, directoryProvider, null, parameterBindings, mailClient,
+                userEmailOrNull, sessionTokenOrNull);
+    }
+
+    /**
+     * Creates an instance for specified directory provider, workspace provider, parameter bindings,
+     * e-mail client, and optional user e-mail address and sessionToken.
+     */
+    public DataSetProcessingContext(IHierarchicalContentProvider contentProvider,
+            IDataSetDirectoryProvider directoryProvider,
+            ISessionWorkspaceProvider sessionWorkspaceProviderOrNull,
+            Map<String, String> parameterBindings,
+            IMailClient mailClient, String userEmailOrNull, String sessionTokenOrNull)
     {
         this.hierarchicalContentProvider = contentProvider;
         this.directoryProvider = directoryProvider;
@@ -66,6 +83,7 @@ public class DataSetProcessingContext
         this.mailClient = mailClient;
         this.userEmailOrNull = userEmailOrNull;
         this.sessionTokenOrNull = sessionTokenOrNull;
+        this.sessionWorkspaceProviderOrNull = sessionWorkspaceProviderOrNull;
     }
 
     public IDataSetDirectoryProvider getDirectoryProvider()
@@ -73,6 +91,15 @@ public class DataSetProcessingContext
         return directoryProvider;
     }
 
+    /**
+     * Returns the session workspace provider of this context, if available and <code>null</code> if
+     * this context has no session workspace provider.
+     */
+    public ISessionWorkspaceProvider tryGetSessionWorkspaceProvider()
+    {
+        return sessionWorkspaceProviderOrNull;
+    }
+
     public final Map<String, String> getParameterBindings()
     {
         return parameterBindings;
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
index e220ade5f280a08bb8a7704e2d23224ba21c43c3..41e7812e8ea2d94098c7fa2eafeeb510c5ca34e7 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/CommonBusinessObjectFactory.java
@@ -32,7 +32,6 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.ExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.GridCustomColumnBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.GridCustomFilterBO;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.SpaceBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IAttachmentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IAuthorizationGroupBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ICommonBusinessObjectFactory;
@@ -47,7 +46,6 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IEntityTypePropertyTy
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IExperimentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IGridCustomFilterOrColumnBO;
-import ch.systemsx.cisd.openbis.generic.server.business.bo.ISpaceBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IMaterialTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IProjectBO;
@@ -57,6 +55,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.IRoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ISampleTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IScriptBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.ISpaceBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ITrashBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.IVocabularyTermBO;
@@ -69,6 +68,7 @@ import ch.systemsx.cisd.openbis.generic.server.business.bo.RoleAssignmentTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.SampleBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.SampleTable;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.ScriptBO;
+import ch.systemsx.cisd.openbis.generic.server.business.bo.SpaceBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.TrashBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.VocabularyBO;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.VocabularyTermBO;
@@ -94,10 +94,20 @@ public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFac
         ICommonBusinessObjectFactory
 {
 
+    private final DataStoreUserSessionCleaner dssUserSessionCleaner;
+
     public CommonBusinessObjectFactory(IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory,
-            IRelationshipService relationshipService, IEntityOperationChecker entityOperationChecker)
+            IRelationshipService relationshipService,
+            IEntityOperationChecker entityOperationChecker,
+            DataStoreUserSessionCleaner dssUserSessionCleaner)
     {
         super(daoFactory, dssFactory, relationshipService, entityOperationChecker);
+        this.dssUserSessionCleaner = dssUserSessionCleaner;
+    }
+
+    protected DataStoreUserSessionCleaner getDssUserSessionCleaner()
+    {
+        return dssUserSessionCleaner;
     }
 
     @Override
@@ -165,7 +175,8 @@ public final class CommonBusinessObjectFactory extends AbstractBusinessObjectFac
     @Override
     public final IDataSetTable createDataSetTable(final Session session)
     {
-        return new DataSetTable(getDaoFactory(), getDSSFactory(), session, getRelationshipService());
+        return new DataSetTable(getDaoFactory(), getDSSFactory(), getDssUserSessionCleaner(),
+                session, getRelationshipService());
     }
 
     @Override
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DataStoreUserSessionCleaner.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DataStoreUserSessionCleaner.java
new file mode 100644
index 0000000000000000000000000000000000000000..73b650fbb1a306ed97dc0bcb31a8994eca703c19
--- /dev/null
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/DataStoreUserSessionCleaner.java
@@ -0,0 +1,69 @@
+/*
+ * Copyright 2012 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.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import ch.systemsx.cisd.openbis.generic.shared.IDataStoreService;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session;
+import ch.systemsx.cisd.openbis.generic.shared.dto.Session.ISessionCleaner;
+
+/**
+ * A cleaner for user session data on data store servers.
+ * 
+ * @author Bernd Rinn
+ */
+public class DataStoreUserSessionCleaner
+{
+
+    private final Map<String, List<IDataStoreService>> sessions =
+            new HashMap<String, List<IDataStoreService>>();
+
+    public void add(Session userSession, IDataStoreService dataStore)
+    {
+        final String userSessionToken = userSession.getSessionToken();
+        final List<IDataStoreService> dataStores = getOrCreateDataStores(userSessionToken);
+        dataStores.add(dataStore);
+        userSession.addCleanupListener(new ISessionCleaner()
+            {
+                @Override
+                public void cleanup()
+                {
+                    for (IDataStoreService service : dataStores)
+                    {
+                        service.cleanupSession(userSessionToken);
+                    }
+                    sessions.remove(userSessionToken);
+                }
+            });
+    }
+
+    private List<IDataStoreService> getOrCreateDataStores(String userSessionToken)
+    {
+        List<IDataStoreService> dataStores = sessions.get(userSessionToken);
+        if (dataStores == null)
+        {
+            dataStores = new ArrayList<IDataStoreService>();
+            sessions.put(userSessionToken, dataStores);
+        }
+        return dataStores;
+    }
+
+}
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java
index 1f57f31a80f1a2a544e44d1a86d92ff55c06e254..4a0538576f4ef49d7d1783eac220cce4dc3cbc1d 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTable.java
@@ -43,6 +43,7 @@ import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 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.DataStoreUserSessionCleaner;
 import ch.systemsx.cisd.openbis.generic.server.business.IDataStoreServiceFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.exception.DataSetDeletionDisallowedTypesException;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.exception.DataSetDeletionUnknownLocationsException;
@@ -197,11 +198,15 @@ public final class DataSetTable extends AbstractDataSetBusinessObject implements
 
     private List<DataPE> dataSets;
 
-    public DataSetTable(final IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory,
-            final Session session, IRelationshipService relationshipService)
+    private final DataStoreUserSessionCleaner dssUserSessionCleaner;
+
+    public DataSetTable(IDAOFactory daoFactory, IDataStoreServiceFactory dssFactory,
+            DataStoreUserSessionCleaner dssUserSessionCleaner,
+            Session session, IRelationshipService relationshipService)
     {
         super(daoFactory, session, relationshipService);
         this.dssFactory = dssFactory;
+        this.dssUserSessionCleaner = dssUserSessionCleaner;
     }
 
     //
@@ -596,6 +601,7 @@ public final class DataSetTable extends AbstractDataSetBusinessObject implements
         List<DatasetDescription> locations = loadAvailableDatasetDescriptions(datasetCodes);
         String sessionToken = dataStore.getSessionToken();
         String userSessionToken = session.getSessionToken();
+        dssUserSessionCleaner.add(session, service);
         return service.createReportFromDatasets(sessionToken, userSessionToken,
                 datastoreServiceKey, locations, tryGetLoggedUserEmail());
     }
@@ -1050,6 +1056,7 @@ public final class DataSetTable extends AbstractDataSetBusinessObject implements
         }
         String sessionToken = dataStore.getSessionToken();
         String userSessionToken = session.getSessionToken();
+        dssUserSessionCleaner.add(session, service);
         return service.createReportFromAggregationService(sessionToken, userSessionToken,
                 datastoreServiceKey, parameters, tryGetLoggedUserEmail());
     }
diff --git a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
index b57331150e6f8887dc9750a72dca9fa7d3de6a72..a6be88f2faa7f2ac9a8daf1ee7ddbcc53b354535 100644
--- a/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
+++ b/openbis/source/java/ch/systemsx/cisd/openbis/generic/shared/IDataStoreService.java
@@ -39,7 +39,7 @@ public interface IDataStoreService
     /**
      * Every time this interface and related DTO's are changed, we should increment this number.
      */
-    public static final int VERSION = 7; // for release 131
+    public static final int VERSION = 8; // for release 137
 
     /**
      * Returns the version of this service.
@@ -83,7 +83,12 @@ public interface IDataStoreService
     public void uploadDataSetsToCIFEX(String sessionToken, List<ExternalData> dataSets,
             DataSetUploadContext context) throws InvalidAuthenticationException;
 
-    /** Runs the reporting task with the specified id for provided datasets */
+    /**
+     * Runs the reporting task with the specified id for provided datasets.
+     * <p>
+     * <i> Ensure that you call {@link #cleanupSession(String)} on closing of the user sesssion
+     * <var>userSessionToken</var> so that DSS gets the chance to cleanup session files. </i>
+     */
     public TableModel createReportFromDatasets(String sessionToken, String userSessionToken,
             String serviceKey, List<DatasetDescription> datasets, String userEmailOrNull);
 
@@ -138,6 +143,9 @@ public interface IDataStoreService
 
     /**
      * Gets the link from a service that supports the IReportingPluginTask#createLink method.
+     * <p>
+     * <i> Ensure that you call {@link #cleanupSession(String)} on closing of the user sesssion
+     * <var>userSessionToken</var> so that DSS gets the chance to cleanup session files. </i>
      * 
      * @param sessionToken The sessionToken.
      * @param userSessionToken The session token of the user that initiated the processing.
@@ -152,4 +160,12 @@ public interface IDataStoreService
 
     public String putDataSet(String sessionToken, String dropboxName,
             CustomImportFile customImportFile);
+
+    /**
+     * Cleans up the user session with given <var>userSessionToken</var>.
+     * 
+     * @since 8
+     */
+    public void cleanupSession(String userSessionToken);
+
 }
diff --git a/openbis/source/java/genericApplicationContext.xml b/openbis/source/java/genericApplicationContext.xml
index 50f4e2d6be4941424b4b209d542283402678f897..7ceb626655308b2c6f1cc4ee6ef3b5609025e91a 100644
--- a/openbis/source/java/genericApplicationContext.xml
+++ b/openbis/source/java/genericApplicationContext.xml
@@ -49,6 +49,8 @@
     
     <bean id="dss-factory" class="ch.systemsx.cisd.openbis.generic.server.business.DataStoreServiceFactory"/>
 
+		<bean id="dss-user-session-cleaner" class="ch.systemsx.cisd.openbis.generic.server.DataStoreUserSessionCleaner" />
+
     <bean id="authentication-service"
         class="ch.systemsx.cisd.openbis.generic.server.AuthenticationServiceHolder">
         <constructor-arg ref="${authentication-service}" />
@@ -83,6 +85,7 @@
         <constructor-arg ref="dss-factory" />
         <constructor-arg ref="relationship-service" />
         <constructor-arg ref="entity-operation-checker" />
+        <constructor-arg ref="dss-user-session-cleaner" />
     </bean>
 
     <bean id="last-modification-state"
diff --git a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java
index 75d4d8db2ff37a0c0bbe8afc505b40f4189c34e3..9367c1e603453e8b1dc7dd180bc86bdb2ca8ca53 100644
--- a/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java
+++ b/openbis/sourceTest/java/ch/systemsx/cisd/openbis/generic/server/business/bo/DataSetTableTest.java
@@ -39,6 +39,7 @@ import org.testng.annotations.Test;
 
 import ch.rinn.restrictions.Friend;
 import ch.systemsx.cisd.common.exceptions.UserFailureException;
+import ch.systemsx.cisd.openbis.generic.server.DataStoreUserSessionCleaner;
 import ch.systemsx.cisd.openbis.generic.server.business.IDataStoreServiceFactory;
 import ch.systemsx.cisd.openbis.generic.server.business.ManagerTestTool;
 import ch.systemsx.cisd.openbis.generic.server.business.bo.exception.DataSetDeletionUnknownLocationsException;
@@ -79,6 +80,8 @@ public final class DataSetTableTest extends AbstractBOTest
 {
     private IDataStoreServiceFactory dssFactory;
 
+    private DataStoreUserSessionCleaner dssUserSessionCleaner;
+
     private DataStorePE dss1;
 
     private DataStorePE dss2;
@@ -93,8 +96,8 @@ public final class DataSetTableTest extends AbstractBOTest
 
     private final DataSetTable createDataSetTable()
     {
-        return new DataSetTable(daoFactory, dssFactory, ManagerTestTool.EXAMPLE_SESSION,
-                relationshipService);
+        return new DataSetTable(daoFactory, dssFactory, dssUserSessionCleaner,
+                ManagerTestTool.EXAMPLE_SESSION, relationshipService);
     }
 
     @BeforeMethod
@@ -103,6 +106,7 @@ public final class DataSetTableTest extends AbstractBOTest
     {
         super.beforeMethod();
         dssFactory = context.mock(IDataStoreServiceFactory.class);
+        dssUserSessionCleaner = new DataStoreUserSessionCleaner();
         dss1 = createDataStore("dss1", false);
         dss2 = createDataStore("dss2", true);
         dss3 = createDataStore("dss3", true);
@@ -546,8 +550,8 @@ public final class DataSetTableTest extends AbstractBOTest
         final ExternalDataPE d3Available = createDataSet("d3a", dss3, AVAILABLE);
         final ExternalDataPE d3NonAvailable = createDataSet("d3n", dss3, ARCHIVED);
         final ExternalDataPE[] allDataSets =
-                    { d2Available1, d2Available2, d2NonAvailable1, d2NonAvailable2, d3Available,
-                            d3NonAvailable, d2NonAvailable3 };
+            { d2Available1, d2Available2, d2NonAvailable1, d2NonAvailable2, d3Available,
+                    d3NonAvailable, d2NonAvailable3 };
         context.checking(new Expectations()
             {
                 {
@@ -581,8 +585,8 @@ public final class DataSetTableTest extends AbstractBOTest
         final ExternalDataPE d3Archived = createDataSet("d3a", dss3, ARCHIVED);
         final ExternalDataPE d3NonArchived = createDataSet("d3n", dss3, AVAILABLE);
         final ExternalDataPE[] allDataSets =
-                    { d2Archived1, d2Archived2, d2NonArchived1, d2NonArchived2, d3Archived,
-                            d3NonArchived, d2NonAvailable3 };
+            { d2Archived1, d2Archived2, d2NonArchived1, d2NonArchived2, d3Archived,
+                    d3NonArchived, d2NonAvailable3 };
         context.checking(new Expectations()
             {
                 {