From 189d9c5027ada705cc272bac97bb4ce2a1bf6e84 Mon Sep 17 00:00:00 2001
From: pkupczyk <piotr.kupczyk@id.ethz.ch>
Date: Mon, 25 Mar 2024 16:17:49 +0100
Subject: [PATCH] SSDM-13578 : 2PT : Database and V3 Implementation - js facade

---
 .../ch/ethz/sis/openbis/generic/OpenBIS.java  | 29 ++++++++-
 api-openbis-javascript/build.gradle           |  6 +-
 api-openbis-javascript/src/v3/config.js       |  8 ++-
 api-openbis-javascript/src/v3/openbis.js      | 43 +++++++++++++-
 .../dto/OpenBISJavaScriptAFSFacade.java       | 59 +++++++++++++++++++
 .../dto/OpenBISJavaScriptFacade.java          |  5 ++
 .../systemtests/Integration2PCTest.java       | 42 ++++---------
 7 files changed, 157 insertions(+), 35 deletions(-)
 create mode 100644 api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptAFSFacade.java

diff --git a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java
index 0aae5473b04..b237e4fe939 100644
--- a/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java
+++ b/api-openbis-java/source/java/ch/ethz/sis/openbis/generic/OpenBIS.java
@@ -24,6 +24,7 @@ import java.io.InputStream;
 import java.lang.reflect.Proxy;
 import java.net.URI;
 import java.nio.file.Path;
+import java.security.MessageDigest;
 import java.util.Calendar;
 import java.util.Date;
 import java.util.Iterator;
@@ -1445,6 +1446,17 @@ public class OpenBIS
     public class AfsServerFacade
     {
 
+        private final MessageDigest digest;
+
+        private AfsServerFacade() {
+            try
+            {
+                this.digest = MessageDigest.getInstance("MD5");
+            } catch (Exception e){
+                throw new RuntimeException("Could not create afs server facade", e);
+            }
+        }
+
         public List<ch.ethz.sis.afsapi.dto.File> list(String owner, String source, Boolean recursively)
         {
             try
@@ -1473,11 +1485,11 @@ public class OpenBIS
             }
         }
 
-        public Boolean write(String owner, String source, Long offset, byte[] data, byte[] md5Hash)
+        public Boolean write(String owner, String source, Long offset, byte[] data)
         {
             try
             {
-                return afsClientWithTransactions.write(owner, source, offset, data, md5Hash);
+                return afsClientWithTransactions.write(owner, source, offset, data, calculateMD5(data));
             } catch (RuntimeException e)
             {
                 throw e;
@@ -1543,6 +1555,19 @@ public class OpenBIS
             }
         }
 
+        private byte[] calculateMD5(byte[] data)
+        {
+            try
+            {
+                digest.reset();
+                digest.update(data);
+                return digest.digest();
+            } catch (Exception e)
+            {
+                throw new RuntimeException("Checksum calculation failed", e);
+            }
+        }
+
     }
 
     //
diff --git a/api-openbis-javascript/build.gradle b/api-openbis-javascript/build.gradle
index 483e5d844e5..a22cde3329f 100644
--- a/api-openbis-javascript/build.gradle
+++ b/api-openbis-javascript/build.gradle
@@ -11,8 +11,12 @@ node {
     nodeModulesDir = file("${projectDir}")
 }
 
+task copyAfsApi(type: Copy) {
+    from("${project(':api-data-store-server-javascript').projectDir}/src/js/api")
+    into file('src/v3/afs')
+}
 
-task bundleOpenbisStaticResources(type: Exec) {
+task bundleOpenbisStaticResources(type: Exec, dependsOn: copyAfsApi) {
     dependsOn 'npmInstall'
     commandLine 'bash', '-c', "${projectDir}/bin/build.sh"
 }
diff --git a/api-openbis-javascript/src/v3/config.js b/api-openbis-javascript/src/v3/config.js
index 3ff93336411..0453c2d6d4c 100644
--- a/api-openbis-javascript/src/v3/config.js
+++ b/api-openbis-javascript/src/v3/config.js
@@ -27,7 +27,9 @@ var require = (function() {
 			// "openbis" : "../../js/openbis",
 			"openbis-screening" : "../../js/openbis-screening",
 			"bootstrap" : "../../lib/bootstrap/js/bootstrap.min",
-			"bootstrap-slider" : "../../lib/bootstrap-slider/js/bootstrap-slider.min"
+			"bootstrap-slider" : "../../lib/bootstrap-slider/js/bootstrap-slider.min",
+			"afs" : "afs/server-data-store-facade",
+			"afs-md5" : "afs/md5"
 		},
 		shim : {
 			"stjs" : {
@@ -45,6 +47,10 @@ var require = (function() {
 			"openbis-screening" : {
 				deps : [ "openbis" ],
 				exports : "openbis"
+			},
+			"afs" : {
+				deps : [ "afs-md5" ],
+				exports : "DataStoreServer"
 			}
 		}
 	}
diff --git a/api-openbis-javascript/src/v3/openbis.js b/api-openbis-javascript/src/v3/openbis.js
index fa10067c89b..f9c7525030f 100644
--- a/api-openbis-javascript/src/v3/openbis.js
+++ b/api-openbis-javascript/src/v3/openbis.js
@@ -1,6 +1,6 @@
 define([ 'jquery', 'util/Json', 'as/dto/datastore/search/DataStoreSearchCriteria', 'as/dto/datastore/fetchoptions/DataStoreFetchOptions',
-	'as/dto/common/search/SearchResult'], function(jquery,
-		stjsUtil, DataStoreSearchCriteria, DataStoreFetchOptions, SearchResult) {
+	'as/dto/common/search/SearchResult', 'afs'], function(jquery,
+		stjsUtil, DataStoreSearchCriteria, DataStoreFetchOptions, SearchResult, afs) {
 	jquery.noConflict();
 
 	var __private = function() {
@@ -435,6 +435,41 @@ define([ 'jquery', 'util/Json', 'as/dto/datastore/search/DataStoreSearchCriteria
 		}
 	}
 
+    var afsServerFacade = function(asFacade) {
+
+        this.afsServer = new DataStoreServer("http://localhost:8085", "/data-store-server");
+        this.afsServer.useSession(asFacade._private.sessionToken)
+
+		this.list = function(owner, source, recursively) {
+		    return this.afsServer.list(owner, source, recursively);
+		}
+
+		this.read = function(owner, source, offset, limit){
+		    return this.afsServer.read(owner, source, offset, limit);
+		}
+
+		this.write = function(owner, source, offset, data){
+		    return this.afsServer.write(owner, source, offset, data);
+		}
+
+		this.delete = function(owner, source){
+		    return this.afsServer.delete(owner, source)
+		}
+
+		this.copy = function(sourceOwner, source, targetOwner, target){
+		    return this.afsServer.copy(sourceOwner, source, targetOwner, target);
+		}
+
+		this.move = function(sourceOwner, source, targetOwner, target){
+		    return this.afsServer.move(sourceOwner, source, targetOwner, target);
+		}
+
+		this.create = function(owner, source, directory){
+		    return this.afsServer.create(owner, source, directory);
+		}
+
+	}
+
 	var facade = function(openbisUrl) {
 
 		if (!openbisUrl) {
@@ -2422,6 +2457,10 @@ define([ 'jquery', 'util/Json', 'as/dto/datastore/search/DataStoreSearchCriteria
 			return new dataStoreFacade(this, dataStoreCodes);
 		}
 
+		this.getAfsServerFacade = function() {
+            return new afsServerFacade(this)
+		}
+
 		this.getMajorVersion = function() {
 			var thisFacade = this;
 			return thisFacade._private.ajaxRequest({
diff --git a/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptAFSFacade.java b/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptAFSFacade.java
new file mode 100644
index 00000000000..94f4d92b57d
--- /dev/null
+++ b/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptAFSFacade.java
@@ -0,0 +1,59 @@
+package ch.ethz.sis.openbis.generic.typescript.dto;
+
+import java.util.List;
+
+import ch.ethz.sis.afsapi.dto.File;
+import ch.ethz.sis.openbis.generic.typescript.TypeScriptMethod;
+import ch.ethz.sis.openbis.generic.typescript.TypeScriptObject;
+
+@TypeScriptObject
+public class OpenBISJavaScriptAFSFacade
+{
+
+    private OpenBISJavaScriptAFSFacade()
+    {
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public List<File> list(final String owner, final String source, final Boolean recursively)
+    {
+        return null;
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public byte[] read(final String source, final long offset, final int limit)
+    {
+        return null;
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public boolean write(final String source, final long offset, final byte[] data)
+    {
+        return false;
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public boolean delete(final String source)
+    {
+        return false;
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public boolean copy(final String source, final String target)
+    {
+        return false;
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public boolean move(final String source, final String target)
+    {
+        return false;
+    }
+
+    @TypeScriptMethod(sessionToken = false)
+    public boolean create(final String source, final boolean directory)
+    {
+        return false;
+    }
+
+}
diff --git a/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptFacade.java b/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptFacade.java
index 6aacab7c077..ca7f282643d 100644
--- a/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptFacade.java
+++ b/api-openbis-typescript/source/java/ch/ethz/sis/openbis/generic/typescript/dto/OpenBISJavaScriptFacade.java
@@ -266,6 +266,11 @@ public class OpenBISJavaScriptFacade implements IApplicationServerApi
         return null;
     }
 
+    @TypeScriptMethod(sessionToken = false, async = false)
+    public OpenBISJavaScriptAFSFacade getAfsServerFacade(){
+        return null;
+    }
+
     @TypeScriptMethod(sessionToken = false, async = false)
     public OpenBISJavaScriptDSSFacade getDataStoreFacade(String[] dataStoreCodes){
         return null;
diff --git a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java
index 10fc4da8bb0..3eff5485a83 100644
--- a/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java
+++ b/test-integration/sourceTest/java/ch/ethz/sis/openbis/systemtests/Integration2PCTest.java
@@ -10,7 +10,6 @@ import static org.testng.Assert.fail;
 
 import java.lang.reflect.Method;
 import java.nio.charset.StandardCharsets;
-import java.security.MessageDigest;
 import java.sql.Connection;
 import java.sql.ResultSet;
 import java.sql.Statement;
@@ -90,10 +89,10 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBISWithTr.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBISWithTr.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBISWithTr.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         WriteData writeData2 = createWriteData();
-        openBISWithTr.getAfsServerFacade().write(writeData2.owner, writeData2.source, 0L, writeData2.bytes, writeData2.md5);
+        openBISWithTr.getAfsServerFacade().write(writeData2.owner, writeData2.source, 0L, writeData2.bytes);
 
         SpaceCreation spaceCreation = createSpaceCreation();
         SpacePermId spaceId = openBISWithTr.createSpaces(List.of(spaceCreation)).get(0);
@@ -379,7 +378,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBIS.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -451,7 +450,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         try
         {
             // first attempt
-            openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+            openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
             fail();
         } catch (Exception e)
         {
@@ -466,7 +465,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         setAfsServerProxyInterceptor((method, defaultAction) -> defaultAction.call());
 
         // second attempt
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         openBIS.commitTransaction();
 
@@ -527,7 +526,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBIS.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -587,7 +586,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBIS.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -664,7 +663,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBIS.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -717,7 +716,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBIS.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -846,7 +845,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         UUID transactionId = openBISWithTr.beginTransaction();
 
         WriteData writeData = createWriteData();
-        openBISWithTr.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBISWithTr.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -919,7 +918,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
         SpacePermId spaceId = openBIS.createSpaces(List.of(spaceCreation)).get(0);
 
         WriteData writeData = createWriteData();
-        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes, writeData.md5);
+        openBIS.getAfsServerFacade().write(writeData.owner, writeData.source, 0L, writeData.bytes);
 
         assertTransactions(getTransactionCoordinator().getTransactionMap(), new TestTransaction(transactionId, TransactionStatus.BEGIN_FINISHED));
 
@@ -987,7 +986,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
 
         WriteData writeDataCommitted = createWriteData();
         openBISWithCommittedTransaction.getAfsServerFacade()
-                .write(writeDataCommitted.owner, writeDataCommitted.source, 0L, writeDataCommitted.bytes, writeDataCommitted.md5);
+                .write(writeDataCommitted.owner, writeDataCommitted.source, 0L, writeDataCommitted.bytes);
 
         openBISWithCommittedTransaction.commitTransaction();
 
@@ -1003,7 +1002,7 @@ public class Integration2PCTest extends AbstractIntegrationTest
 
         WriteData writeDataNotCommitted = createWriteData();
         openBISWithNotCommittedTransaction.getAfsServerFacade()
-                .write(writeDataNotCommitted.owner, writeDataNotCommitted.source, 0L, writeDataNotCommitted.bytes, writeDataNotCommitted.md5);
+                .write(writeDataNotCommitted.owner, writeDataNotCommitted.source, 0L, writeDataNotCommitted.bytes);
 
         // let's wait for the task that tries to finish failed or abandoned transactions runs
         Thread.sleep(WAITING_TIME_FOR_FINISHING_TRANSACTIONS);
@@ -1140,23 +1139,9 @@ public class Integration2PCTest extends AbstractIntegrationTest
         writeData.source = "test-source-" + UUID.randomUUID();
         writeData.content = "test-content-" + UUID.randomUUID();
         writeData.bytes = writeData.content.getBytes(StandardCharsets.UTF_8);
-        writeData.md5 = calculateMD5(writeData.bytes);
         return writeData;
     }
 
-    private static byte[] calculateMD5(byte[] data)
-    {
-        try
-        {
-            MessageDigest md = MessageDigest.getInstance("MD5");
-            md.update(data);
-            return md.digest();
-        } catch (Exception e)
-        {
-            throw new RuntimeException("Checksum calculation failed", e);
-        }
-    }
-
     private static class WriteData
     {
         public String owner;
@@ -1167,7 +1152,6 @@ public class Integration2PCTest extends AbstractIntegrationTest
 
         public byte[] bytes;
 
-        public byte[] md5;
     }
 
 }
-- 
GitLab