IBM Cloud Object Storage(ICOS)に付属しているAsperaにSDK(Java版)を用いてファイルアップロードする

IBM Cloud Object Storage(ICOS)にファイルをアップロードする方法です。
今回はICOSに付属しているAsperaに対して、Java版のSDKを用いて操作を行います。

# 使用した環境
* macOS Mojave 10.14.6
* IntelliJ IDEA Ultimate 2019.03
* Java8

```
$ java -version
java version "1.8.0_211"
Java(TM) SE Runtime Environment (build 1.8.0_211-b12)
Java HotSpot(TM) 64-Bit Server VM (build 25.211-b12, mixed mode)
```

# Java版SDKのセットアップ
こちらを参考にセットアップ下さい。
[GitHub：IBM/ibm-cos-sdk-java](https://github.com/IBM/ibm-cos-sdk-java)

基本的には `pom.xml` にSDKのエントリを追加するだけです。

# ICOSの情報確認
IBM Cloud コンソール（Web）にログインしてICOSのサービス資格情報を確認します。
サービス資格情報はICOSに作成したバケットの資格情報の中にあります。
![service_info.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/187099/e851c63d-46c2-e70c-1e11-cbddda4a7f13.png)

# プログラム
拙作過ぎて恐縮ですが、あくまでもサンプルプログラムです。
皆さんはもっといい感じで書いてください。

```Java:IcosControl.java
package com.ibm.jp.dev;

import java.io.*;
import java.sql.Timestamp;
import java.util.List;

import com.ibm.cloud.objectstorage.ClientConfiguration;
import com.ibm.cloud.objectstorage.SDKGlobalConfiguration;
import com.ibm.cloud.objectstorage.auth.AWSCredentials;
import com.ibm.cloud.objectstorage.auth.AWSStaticCredentialsProvider;
import com.ibm.cloud.objectstorage.client.builder.AwsClientBuilder.EndpointConfiguration;
import com.ibm.cloud.objectstorage.services.s3.AmazonS3;
import com.ibm.cloud.objectstorage.services.s3.AmazonS3ClientBuilder;
import com.ibm.cloud.objectstorage.services.s3.model.*;
import com.ibm.cloud.objectstorage.oauth.BasicIBMOAuthCredentials;

public class IcosControl {
    private static String COS_ENDPOINT = "https://s3.jp-tok.cloud-object-storage.appdomain.cloud"; // eg "https://s3.us.cloud-object-storage.appdomain.cloud"
    private static String COS_API_KEY_ID = "your-api-key"; // eg "0viPHOY7LbLNa9eLftrtHPpTjoGv6hbLD1QalRXikliJ"
    private static String COS_AUTH_ENDPOINT = "https://iam.cloud.ibm.com/identity/token";
    private static String COS_SERVICE_CRN = "your-service-crn"; // eg "crn:v1:bluemix:public:cloud-object-storage:global:a/3bf0d9003abfb5d29761c3e97696b71c:d6f04d83-6c4f-4a62-a165-696756d63903::"
    private static String COS_BUCKET_LOCATION = "jp-tok"; // eg "us"
    private static String COS_BUCKET_NAME = "your-bucket-name";
    private static String COS_STORAGE_CLASS = "jp-tok-standard"; // eg us-south-standard
    private static AmazonS3 _cosClient;

    private static int SUCCESS = 0;
    private static int ERROR = -1;

    public static void main(String[] args) throws FileNotFoundException {

        SDKGlobalConfiguration.IAM_ENDPOINT = COS_AUTH_ENDPOINT;
        String bucketName = COS_BUCKET_NAME;
        String api_key = COS_API_KEY_ID;
        String service_instance_id = COS_SERVICE_CRN;
        String endpoint_url = COS_ENDPOINT;
        String location = COS_BUCKET_LOCATION;

        System.out.println("ICOS Access START: " + new Timestamp(System.currentTimeMillis()).toString());
        _cosClient = createClient(api_key, service_instance_id, endpoint_url, location);

        // Bucketのリスト
        listBuckets(_cosClient);

        System.out.println("■ putObject Start ■");

        // ファイル送信
//        File file = new File("/tmp/test-upload-java.txt");
        File file = new File(args[0]);
        FileInputStream fis = new FileInputStream(file);
        ObjectMetadata om = new ObjectMetadata();
        om.setContentLength(file.length());
        final PutObjectRequest putRequest = new PutObjectRequest(bucketName, file.getName(), fis, om);
        // アップロード
        _cosClient.putObject(putRequest);
        System.out.println("■ putObject End ■");

        System.out.println("ICOS Access END: " + new Timestamp(System.currentTimeMillis()).toString());

        // 正常終了
        System.exit(SUCCESS);

    }

    /**
     * @param api_key
     * @param service_instance_id
     * @param endpoint_url
     * @param location
     * @return AmazonS3
     */
    public static AmazonS3 createClient(String api_key, String service_instance_id, String endpoint_url, String location)
    {
        AWSCredentials credentials;
        credentials = new BasicIBMOAuthCredentials(api_key, service_instance_id);

        ClientConfiguration clientConfig = new ClientConfiguration().withRequestTimeout(5000);
        clientConfig.setUseTcpKeepAlive(true);

        AmazonS3 cos = AmazonS3ClientBuilder.standard().withCredentials(new AWSStaticCredentialsProvider(credentials))
                .withEndpointConfiguration(new EndpointConfiguration(endpoint_url, location)).withPathStyleAccessEnabled(true)
                .withClientConfiguration(clientConfig).build();
        return cos;
    }

    /**
     * @param bucketName
     * @param cosClient
     */
    public static void listObjects(String bucketName, AmazonS3 cosClient)
    {
        System.out.println();
        System.out.println("■ Listing objects in bucket " + bucketName + " ■");

        // Bucketが存在するか？
        boolean isBucket = false;
        isBucket = cosClient.doesBucketExistV2(bucketName);
        if(isBucket) {
            ObjectListing objectListing = cosClient.listObjects(new ListObjectsRequest().withBucketName(bucketName));
            for (S3ObjectSummary objectSummary : objectListing.getObjectSummaries()) {
                System.out.println(" - " + objectSummary.getKey() + "  " + "(size = " + objectSummary.getSize() + ")");
            }
        }
        System.out.println();
    }

    /**
     * @param cosClient
     */
    public static void listBuckets(AmazonS3 cosClient)
    {
        System.out.println();
        System.out.println("■ Listing buckets ■");
        final List<Bucket> bucketList = cosClient.listBuckets();
        for (final Bucket bucket : bucketList) {
            System.out.println(bucket.getName());
        }
        System.out.println();
    }

}
```


```XML:pom.xml
<?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">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.ibm.jp.dev</groupId>
    <artifactId>cos-control</artifactId>
    <version>1.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <java.version>1.8</java.version>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.ibm.cos</groupId>
            <artifactId>ibm-cos-java-sdk</artifactId>
            <version>2.6.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.10.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.10.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.1</version>
                <configuration>
                    <source>${java.version}</source>
                    <target>${java.version}</target>
                </configuration>
            </plugin>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>3.2.0</version>
                <configuration>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <archive>
                        <manifest>
                            <mainClass>com.ibm.jp.dev.IcosControl</mainClass>
                        </manifest>
                    </archive>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

</project>
```

# アップロード実行
## 実行
作成したjarファイルからパラメータを与えて実行してみます。

```
$ java -jar target/cos-control-1.0-jar-with-dependencies.jar /tmp/test-upload-java.txt
ICOS Access START: 2020-03-20 12:03:04.983

■ Listing buckets ■
test-bucket

■ putObject Start ■
■ putObject End ■
ICOS Access END: 2020-03-20 12:03:12.164
```

## 到着確認
ちゃんと届いてました。

```
test-upload-java.txt              Mar 20, 2020 at 12:03:11   519 B 
```

# あとがき
意外と、、、というと誤解を招くかもしれませんが、すんなりとアップロードは上手くいきました。
実はプログラムを作成してしばらくは、接続は出来ているのにBucketの中身を見ようとするとエラーになる、という謎事象も発生していたのですが、エンドポイントのURLに"jp-"が付いていなかったので、、、というオチでした。
皆様の参考になれば幸いです。

# 参考リンク
- [IBM Cloud docs：Aspera 高速転送の使用（Javaサンプル）](https://cloud.ibm.com/docs/services/cloud-object-storage/libraries?topic=cloud-object-storage-java&locale=ja#java-examples-aspera)
- [IBM COS SDK for Java 2.6.1 API](https://ibm.github.io/ibm-cos-sdk-java/)
- [IBM Cloud Object Storage - Java SDK](https://github.com/ibm/ibm-cos-sdk-java)
- [curlコマンドでIBM Cloud Object Storage(ICOS)にファイルをアップロードして公開する](https://qiita.com/y_tama/items/6e31922eb9504502d568)
- [IBM Cloud Object Storage(ICOS)にCLI(ibmcloudコマンド)を用いてファイルアップロードする](https://qiita.com/takanobu_kawaguchi/items/90ed22c5a2852fb3b9d5)
- [IBM Cloud Object Storage(ICOS)に付属しているAsperaにSDK(Python版)を用いてファイルアップロードする](https://qiita.com/takanobu_kawaguchi/items/f174e393d36c2940db18)