This is an automated email from the ASF dual-hosted git repository.

dimuthuupe pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/airavata-mft.git


The following commit(s) were added to refs/heads/master by this push:
     new 5171fee  Adding Swift connector
5171fee is described below

commit 5171fee314dd84a4e57fa4291d36b5221f85332e
Author: Dimuthu Wannipurage <[email protected]>
AuthorDate: Tue May 3 17:43:00 2022 -0400

    Adding Swift connector
---
 agent/pom.xml                                      |  21 +--
 .../airavata/mft/core/ConnectorResolver.java       |   6 +
 .../mft/core/MetadataCollectorResolver.java        |   3 +
 pom.xml                                            |   2 +
 scripts/build.sh                                   |   2 +-
 transport/pom.xml                                  |   1 +
 transport/scp-transport/pom.xml                    |   2 +-
 transport/swift-transport/pom.xml                  |  47 +++++++
 .../transport/swift/SwiftIncomingConnector.java    | 148 +++++++++++++++++++
 .../transport/swift/SwiftMetadataCollector.java    | 156 +++++++++++++++++++++
 .../transport/swift/SwiftOutgoingConnector.java    | 149 ++++++++++++++++++++
 11 files changed, 527 insertions(+), 10 deletions(-)

diff --git a/agent/pom.xml b/agent/pom.xml
index 7e3a9cd..c0ab77d 100644
--- a/agent/pom.xml
+++ b/agent/pom.xml
@@ -36,7 +36,7 @@
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-scp-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
             <exclusions>
                 <exclusion>
                     <groupId>org.apache.custos</groupId>
@@ -47,27 +47,27 @@
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-local-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-s3-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-box-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-azure-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-gcp-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
@@ -77,12 +77,17 @@
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-ftp-transport</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>mft-swift-transport</artifactId>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>org.apache.airavata</groupId>
             <artifactId>mft-common-clients</artifactId>
-            <version>0.01-SNAPSHOT</version>
+            <version>${project.version}</version>
         </dependency>
         <dependency>
             <groupId>com.orbitz.consul</groupId>
diff --git 
a/core/src/main/java/org/apache/airavata/mft/core/ConnectorResolver.java 
b/core/src/main/java/org/apache/airavata/mft/core/ConnectorResolver.java
index f061a31..a3910a5 100644
--- a/core/src/main/java/org/apache/airavata/mft/core/ConnectorResolver.java
+++ b/core/src/main/java/org/apache/airavata/mft/core/ConnectorResolver.java
@@ -70,6 +70,9 @@ public final class ConnectorResolver {
             case "S3":
                 className = 
"org.apache.airavata.mft.transport.s3.S3IncomingConnector";
                 break;
+            case "SWIFT":
+                className = 
"org.apache.airavata.mft.transport.swift.SwiftIncomingConnector";
+                break;
         }
 
         if (className != null) {
@@ -87,6 +90,9 @@ public final class ConnectorResolver {
             case "S3":
                 className = 
"org.apache.airavata.mft.transport.s3.S3OutgoingConnector";
                 break;
+            case "SWIFT":
+                className = 
"org.apache.airavata.mft.transport.swift.SwiftOutgoingConnector";
+                break;
         }
 
         if (className != null) {
diff --git 
a/core/src/main/java/org/apache/airavata/mft/core/MetadataCollectorResolver.java
 
b/core/src/main/java/org/apache/airavata/mft/core/MetadataCollectorResolver.java
index c9da731..9ab820a 100644
--- 
a/core/src/main/java/org/apache/airavata/mft/core/MetadataCollectorResolver.java
+++ 
b/core/src/main/java/org/apache/airavata/mft/core/MetadataCollectorResolver.java
@@ -51,6 +51,9 @@ public final class MetadataCollectorResolver {
             case "FTP":
                 className = 
"org.apache.airavata.mft.transport.ftp.FTPMetadataCollector";
                 break;
+            case "SWIFT":
+                className = 
"org.apache.airavata.mft.transport.swift.SwiftMetadataCollector";
+                break;
         }
 
         if (className != null) {
diff --git a/pom.xml b/pom.xml
index cb33e96..0573509 100755
--- a/pom.xml
+++ b/pom.xml
@@ -149,6 +149,8 @@
         <sshj>0.27.0</sshj>
         <mariadb.jdbc>2.5.1</mariadb.jdbc>
         <custos.clients.version>1.1-SNAPSHOT</custos.clients.version>
+        <jclouds.version>2.5.0</jclouds.version>
+        <commons.io.version>2.6</commons.io.version>
     </properties>
 
 </project>
diff --git a/scripts/build.sh b/scripts/build.sh
index 42f3038..2d495f6 100755
--- a/scripts/build.sh
+++ b/scripts/build.sh
@@ -18,7 +18,7 @@
 # under the License.
 
 cd ../
-#mvn clean install
+mvn clean install
 rm -rf airavata-mft
 mkdir -p airavata-mft
 cp agent/target/MFT-Agent-0.01-bin.zip airavata-mft/
diff --git a/transport/pom.xml b/transport/pom.xml
index d53cfca..c537b24 100755
--- a/transport/pom.xml
+++ b/transport/pom.xml
@@ -41,6 +41,7 @@
         <module>gcp-transport</module>
         <module>ftp-transport</module>
         <module>dropbox-transport</module>
+        <module>swift-transport</module>
     </modules>
     <dependencies>
         <dependency>
diff --git a/transport/scp-transport/pom.xml b/transport/scp-transport/pom.xml
index 7680f54..eac4d43 100755
--- a/transport/scp-transport/pom.xml
+++ b/transport/scp-transport/pom.xml
@@ -51,7 +51,7 @@
         <dependency>
             <groupId>commons-io</groupId>
             <artifactId>commons-io</artifactId>
-            <version>2.6</version>
+            <version>${commons.io.version}</version>
         </dependency>
     </dependencies>
 
diff --git a/transport/swift-transport/pom.xml 
b/transport/swift-transport/pom.xml
new file mode 100644
index 0000000..b26facc
--- /dev/null
+++ b/transport/swift-transport/pom.xml
@@ -0,0 +1,47 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0";
+         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance";
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 
http://maven.apache.org/xsd/maven-4.0.0.xsd";>
+    <parent>
+        <artifactId>mft-transport</artifactId>
+        <groupId>org.apache.airavata</groupId>
+        <version>0.01-SNAPSHOT</version>
+    </parent>
+    <modelVersion>4.0.0</modelVersion>
+
+    <artifactId>mft-swift-transport</artifactId>
+
+    <properties>
+        <maven.compiler.source>11</maven.compiler.source>
+        <maven.compiler.target>11</maven.compiler.target>
+    </properties>
+
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.airavata</groupId>
+            <artifactId>mft-core</artifactId>
+            <version>${project.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.api</groupId>
+            <artifactId>openstack-swift</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.api</groupId>
+            <artifactId>openstack-nova</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.jclouds.api</groupId>
+            <artifactId>openstack-keystone</artifactId>
+            <version>${jclouds.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>commons-io</groupId>
+            <artifactId>commons-io</artifactId>
+            <version>${commons.io.version}</version>
+        </dependency>
+    </dependencies>
+
+</project>
\ No newline at end of file
diff --git 
a/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftIncomingConnector.java
 
b/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftIncomingConnector.java
new file mode 100644
index 0000000..1e3a6bf
--- /dev/null
+++ 
b/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftIncomingConnector.java
@@ -0,0 +1,148 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.airavata.mft.transport.swift;
+
+import org.apache.airavata.mft.core.api.ConnectorConfig;
+import org.apache.airavata.mft.core.api.IncomingChunkedConnector;
+import org.apache.airavata.mft.credential.stubs.swift.SwiftSecret;
+import org.apache.airavata.mft.credential.stubs.swift.SwiftSecretGetRequest;
+import org.apache.airavata.mft.resource.client.ResourceServiceClient;
+import org.apache.airavata.mft.resource.client.ResourceServiceClientBuilder;
+import org.apache.airavata.mft.resource.stubs.common.GenericResource;
+import org.apache.airavata.mft.resource.stubs.common.GenericResourceGetRequest;
+import org.apache.airavata.mft.resource.stubs.s3.storage.S3Storage;
+import org.apache.airavata.mft.resource.stubs.swift.storage.SwiftStorage;
+import org.apache.airavata.mft.secret.client.SecretServiceClient;
+import org.apache.airavata.mft.secret.client.SecretServiceClientBuilder;
+import org.apache.commons.io.IOUtils;
+import org.jclouds.ContextBuilder;
+import org.jclouds.http.options.GetOptions;
+import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.jclouds.openstack.swift.v1.SwiftApi;
+import org.jclouds.openstack.swift.v1.domain.SwiftObject;
+import org.jclouds.openstack.swift.v1.features.ObjectApi;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.File;
+import java.io.InputStream;
+import java.nio.file.StandardCopyOption;
+import java.util.Properties;
+
+public class SwiftIncomingConnector implements IncomingChunkedConnector {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(SwiftIncomingConnector.class);
+
+    private GenericResource resource;
+    private SwiftApi swiftApi;
+    private ObjectApi objectApi;
+
+    @Override
+    public void init(ConnectorConfig cc) throws Exception {
+        try (ResourceServiceClient resourceClient = 
ResourceServiceClientBuilder
+                .buildClient(cc.getResourceServiceHost(), 
cc.getResourceServicePort())) {
+
+            resource = 
resourceClient.get().getGenericResource(GenericResourceGetRequest.newBuilder()
+                    .setAuthzToken(cc.getAuthToken())
+                    .setResourceId(cc.getResourceId()).build());
+        }
+
+        if (resource.getStorageCase() != 
GenericResource.StorageCase.SWIFTSTORAGE) {
+            logger.error("Invalid storage type {} specified for resource {}", 
resource.getStorageCase(), cc.getResourceId());
+            throw new Exception("Invalid storage type specified for resource " 
+ cc.getResourceId());
+        }
+
+        SwiftStorage swiftStorage = resource.getSwiftStorage();
+
+        SwiftSecret swiftSecret;
+
+        try (SecretServiceClient secretClient = 
SecretServiceClientBuilder.buildClient(
+                cc.getSecretServiceHost(), cc.getSecretServicePort())) {
+
+            swiftSecret = 
secretClient.swift().getSwiftSecret(SwiftSecretGetRequest.newBuilder()
+                    .setAuthzToken(cc.getAuthToken())
+                    .setSecretId(cc.getCredentialToken()).build());
+
+            String provider = "openstack-swift";
+
+            Properties overrides = new Properties();
+            overrides.put(KeystoneProperties.KEYSTONE_VERSION, 
swiftStorage.getKeystoneVersion() + "");
+
+            String identity = null;
+            String credential = null;
+            switch (swiftSecret.getSecretCase()) {
+                case PASSWORDSECRET:
+                    identity = swiftSecret.getPasswordSecret().getDomainId() + 
":" + swiftSecret.getPasswordSecret().getUserName();
+                    credential = swiftSecret.getPasswordSecret().getPassword();
+                    overrides.put(KeystoneProperties.SCOPE, "projectId:" + 
swiftSecret.getPasswordSecret().getProjectId());
+                    overrides.put(KeystoneProperties.CREDENTIAL_TYPE, 
CredentialTypes.PASSWORD_CREDENTIALS);
+                    break;
+                case AUTHCREDENTIALSECRET:
+                    identity = 
swiftSecret.getAuthCredentialSecret().getCredentialId();
+                    credential = 
swiftSecret.getAuthCredentialSecret().getCredentialSecret();
+                    overrides.put(KeystoneProperties.CREDENTIAL_TYPE, 
CredentialTypes.API_ACCESS_KEY_CREDENTIALS);
+                    break;
+            }
+
+            swiftApi = ContextBuilder.newBuilder(provider)
+                    .endpoint(swiftStorage.getEndpoint())
+                    .credentials(identity, credential)
+                    .overrides(overrides)
+                    .buildApi(SwiftApi.class);
+
+            objectApi = swiftApi.getObjectApi(swiftStorage.getRegion(), 
swiftStorage.getContainer());
+
+        }
+    }
+
+    @Override
+    public void complete() throws Exception {
+        if (swiftApi != null) {
+            swiftApi.close();
+        }
+    }
+
+    @Override
+    public void downloadChunk(int chunkId, long startByte, long endByte, 
String downloadFile) throws Exception {
+        SwiftObject swiftObject = objectApi.get(
+                resource.getFile().getResourcePath(),
+                GetOptions.Builder.range(startByte, endByte));
+
+        InputStream inputStream = swiftObject.getPayload().openStream();
+
+        File targetFile = new File("/tmp/targetFile.tmp");
+
+        java.nio.file.Files.copy(
+                inputStream,
+                targetFile.toPath(),
+                StandardCopyOption.REPLACE_EXISTING);
+
+        IOUtils.closeQuietly(inputStream);
+    }
+
+    @Override
+    public InputStream downloadChunk(int chunkId, long startByte, long 
endByte) throws Exception {
+
+        SwiftObject swiftObject = objectApi.get(
+                resource.getFile().getResourcePath(),
+                GetOptions.Builder.range(startByte, endByte));
+
+        return swiftObject.getPayload().openStream();
+    }
+}
diff --git 
a/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftMetadataCollector.java
 
b/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftMetadataCollector.java
new file mode 100644
index 0000000..2200b2b
--- /dev/null
+++ 
b/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftMetadataCollector.java
@@ -0,0 +1,156 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.airavata.mft.transport.swift;
+
+import org.apache.airavata.mft.common.AuthToken;
+import org.apache.airavata.mft.core.DirectoryResourceMetadata;
+import org.apache.airavata.mft.core.FileResourceMetadata;
+import org.apache.airavata.mft.core.api.MetadataCollector;
+import org.apache.airavata.mft.credential.stubs.swift.SwiftSecret;
+import org.apache.airavata.mft.credential.stubs.swift.SwiftSecretGetRequest;
+import org.apache.airavata.mft.resource.client.ResourceServiceClient;
+import org.apache.airavata.mft.resource.client.ResourceServiceClientBuilder;
+import org.apache.airavata.mft.resource.stubs.common.GenericResource;
+import org.apache.airavata.mft.resource.stubs.common.GenericResourceGetRequest;
+import org.apache.airavata.mft.resource.stubs.swift.storage.SwiftStorage;
+import org.apache.airavata.mft.secret.client.SecretServiceClient;
+import org.apache.airavata.mft.secret.client.SecretServiceClientBuilder;
+import org.jclouds.ContextBuilder;
+import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.jclouds.openstack.swift.v1.SwiftApi;
+import org.jclouds.openstack.swift.v1.domain.SwiftObject;
+import org.jclouds.openstack.swift.v1.features.ObjectApi;
+
+import java.util.Properties;
+
+public class SwiftMetadataCollector implements MetadataCollector {
+
+    private String resourceServiceHost;
+    private int resourceServicePort;
+    private String secretServiceHost;
+    private int secretServicePort;
+    boolean initialized = false;
+
+    @Override
+    public void init(String resourceServiceHost, int resourceServicePort, 
String secretServiceHost, int secretServicePort) {
+        this.resourceServiceHost = resourceServiceHost;
+        this.resourceServicePort = resourceServicePort;
+        this.secretServiceHost = secretServiceHost;
+        this.secretServicePort = secretServicePort;
+        this.initialized = true;
+    }
+
+    private void checkInitialized() {
+        if (!initialized) {
+            throw new IllegalStateException("Swift Metadata Collector is not 
initialized");
+        }
+    }
+
+    private SwiftApi getSwiftApi(SwiftStorage swiftStorage, SwiftSecret 
swiftSecret) {
+        String provider = "openstack-swift";
+
+        Properties overrides = new Properties();
+        overrides.put(KeystoneProperties.KEYSTONE_VERSION, 
swiftStorage.getKeystoneVersion() + "");
+
+        String identity = null;
+        String credential = null;
+        switch (swiftSecret.getSecretCase()) {
+            case PASSWORDSECRET:
+                identity = swiftSecret.getPasswordSecret().getDomainId() + ":" 
+ swiftSecret.getPasswordSecret().getUserName();
+                credential = swiftSecret.getPasswordSecret().getPassword();
+                overrides.put(KeystoneProperties.SCOPE, "projectId:" + 
swiftSecret.getPasswordSecret().getProjectId());
+                overrides.put(KeystoneProperties.CREDENTIAL_TYPE, 
CredentialTypes.PASSWORD_CREDENTIALS);
+                break;
+            case AUTHCREDENTIALSECRET:
+                identity = 
swiftSecret.getAuthCredentialSecret().getCredentialId();
+                credential = 
swiftSecret.getAuthCredentialSecret().getCredentialSecret();
+                overrides.put(KeystoneProperties.CREDENTIAL_TYPE, 
CredentialTypes.API_ACCESS_KEY_CREDENTIALS);
+                break;
+        }
+
+        return ContextBuilder.newBuilder(provider)
+                .endpoint(swiftStorage.getEndpoint())
+                .credentials(identity, credential)
+                .overrides(overrides)
+                .buildApi(SwiftApi.class);
+    }
+
+    @Override
+    public FileResourceMetadata getFileResourceMetadata(AuthToken authZToken, 
String resourceId, String credentialToken) throws Exception {
+        checkInitialized();
+
+        ResourceServiceClient resourceClient = 
ResourceServiceClientBuilder.buildClient(resourceServiceHost, 
resourceServicePort);
+        GenericResource swiftResource = 
resourceClient.get().getGenericResource(GenericResourceGetRequest.newBuilder().setResourceId(resourceId).build());
+
+        SecretServiceClient secretClient = 
SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
+        SwiftSecret swiftSecret = 
secretClient.swift().getSwiftSecret(SwiftSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
+
+        SwiftApi swiftApi = getSwiftApi(swiftResource.getSwiftStorage(), 
swiftSecret);
+
+        ObjectApi objectApi = 
swiftApi.getObjectApi(swiftResource.getSwiftStorage().getRegion(), 
swiftResource.getSwiftStorage().getContainer());
+
+        SwiftObject swiftObject = 
objectApi.get(swiftResource.getFile().getResourcePath());
+
+        FileResourceMetadata metadata = new FileResourceMetadata();
+        
metadata.setResourceSize(swiftObject.getPayload().getContentMetadata().getContentLength());
+        metadata.setMd5sum(swiftObject.getETag());
+        metadata.setUpdateTime(swiftObject.getLastModified().getTime());
+        metadata.setCreatedTime(swiftObject.getLastModified().getTime());
+        return metadata;
+    }
+
+    @Override
+    public FileResourceMetadata getFileResourceMetadata(AuthToken authZToken, 
String parentResourceId, String resourcePath, String credentialToken) throws 
Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(AuthToken 
authZToken, String resourceId, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public DirectoryResourceMetadata getDirectoryResourceMetadata(AuthToken 
authZToken, String parentResourceId, String resourcePath, String 
credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+
+    @Override
+    public Boolean isAvailable(AuthToken authZToken, String resourceId, String 
credentialToken) throws Exception {
+        checkInitialized();
+
+        ResourceServiceClient resourceClient = 
ResourceServiceClientBuilder.buildClient(resourceServiceHost, 
resourceServicePort);
+        GenericResource swiftResource = 
resourceClient.get().getGenericResource(GenericResourceGetRequest.newBuilder().setResourceId(resourceId).build());
+
+        SecretServiceClient secretClient = 
SecretServiceClientBuilder.buildClient(secretServiceHost, secretServicePort);
+        SwiftSecret swiftSecret = 
secretClient.swift().getSwiftSecret(SwiftSecretGetRequest.newBuilder().setSecretId(credentialToken).build());
+
+        SwiftApi swiftApi = getSwiftApi(swiftResource.getSwiftStorage(), 
swiftSecret);
+
+        ObjectApi objectApi = 
swiftApi.getObjectApi(swiftResource.getSwiftStorage().getRegion(), 
swiftResource.getSwiftStorage().getContainer());
+
+        SwiftObject swiftObject = 
objectApi.get(swiftResource.getFile().getResourcePath());
+
+        return swiftObject != null;
+    }
+
+    @Override
+    public Boolean isAvailable(AuthToken authToken, String parentResourceId, 
String resourcePath, String credentialToken) throws Exception {
+        throw new UnsupportedOperationException("Method not implemented");
+    }
+}
diff --git 
a/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftOutgoingConnector.java
 
b/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftOutgoingConnector.java
new file mode 100644
index 0000000..3734e8b
--- /dev/null
+++ 
b/transport/swift-transport/src/main/java/org/apache/airavata/mft/transport/swift/SwiftOutgoingConnector.java
@@ -0,0 +1,149 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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 org.apache.airavata.mft.transport.swift;
+
+import org.apache.airavata.mft.core.api.ConnectorConfig;
+import org.apache.airavata.mft.core.api.OutgoingChunkedConnector;
+import org.apache.airavata.mft.credential.stubs.swift.SwiftSecret;
+import org.apache.airavata.mft.credential.stubs.swift.SwiftSecretGetRequest;
+import org.apache.airavata.mft.resource.client.ResourceServiceClient;
+import org.apache.airavata.mft.resource.client.ResourceServiceClientBuilder;
+import org.apache.airavata.mft.resource.stubs.common.GenericResource;
+import org.apache.airavata.mft.resource.stubs.common.GenericResourceGetRequest;
+import org.apache.airavata.mft.resource.stubs.swift.storage.SwiftStorage;
+import org.apache.airavata.mft.secret.client.SecretServiceClient;
+import org.apache.airavata.mft.secret.client.SecretServiceClientBuilder;
+import org.jclouds.ContextBuilder;
+import org.jclouds.io.payloads.InputStreamPayload;
+import org.jclouds.openstack.keystone.auth.config.CredentialTypes;
+import org.jclouds.openstack.keystone.config.KeystoneProperties;
+import org.jclouds.openstack.swift.v1.SwiftApi;
+import org.jclouds.openstack.swift.v1.domain.Segment;
+import org.jclouds.openstack.swift.v1.features.ObjectApi;
+import org.jclouds.openstack.swift.v1.features.StaticLargeObjectApi;
+import org.jclouds.openstack.swift.v1.options.PutOptions;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.FileInputStream;
+import java.io.InputStream;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+
+public class SwiftOutgoingConnector implements OutgoingChunkedConnector {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(SwiftOutgoingConnector.class);
+
+    private GenericResource resource;
+    private SwiftApi swiftApi;
+    private ObjectApi objectApi;
+    private StaticLargeObjectApi staticLargeObjectApi;
+
+    private final Map<Integer, Segment> segmentMap = new ConcurrentHashMap();
+
+    // Referring to 
https://www.mirantis.com/blog/large-objects-in-cloud-storages/
+
+    @Override
+    public void init(ConnectorConfig cc) throws Exception {
+        try (ResourceServiceClient resourceClient = 
ResourceServiceClientBuilder
+                .buildClient(cc.getResourceServiceHost(), 
cc.getResourceServicePort())) {
+
+            resource = 
resourceClient.get().getGenericResource(GenericResourceGetRequest.newBuilder()
+                    .setAuthzToken(cc.getAuthToken())
+                    .setResourceId(cc.getResourceId()).build());
+        }
+
+        if (resource.getStorageCase() != 
GenericResource.StorageCase.SWIFTSTORAGE) {
+            logger.error("Invalid storage type {} specified for resource {}", 
resource.getStorageCase(), cc.getResourceId());
+            throw new Exception("Invalid storage type specified for resource " 
+ cc.getResourceId());
+        }
+
+        SwiftStorage swiftStorage = resource.getSwiftStorage();
+
+        SwiftSecret swiftSecret;
+
+        try (SecretServiceClient secretClient = 
SecretServiceClientBuilder.buildClient(
+                cc.getSecretServiceHost(), cc.getSecretServicePort())) {
+
+            swiftSecret = 
secretClient.swift().getSwiftSecret(SwiftSecretGetRequest.newBuilder()
+                    .setAuthzToken(cc.getAuthToken())
+                    .setSecretId(cc.getCredentialToken()).build());
+
+            String provider = "openstack-swift";
+
+            Properties overrides = new Properties();
+            overrides.put(KeystoneProperties.KEYSTONE_VERSION, 
swiftStorage.getKeystoneVersion() + "");
+
+            String identity = null;
+            String credential = null;
+            switch (swiftSecret.getSecretCase()) {
+                case PASSWORDSECRET:
+                    identity = swiftSecret.getPasswordSecret().getDomainId() + 
":" + swiftSecret.getPasswordSecret().getUserName();
+                    credential = swiftSecret.getPasswordSecret().getPassword();
+                    overrides.put(KeystoneProperties.SCOPE, "projectId:" + 
swiftSecret.getPasswordSecret().getProjectId());
+                    overrides.put(KeystoneProperties.CREDENTIAL_TYPE, 
CredentialTypes.PASSWORD_CREDENTIALS);
+                    break;
+                case AUTHCREDENTIALSECRET:
+                    identity = 
swiftSecret.getAuthCredentialSecret().getCredentialId();
+                    credential = 
swiftSecret.getAuthCredentialSecret().getCredentialSecret();
+                    overrides.put(KeystoneProperties.CREDENTIAL_TYPE, 
CredentialTypes.API_ACCESS_KEY_CREDENTIALS);
+                    break;
+            }
+
+            swiftApi = ContextBuilder.newBuilder(provider)
+                    .endpoint(swiftStorage.getEndpoint())
+                    .credentials(identity, credential)
+                    .overrides(overrides)
+                    .buildApi(SwiftApi.class);
+
+            objectApi = swiftApi.getObjectApi(swiftStorage.getRegion(), 
swiftStorage.getContainer());
+            staticLargeObjectApi = 
swiftApi.getStaticLargeObjectApi(swiftStorage.getRegion(), 
swiftStorage.getContainer());
+        }
+    }
+
+    @Override
+    public void complete() throws Exception {
+
+        List<Segment> segments = new ArrayList<>();
+        for (int id = 0; id < segmentMap.size(); id ++) {
+            segments.add(segmentMap.get(id));
+        }
+
+        String etag = 
staticLargeObjectApi.replaceManifest(resource.getFile().getResourcePath(),
+                segments, new HashMap<>());
+
+        if (swiftApi != null) {
+            swiftApi.close();
+        }
+    }
+
+    @Override
+    public void uploadChunk(int chunkId, long startByte, long endByte, String 
uploadFile) throws Exception {
+        InputStream fis = new FileInputStream(uploadFile);
+        uploadChunk(chunkId, startByte, endByte, fis);
+    }
+
+    @Override
+    public void uploadChunk(int chunkId, long startByte, long endByte, 
InputStream inputStream) throws Exception {
+        String etag = objectApi.put(resource.getFile().getResourcePath() + 
chunkId, new InputStreamPayload(inputStream));
+        Segment segment = Segment.builder().etag(etag)
+                .path(resource.getFile().getResourcePath() + chunkId)
+                .sizeBytes(endByte - startByte).build();
+        segmentMap.put(chunkId, segment);
+    }
+}

Reply via email to