From 4a61e56f6b108e276997a1cd7149017df53708b8 Mon Sep 17 00:00:00 2001
From: cramakri <cramakri>
Date: Thu, 1 Apr 2010 14:04:35 +0000
Subject: [PATCH] LMS-1465 Added support for downloading files.

SVN: 15331
---
 .../openbis/dss/component/IDssComponent.java  |  3 +-
 .../dss/component/impl/DssComponent.java      | 16 ++++++----
 .../generic/server/AbstractDssServiceRpc.java | 30 +++++++++++++++++
 .../dss/generic/server/DssServiceRpcV1.java   | 24 +++++++++-----
 .../dss/rpc/shared/IDssServiceRpcV1.java      | 19 ++++++++++-
 .../generic/server/DssServiceRpcV1Test.java   | 32 +++++++++++++++++--
 6 files changed, 104 insertions(+), 20 deletions(-)

diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java
index 96f8b09868b..66f48fc979a 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/IDssComponent.java
@@ -19,7 +19,6 @@ package ch.systemsx.cisd.openbis.dss.component;
 import ch.systemsx.cisd.common.exceptions.AuthorizationFailureException;
 import ch.systemsx.cisd.common.exceptions.EnvironmentFailureException;
 import ch.systemsx.cisd.common.exceptions.InvalidSessionException;
-import ch.systemsx.cisd.common.exceptions.UserFailureException;
 
 /**
  * A component that manages a connection to openBIS and 1 or more data store servers.
@@ -62,7 +61,7 @@ public interface IDssComponent
      * @throws EnvironmentFailureException Thrown in cases where it is not possible to connect to
      *             the server.
      */
-    public IDataSetDss getDataSet(String code) throws UserFailureException,
+    public IDataSetDss getDataSet(String code) throws IllegalStateException,
             EnvironmentFailureException;
 
     /**
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java
index 41cb4f15ced..a18a5261a8e 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/component/impl/DssComponent.java
@@ -95,7 +95,8 @@ public class DssComponent implements IDssComponent
         state.checkSession();
     }
 
-    public IDataSetDss getDataSet(String code)
+    public IDataSetDss getDataSet(String code) throws EnvironmentFailureException,
+            IllegalStateException
     {
         return state.getDataSet(code);
     }
@@ -125,14 +126,14 @@ abstract class AbstractDssComponentState implements IDssComponent
         this.service = service;
     }
 
-    public void checkSession() throws InvalidSessionException
+    public void checkSession() throws IllegalStateException
     {
-        throw new UserFailureException("Please log in");
+        throw new IllegalStateException("Please log in");
     }
 
-    public IDataSetDss getDataSet(String code)
+    public IDataSetDss getDataSet(String code) throws IllegalStateException
     {
-        throw new UserFailureException("Please log in");
+        throw new IllegalStateException("Please log in");
     }
 
     /**
@@ -265,9 +266,10 @@ class AuthenticatedState extends AbstractDssComponentState
      * Package visible method to communicate with the server and get a list of files contained in
      * this data set.
      */
-    InputStream getFile(DataSetDss dataSet, String path) throws InvalidSessionException
+    InputStream getFile(DataSetDss dataSetDss, String path) throws InvalidSessionException
     {
-        return null;
+        return dataSetDss.getService().getFileForDataSet(getSessionToken(), dataSetDss.getCode(),
+                path);
     }
 
     /**
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java
index d3b736b9de0..0e89b995bb2 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/AbstractDssServiceRpc.java
@@ -17,6 +17,7 @@
 package ch.systemsx.cisd.openbis.dss.generic.server;
 
 import java.io.File;
+import java.io.IOException;
 
 import org.apache.log4j.Logger;
 
@@ -129,4 +130,33 @@ public abstract class AbstractDssServiceRpc
         return dataSetRootDirectory;
     }
 
+    protected File checkAccessAndGetRootDirectory(String sessionToken, String dataSetCode)
+            throws IllegalArgumentException
+    {
+        if (isDatasetAccessible(sessionToken, dataSetCode) == false)
+            throw new IllegalArgumentException("Path does not exist.");
+
+        File dataSetRootDirectory = getRootDirectoryForDataSet(dataSetCode);
+        if (dataSetRootDirectory.exists() == false)
+        {
+            throw new IllegalArgumentException("Path does not exist.");
+        }
+
+        return dataSetRootDirectory;
+    }
+
+    protected File checkAccessAndGetFile(String sessionToken, String dataSetCode, String path)
+            throws IOException, IllegalArgumentException
+    {
+        File dataSetRootDirectory = checkAccessAndGetRootDirectory(sessionToken, dataSetCode);
+
+        String dataSetRootPath = dataSetRootDirectory.getCanonicalPath();
+        File requestedFile = new File(dataSetRootDirectory, path);
+        // Make sure the requested file is under the root of the data set
+        if (requestedFile.getCanonicalPath().startsWith(dataSetRootPath) == false)
+        {
+            throw new IllegalArgumentException("Path does not exist.");
+        }
+        return requestedFile;
+    }
 }
\ No newline at end of file
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1.java
index 7ed056635e1..1e8f74fe909 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1.java
@@ -17,7 +17,9 @@
 package ch.systemsx.cisd.openbis.dss.generic.server;
 
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.util.ArrayList;
 
 import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked;
@@ -40,14 +42,7 @@ public class DssServiceRpcV1 extends AbstractDssServiceRpc implements IDssServic
     public FileInfoDss[] listFilesForDataSet(String sessionToken, String dataSetCode,
             String startPath, boolean isRecursive) throws IllegalArgumentException
     {
-        if (isDatasetAccessible(sessionToken, dataSetCode) == false)
-            throw new IllegalArgumentException("Path does not exist.");
-
-        File dataSetRootDirectory = getRootDirectoryForDataSet(dataSetCode);
-        if (dataSetRootDirectory.exists() == false)
-        {
-            throw new IllegalArgumentException("Path does not exist.");
-        }
+        File dataSetRootDirectory = checkAccessAndGetRootDirectory(sessionToken, dataSetCode);
 
         try
         {
@@ -71,6 +66,19 @@ public class DssServiceRpcV1 extends AbstractDssServiceRpc implements IDssServic
         }
     }
 
+    public InputStream getFileForDataSet(String sessionToken, String dataSetCode, String path)
+            throws IOExceptionUnchecked, IllegalArgumentException
+    {
+        try
+        {
+            File requestedFile = checkAccessAndGetFile(sessionToken, dataSetCode, path);
+            return new FileInputStream(requestedFile);
+        } catch (IOException ex)
+        {
+            throw new IOExceptionUnchecked(ex);
+        }
+    }
+
     public int getMinClientVersion()
     {
         return 1;
diff --git a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java
index b2cd04b87c1..186dae891b2 100644
--- a/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java
+++ b/datastore_server/source/java/ch/systemsx/cisd/openbis/dss/rpc/shared/IDssServiceRpcV1.java
@@ -16,6 +16,10 @@
 
 package ch.systemsx.cisd.openbis.dss.rpc.shared;
 
+import java.io.InputStream;
+
+import ch.systemsx.cisd.base.exceptions.IOExceptionUnchecked;
+
 /**
  * @author Chandrasekhar Ramakrishnan
  */
@@ -29,7 +33,20 @@ public interface IDssServiceRpcV1 extends IDssServiceRpc
 
     /**
      * Get an array of FileInfoDss objects that describe the file-system structure of the data set.
+     * 
+     * @throws IOExceptionUnchecked Thrown if an IOException occurs when listing the files
+     * @throws IllegalArgumentException Thrown if the dataSetCode or startPath are not valid
      */
     public FileInfoDss[] listFilesForDataSet(String sessionToken, String dataSetCode,
-            String startPath, boolean isRecursive) throws IllegalArgumentException;
+            String startPath, boolean isRecursive) throws IOExceptionUnchecked,
+            IllegalArgumentException;
+
+    /**
+     * Get an array of FileInfoDss objects that describe the file-system structure of the data set.
+     * 
+     * @throws IOExceptionUnchecked Thrown if an IOException occurs when listing the files
+     * @throws IllegalArgumentException Thrown if the dataSetCode or startPath are not valid
+     */
+    public InputStream getFileForDataSet(String sessionToken, String dataSetCode, String startPath)
+            throws IOExceptionUnchecked, IllegalArgumentException;
 }
diff --git a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java
index 241b0634ef4..2f86a667bc5 100644
--- a/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java
+++ b/datastore_server/sourceTest/java/ch/systemsx/cisd/openbis/dss/generic/server/DssServiceRpcV1Test.java
@@ -16,10 +16,12 @@
 
 package ch.systemsx.cisd.openbis.dss.generic.server;
 
+import java.io.BufferedReader;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
-import java.util.Arrays;
 
 import org.jmock.Expectations;
 import org.jmock.Mockery;
@@ -221,7 +223,6 @@ public class DssServiceRpcV1Test extends AbstractFileSystemTestCase
         setupStandardExpectations();
         FileInfoDss[] fileInfos =
                 rpcService.listFilesForDataSet(SESSION_TOKEN, DATA_SET_CODE, "stuff/", false);
-        System.err.println(Arrays.toString(fileInfos));
         assertEquals(2, fileInfos.length);
 
         context.assertIsSatisfied();
@@ -275,4 +276,31 @@ public class DssServiceRpcV1Test extends AbstractFileSystemTestCase
 
         context.assertIsSatisfied();
     }
+
+    @Test
+    public void testDataSetFileRetrieval() throws IOException
+    {
+        setupStandardExpectations();
+        FileInfoDss[] fileInfos =
+                rpcService
+                        .listFilesForDataSet(SESSION_TOKEN, DATA_SET_CODE, "stuff/bar.txt", false);
+        assertEquals(1, fileInfos.length);
+
+        InputStream is =
+                rpcService.getFileForDataSet(SESSION_TOKEN, DATA_SET_CODE, fileInfos[0].getPath());
+
+        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+        int readChar;
+        int charCount = 0;
+        while ((readChar = reader.read()) >= 0)
+        {
+            // Wrote many 'a' characters into the file
+            assertEquals(97, readChar);
+            ++charCount;
+        }
+
+        assertEquals(fileInfos[0].getFileSize(), charCount);
+
+        context.assertIsSatisfied();
+    }
 }
-- 
GitLab