

 **このページは、ボールトと 2012 年リリース当時の REST API を使用する、Amazon Glacier サービスの既存のお客様のみを対象としています。**

アーカイブストレージソリューションをお探しの場合は、Amazon S3 の Amazon Glacier ストレージクラス (S3 Glacier Instant Retrieval、S3 Glacier Flexible Retrieval、S3 Glacier Deep Archive) を使用することをお勧めします。これらのストレージオプションの詳細については、「[Amazon Glacier ストレージクラス](https://aws.amazon.com/s3/storage-classes/glacier/)」を参照してください。

Amazon Glacier (元のスタンドアロンボールトベースのサービス) は、新規顧客を受け入れなくなりました。Amazon Glacier は、ボールトにデータを保存する独自の API を備えたスタンドアロンサービスであり、Amazon S3 および Amazon S3 Glacier ストレージクラスとは異なります。既存のデータは Amazon Glacier で無期限に安全性が確保され、引き続きアクセス可能です。移行は必要ありません。低コストの長期アーカイブストレージの場合、 は [Amazon S3 Glacier ストレージクラス](https://aws.amazon.com/s3/storage-classes/glacier/) AWS を推奨します。これにより、S3 バケットベースの APIs、低コスト、 AWS サービス統合で優れたカスタマーエクスペリエンスを実現できます。 AWS リージョン 拡張機能が必要な場合は、[Amazon Glacier ボールトから Amazon S3 Glacier ストレージクラスにデータを転送するためのAWS ソリューションガイダンス](https://aws.amazon.com/solutions/guidance/data-transfer-from-amazon-s3-glacier-vaults-to-amazon-s3/)を使用して、Amazon S3 Glacier ストレージクラスへの移行を検討してください。

翻訳は機械翻訳により提供されています。提供された翻訳内容と英語版の間で齟齬、不一致または矛盾がある場合、英語版が優先します。

# を使用した Amazon Glacier でのアーカイブのダウンロード AWS SDK for Java
<a name="downloading-an-archive-using-java"></a>

両方[高レベル API と低レベル API](using-aws-sdk.md)Amazon SDK for Java で提供されているアーカイブをダウンロードする方法を提供します。

**Topics**
+ [の高レベル API を使用したアーカイブのダウンロード AWS SDK for Java](#downloading-an-archive-using-java-highlevel-api)
+ [の低レベル API を使用したアーカイブのダウンロード AWS SDK for Java](#downloading-an-archive-using-java-lowlevel-api)

## の高レベル API を使用したアーカイブのダウンロード AWS SDK for Java
<a name="downloading-an-archive-using-java-highlevel-api"></a>

高レベル API の `ArchiveTransferManager` クラスには、アーカイブのダウンロードに使用できる `download` メソッドが用意されています。

**重要**  
-`ArchiveTransferManager`クラスは、Amazon Simple Notification Service (Amazon SNS) トピックと、そのトピックにサブスクライブされている Amazon Simple Queue Service (Amazon SQS) キューを作成します。その後、アーカイブの取り出しジョブを開始し、使用可能にするアーカイブを探してキューをポーリングします。アーカイブが使用可能になると、ダウンロードが開始されます。取得時間に関する詳細については、「[アーカイブの取り出しオプション](downloading-an-archive-two-steps.md#api-downloading-an-archive-two-steps-retrieval-options)」を参照してください。

### 例: の高レベル API を使用したアーカイブのダウンロード AWS SDK for Java
<a name="download-archives-java-highlevel-example"></a>

次の Java コード例では、米国西部（オレゴン リージョン (`us-west-2`) のボールト (`examplevault`) からアーカイブをダウンロードします。

このサンプルを実行するための詳しい手順については、「[Eclipse を使用した Amazon Glacier の Java 実行例](using-aws-sdk-for-java.md#setting-up-and-testing-sdk-java)」を参照してください。ここに示したコードは、既存のアーカイブ ID とダウンロードしたアーカイブを保存するローカルファイルパスで更新する必要があります。

**Example**  

```
import java.io.File;
import java.io.IOException;

import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.transfer.ArchiveTransferManager;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sqs.AmazonSQSClient;


public class ArchiveDownloadHighLevel {
    public static String vaultName = "examplevault";
    public static String archiveId = "*** provide archive ID ***";
    public static String downloadFilePath  = "*** provide location to download archive ***";
    
    public static AmazonGlacierClient glacierClient;
    public static AmazonSQSClient sqsClient;
    public static AmazonSNSClient snsClient;
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();
        
        glacierClient = new AmazonGlacierClient(credentials);
        
        sqsClient = new AmazonSQSClient(credentials);
        snsClient = new AmazonSNSClient(credentials);
        glacierClient.setEndpoint("glacier.us-west-2.amazonaws.com");
        sqsClient.setEndpoint("sqs.us-west-2.amazonaws.com");
        snsClient.setEndpoint("sns.us-west-2.amazonaws.com");

        try {
            ArchiveTransferManager atm = new ArchiveTransferManager(glacierClient, sqsClient, snsClient);
            
            atm.download(vaultName, archiveId, new File(downloadFilePath));
            System.out.println("Downloaded file to " + downloadFilePath);
            
        } catch (Exception e)
        {
            System.err.println(e);
        }
    }
}
```

## の低レベル API を使用したアーカイブのダウンロード AWS SDK for Java
<a name="downloading-an-archive-using-java-lowlevel-api"></a>

以下に、 AWS SDK for Java の低レベル API を使用してボールトインベントリを取得する手順を示します。

 

1. `AmazonGlacierClient` クラスのインスタンス（クライアント）を作成します。

   アーカイブをダウンロードする AWS リージョンを指定する必要があります。このクライアントを使用して実行するすべてのオペレーションは、その AWS リージョンに適用されます。

1. `archive-retrieval` メソッドを実行して、`initiateJob` ジョブを開始します。

   `InitiateJobRequest` クラスのインスタンスを作成することにより、ダウンロードするアーカイブのアーカイブ ID や、Amazon Glacier (Amazon Glacier) でジョブの完了メッセージを投稿する Amazon SNS トピック (オプション) などのジョブ情報を入力します。Amazon Glacier は、レスポンスとしてジョブ ID を返します。レスポンスは、`InitiateJobResult` クラスのインスタンスで使用できます。

    

   ```
   JobParameters jobParameters = new JobParameters()
       .withArchiveId("*** provide an archive id ***")
       .withDescription("archive retrieval")
       .withRetrievalByteRange("*** provide a retrieval range***") // optional
       .withType("archive-retrieval");
   
   InitiateJobResult initiateJobResult = client.initiateJob(new InitiateJobRequest()
       .withJobParameters(jobParameters)
       .withVaultName(vaultName));  
             
   String jobId = initiateJobResult.getJobId();
   ```

   オプションで、バイト範囲を指定して、アーカイブの一部のみを準備するよう Amazon Glacier にリクエストすることができます。たとえば、次のステートメントを追加すると、前のリクエストが更新され、アーカイブの 1 MB から 2 MB の部分のみを準備するよう Amazon Glacier にリクエストできます。

    

   ```
   int ONE_MEG = 1048576;
   String retrievalByteRange = String.format("%s-%s", ONE_MEG, 2*ONE_MEG -1);
   
   JobParameters jobParameters = new JobParameters()
       .withType("archive-retrieval")
       .withArchiveId(archiveId)
       .withRetrievalByteRange(retrievalByteRange) 
       .withSNSTopic(snsTopicARN);
   
   InitiateJobResult initiateJobResult = client.initiateJob(new InitiateJobRequest()
       .withJobParameters(jobParameters)
       .withVaultName(vaultName));  
             
   String jobId = initiateJobResult.getJobId();
   ```

    

1.  ジョブが完了するまで待ちます。

   ジョブの出力をダウンロードする準備が整うまで待つ必要があります。ボールトの通知設定により Amazon Simple Notification Service (Amazon SNS) トピックを指定している場合、またはジョブを開始したときに Amazon SNS トピックを指定している場合は、ジョブの完了後に Amazon Glacier によりそのトピックにメッセージが送信されます。

   また、`describeJob` メソッドを呼び出して Amazon Glacier にポーリングすることで、ジョブの完了ステータスを調べることもできます。ただし、通知のために Amazon SNS トピックを使用することをお勧めします。

1. `getJobOutput` メソッドを実行して、ジョブの出力 (アーカイブデータ) をダウンロードします。

   `GetJobOutputRequest` クラスのインスタンスを作成することにより、ジョブ ID やボールト名などのリクエスト情報を指定します。Amazon Glacier により返される出力は `GetJobOutputResult` オブジェクトで使用できます。

    

   ```
   GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest()
           .withJobId("*** provide a job ID ***")
           .withVaultName("*** provide a vault name ****");
   GetJobOutputResult jobOutputResult = client.getJobOutput(jobOutputRequest);
   
   // jobOutputResult.getBody() // Provides the input stream.
   ```

   前述のコードスニペットは、ジョブの出力全体をダウンロードします。このほか、`GetJobOutputRequest` でバイト範囲を指定することにより、出力の一部のみを取得したり、出力全体を小さなチャンクに分けてダウンロードしたりできます。

    

   ```
   GetJobOutputRequest jobOutputRequest = new GetJobOutputRequest()
           .withJobId("*** provide a job ID ***")
           .withRange("bytes=0-1048575")   // Download only the first 1 MB of the output.
           .withVaultName("*** provide a vault name ****");
   ```

   `GetJobOutput` 呼び出しに対するレスポンスとして、Amazon Glacier では、特定の条件が満たされた場合に、ダウンロードしたデータの一部のチェックサムを返します。詳細については、「[データをダウンロードするときのチェックサムの受信](checksum-calculations-range.md)」を参照してください。

   ダウンロードにエラーがないことを確認するために、クライアント側でチェックサムを計算し、Amazon Glacier からレスポンスとして送信されたチェックサムと比較できます。

   オプションの範囲が指定されたアーカイブの取得ジョブの場合は、ジョブの説明を取得すると、取得する範囲のチェックサム（SHA256TreeHash）が含まれます。この値を使用して、後でダウンロードするバイト範囲全体の正確性を詳しく確認できます。たとえば、木構造ハッシュ可能なアーカイブ範囲を取得するジョブを開始してから、出力を複数のチャンクに分けてダウンロードし、`GetJobOutput` リクエストでそれぞれチェックサムが返されるようにした場合は、クライアント側でダウンロードした各部分のチェックサムを計算してから木構造ハッシュを計算することができます。この計算結果を、Amazon Glacier でジョブの説明リクエストに対して返されたレスポンスのチェックサムと比較して、ダウンロードしたバイト範囲全体が Amazon Glacier に格納されているバイト範囲と同じであることを確認できます。

    実例については、「[例 2: の低レベル API を使用してアーカイブを取得する AWS SDK for Java— 出力をチャンクでダウンロードする](#downloading-an-archive-with-range-using-java-example)」を参照してください。

### 例 1: の低レベル API を使用してアーカイブを取得する AWS SDK for Java
<a name="downloading-an-archive-using-java-example"></a>

次の Java コード例では、指定したボールトからアーカイブをダウンロードします。この例では、ジョブが完了した後で、単一の `getJobOutput` 呼び出しで出力全体をダウンロードします。出力をチャンクに分けてダウンロードする例については、「[例 2: の低レベル API を使用してアーカイブを取得する AWS SDK for Java— 出力をチャンクでダウンロードする](#downloading-an-archive-with-range-using-java-example)」を参照してください。

この例では次のタスクを実行しています。

 
+ Amazon Simple Notification Service (Amazon SNS) のトピックの作成

  Amazon Glacier は、ジョブの完了後、このトピックに通知を送信します。
+ Amazon Simple Queue Service (Amazon SQS) キューの作成

  この例では、ポリシーをキューにアタッチして、Amazon SNS トピックでメッセージをキューに投稿できるようにします。
+ 指定したアーカイブをダウンロードするジョブを開始します。

  ジョブのリクエストでは、ジョブの完了後に Amazon Glacier がトピックへの通知を発行できるように、作成した Amazon SNS トピックを指定しています。
+ Amazon SQS キューにジョブ ID を含むメッセージがあるかどうかを定期的に確認します。

  メッセージがある場合は、JSON を解析し、ジョブが正常に完了したかどうかを確認します。正常に完了している場合は、アーカイブをダウンロードします。
+ Amazon SNS トピックおよび作成された Amazon SQS キューを削除して、クリーンアップします。

 

```
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.codehaus.jackson.JsonFactory;
import org.codehaus.jackson.JsonNode;
import org.codehaus.jackson.JsonParseException;
import org.codehaus.jackson.JsonParser;
import org.codehaus.jackson.map.ObjectMapper;

import com.amazonaws.AmazonClientException;
import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.Statement.Effect;
import com.amazonaws.auth.policy.actions.SQSActions;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.model.GetJobOutputRequest;
import com.amazonaws.services.glacier.model.GetJobOutputResult;
import com.amazonaws.services.glacier.model.InitiateJobRequest;
import com.amazonaws.services.glacier.model.InitiateJobResult;
import com.amazonaws.services.glacier.model.JobParameters;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.CreateTopicResult;
import com.amazonaws.services.sns.model.DeleteTopicRequest;
import com.amazonaws.services.sns.model.SubscribeRequest;
import com.amazonaws.services.sns.model.SubscribeResult;
import com.amazonaws.services.sns.model.UnsubscribeRequest;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.CreateQueueResult;
import com.amazonaws.services.sqs.model.DeleteQueueRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesResult;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;


public class AmazonGlacierDownloadArchiveWithSQSPolling {
    
    public static String archiveId = "*** provide archive ID ****";
    public static String vaultName = "*** provide vault name ***";
    public static String snsTopicName = "*** provide topic name ***";
    public static String sqsQueueName = "*** provide queue name ***";
    public static String sqsQueueARN;
    public static String sqsQueueURL;
    public static String snsTopicARN;
    public static String snsSubscriptionARN;
    public static String fileName = "*** provide file name ***";
    public static String region = "*** region ***"; 
    public static long sleepTime = 600; 
    public static AmazonGlacierClient client;
    public static AmazonSQSClient sqsClient;
    public static AmazonSNSClient snsClient;
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier." + region + ".amazonaws.com");
        sqsClient = new AmazonSQSClient(credentials);
        sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com");
        snsClient = new AmazonSNSClient(credentials);
        snsClient.setEndpoint("https://sns." + region + ".amazonaws.com");
                
        try {
            setupSQS();
            
            setupSNS();

            String jobId = initiateJobRequest();
            System.out.println("Jobid = " + jobId);
            
            Boolean success = waitForJobToComplete(jobId, sqsQueueURL);
            if (!success) { throw new Exception("Job did not complete successfully."); }
            
            downloadJobOutput(jobId);
            
            cleanUp();
            
        } catch (Exception e) {
            System.err.println("Archive retrieval failed.");
            System.err.println(e);
        }   
    }

    private static void setupSQS() {
        CreateQueueRequest request = new CreateQueueRequest()
            .withQueueName(sqsQueueName);
        CreateQueueResult result = sqsClient.createQueue(request);  
        sqsQueueURL = result.getQueueUrl();
                
        GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest()
            .withQueueUrl(sqsQueueURL)
            .withAttributeNames("QueueArn");
        
        GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest);
        sqsQueueARN = qResult.getAttributes().get("QueueArn");
        
        Policy sqsPolicy = 
            new Policy().withStatements(
                    new Statement(Effect.Allow)
                    .withPrincipals(Principal.AllUsers)
                    .withActions(SQSActions.SendMessage)
                    .withResources(new Resource(sqsQueueARN)));
        Map<String, String> queueAttributes = new HashMap<String, String>();
        queueAttributes.put("Policy", sqsPolicy.toJson());
        sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); 

    }
    private static void setupSNS() {
        CreateTopicRequest request = new CreateTopicRequest()
            .withName(snsTopicName);
        CreateTopicResult result = snsClient.createTopic(request);
        snsTopicARN = result.getTopicArn();

        SubscribeRequest request2 = new SubscribeRequest()
            .withTopicArn(snsTopicARN)
            .withEndpoint(sqsQueueARN)
            .withProtocol("sqs");
        SubscribeResult result2 = snsClient.subscribe(request2);
                
        snsSubscriptionARN = result2.getSubscriptionArn();
    }
    private static String initiateJobRequest() {
        
        JobParameters jobParameters = new JobParameters()
            .withType("archive-retrieval")
            .withArchiveId(archiveId)
            .withSNSTopic(snsTopicARN);
        
        InitiateJobRequest request = new InitiateJobRequest()
            .withVaultName(vaultName)
            .withJobParameters(jobParameters);
        
        InitiateJobResult response = client.initiateJob(request);
        
        return response.getJobId();
    }
    
    private static Boolean waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException {
        
        Boolean messageFound = false;
        Boolean jobSuccessful = false;
        ObjectMapper mapper = new ObjectMapper();
        JsonFactory factory = mapper.getJsonFactory();
        
        while (!messageFound) {
            List<Message> msgs = sqsClient.receiveMessage(
               new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages();

            if (msgs.size() > 0) {
                for (Message m : msgs) {
                    JsonParser jpMessage = factory.createJsonParser(m.getBody());
                    JsonNode jobMessageNode = mapper.readTree(jpMessage);
                    String jobMessage = jobMessageNode.get("Message").getTextValue();
                    
                    JsonParser jpDesc = factory.createJsonParser(jobMessage);
                    JsonNode jobDescNode = mapper.readTree(jpDesc);
                    String retrievedJobId = jobDescNode.get("JobId").getTextValue();
                    String statusCode = jobDescNode.get("StatusCode").getTextValue();
                    if (retrievedJobId.equals(jobId)) {
                        messageFound = true;
                        if (statusCode.equals("Succeeded")) {
                            jobSuccessful = true;
                        }
                    }
                }
                
            } else {
              Thread.sleep(sleepTime * 1000); 
            }
          }
        return (messageFound && jobSuccessful);
    }
    
    private static void downloadJobOutput(String jobId) throws IOException {
        
        GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
            .withVaultName(vaultName)
            .withJobId(jobId);
        GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest);
    
        InputStream input = new BufferedInputStream(getJobOutputResult.getBody());
        OutputStream output = null;
        try {
            output = new BufferedOutputStream(new FileOutputStream(fileName));

            byte[] buffer = new byte[1024 * 1024];

            int bytesRead = 0;
            do {
                bytesRead = input.read(buffer);
                if (bytesRead <= 0) break;
                output.write(buffer, 0, bytesRead);
            } while (bytesRead > 0);
        } catch (IOException e) {
            throw new AmazonClientException("Unable to save archive", e);
        } finally {
            try {input.close();}  catch (Exception e) {}
            try {output.close();} catch (Exception e) {}
        }
        System.out.println("Retrieved archive to " + fileName);
    }
    
    private static void cleanUp() {
        snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN));
        snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN));
        sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL));
    }
}
```

### 例 2: の低レベル API を使用してアーカイブを取得する AWS SDK for Java— 出力をチャンクでダウンロードする
<a name="downloading-an-archive-with-range-using-java-example"></a>

次の Java コード例では、Amazon Glacier からアーカイブを取得します。このコード例では、`GetJobOutputRequest` オブジェクトのバイト範囲を指定することにより、ジョブの出力をチャンクに分けてダウンロードします。

 

```
import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;

import com.amazonaws.auth.policy.Policy;
import com.amazonaws.auth.policy.Principal;
import com.amazonaws.auth.policy.Resource;
import com.amazonaws.auth.policy.Statement;
import com.amazonaws.auth.policy.Statement.Effect;
import com.amazonaws.auth.policy.actions.SQSActions;
import com.amazonaws.auth.profile.ProfileCredentialsProvider;
import com.amazonaws.services.glacier.AmazonGlacierClient;
import com.amazonaws.services.glacier.TreeHashGenerator;
import com.amazonaws.services.glacier.model.GetJobOutputRequest;
import com.amazonaws.services.glacier.model.GetJobOutputResult;
import com.amazonaws.services.glacier.model.InitiateJobRequest;
import com.amazonaws.services.glacier.model.InitiateJobResult;
import com.amazonaws.services.glacier.model.JobParameters;
import com.amazonaws.services.sns.AmazonSNSClient;
import com.amazonaws.services.sns.model.CreateTopicRequest;
import com.amazonaws.services.sns.model.CreateTopicResult;
import com.amazonaws.services.sns.model.DeleteTopicRequest;
import com.amazonaws.services.sns.model.SubscribeRequest;
import com.amazonaws.services.sns.model.SubscribeResult;
import com.amazonaws.services.sns.model.UnsubscribeRequest;
import com.amazonaws.services.sqs.AmazonSQSClient;
import com.amazonaws.services.sqs.model.CreateQueueRequest;
import com.amazonaws.services.sqs.model.CreateQueueResult;
import com.amazonaws.services.sqs.model.DeleteQueueRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesRequest;
import com.amazonaws.services.sqs.model.GetQueueAttributesResult;
import com.amazonaws.services.sqs.model.Message;
import com.amazonaws.services.sqs.model.ReceiveMessageRequest;
import com.amazonaws.services.sqs.model.SetQueueAttributesRequest;


public class ArchiveDownloadLowLevelWithRange {
    
    public static String vaultName = "*** provide vault name ***";
    public static String archiveId = "*** provide archive id ***";
    public static String snsTopicName = "glacier-temp-sns-topic";
    public static String sqsQueueName = "glacier-temp-sqs-queue";
    public static long downloadChunkSize = 4194304; // 4 MB  
    public static String sqsQueueARN;
    public static String sqsQueueURL;
    public static String snsTopicARN;
    public static String snsSubscriptionARN;
    public static String fileName = "*** provide file name to save archive to ***";
    public static String region   = "*** region ***";
    public static long sleepTime  = 600; 
    
    public static AmazonGlacierClient client;
    public static AmazonSQSClient sqsClient;
    public static AmazonSNSClient snsClient; 
    
    public static void main(String[] args) throws IOException {
        
    	ProfileCredentialsProvider credentials = new ProfileCredentialsProvider();

        client = new AmazonGlacierClient(credentials);
        client.setEndpoint("https://glacier." + region + ".amazonaws.com");
        sqsClient = new AmazonSQSClient(credentials);
        sqsClient.setEndpoint("https://sqs." + region + ".amazonaws.com");
        snsClient = new AmazonSNSClient(credentials);
        snsClient.setEndpoint("https://sns." + region + ".amazonaws.com");
        
        try {
            setupSQS();
            
            setupSNS();

            String jobId = initiateJobRequest();
            System.out.println("Jobid = " + jobId);
            
            long archiveSizeInBytes = waitForJobToComplete(jobId, sqsQueueURL);
            if (archiveSizeInBytes==-1) { throw new Exception("Job did not complete successfully."); }
            
            downloadJobOutput(jobId, archiveSizeInBytes);
            
            cleanUp();
            
        } catch (Exception e) {
            System.err.println("Archive retrieval failed.");
            System.err.println(e);
        }   
    }

    private static void setupSQS() {
        CreateQueueRequest request = new CreateQueueRequest()
            .withQueueName(sqsQueueName);
        CreateQueueResult result = sqsClient.createQueue(request);  
        sqsQueueURL = result.getQueueUrl();
                
        GetQueueAttributesRequest qRequest = new GetQueueAttributesRequest()
            .withQueueUrl(sqsQueueURL)
            .withAttributeNames("QueueArn");
        
        GetQueueAttributesResult qResult = sqsClient.getQueueAttributes(qRequest);
        sqsQueueARN = qResult.getAttributes().get("QueueArn");
        
        Policy sqsPolicy = 
            new Policy().withStatements(
                    new Statement(Effect.Allow)
                    .withPrincipals(Principal.AllUsers)
                    .withActions(SQSActions.SendMessage)
                    .withResources(new Resource(sqsQueueARN)));
        Map<String, String> queueAttributes = new HashMap<String, String>();
        queueAttributes.put("Policy", sqsPolicy.toJson());
        sqsClient.setQueueAttributes(new SetQueueAttributesRequest(sqsQueueURL, queueAttributes)); 

    }
    private static void setupSNS() {
        CreateTopicRequest request = new CreateTopicRequest()
            .withName(snsTopicName);
        CreateTopicResult result = snsClient.createTopic(request);
        snsTopicARN = result.getTopicArn();

        SubscribeRequest request2 = new SubscribeRequest()
            .withTopicArn(snsTopicARN)
            .withEndpoint(sqsQueueARN)
            .withProtocol("sqs");
        SubscribeResult result2 = snsClient.subscribe(request2);
                
        snsSubscriptionARN = result2.getSubscriptionArn();
    }
    private static String initiateJobRequest() {
        
        JobParameters jobParameters = new JobParameters()
            .withType("archive-retrieval")
            .withArchiveId(archiveId)
            .withSNSTopic(snsTopicARN);
        
        InitiateJobRequest request = new InitiateJobRequest()
            .withVaultName(vaultName)
            .withJobParameters(jobParameters);
        
        InitiateJobResult response = client.initiateJob(request);
        
        return response.getJobId();
    }
    
    private static long waitForJobToComplete(String jobId, String sqsQueueUrl) throws InterruptedException, JsonParseException, IOException {
        
        Boolean messageFound = false;
        Boolean jobSuccessful = false;
        long archiveSizeInBytes = -1;
        ObjectMapper mapper = new ObjectMapper();
        JsonFactory factory = mapper.getFactory();
        
        while (!messageFound) {
            List<Message> msgs = sqsClient.receiveMessage(
               new ReceiveMessageRequest(sqsQueueUrl).withMaxNumberOfMessages(10)).getMessages();

            if (msgs.size() > 0) {
                for (Message m : msgs) {
                    JsonParser jpMessage = factory.createJsonParser(m.getBody());
                    JsonNode jobMessageNode = mapper.readTree(jpMessage);
                    String jobMessage = jobMessageNode.get("Message").textValue();
                    
                    JsonParser jpDesc = factory.createJsonParser(jobMessage);
                    JsonNode jobDescNode = mapper.readTree(jpDesc);
                    String retrievedJobId = jobDescNode.get("JobId").textValue();
                    String statusCode = jobDescNode.get("StatusCode").textValue();
                    archiveSizeInBytes = jobDescNode.get("ArchiveSizeInBytes").longValue();
                    if (retrievedJobId.equals(jobId)) {
                        messageFound = true;
                        if (statusCode.equals("Succeeded")) {
                            jobSuccessful = true;
                        }
                    }
                }
                
            } else {
              Thread.sleep(sleepTime * 1000); 
            }
          }
        return (messageFound && jobSuccessful) ? archiveSizeInBytes : -1;
    }
    
    private static void downloadJobOutput(String jobId, long archiveSizeInBytes) throws IOException {
        
        if (archiveSizeInBytes < 0) {
            System.err.println("Nothing to download.");
            return;
        }

        System.out.println("archiveSizeInBytes: " + archiveSizeInBytes);
        FileOutputStream fstream = new FileOutputStream(fileName);
        long startRange = 0;
        long endRange = (downloadChunkSize > archiveSizeInBytes) ? archiveSizeInBytes -1 : downloadChunkSize - 1;

        do {

            GetJobOutputRequest getJobOutputRequest = new GetJobOutputRequest()
                .withVaultName(vaultName)
                .withRange("bytes=" + startRange + "-" + endRange)
                .withJobId(jobId);
            GetJobOutputResult getJobOutputResult = client.getJobOutput(getJobOutputRequest);

            BufferedInputStream is = new BufferedInputStream(getJobOutputResult.getBody());     
            byte[] buffer = new byte[(int)(endRange - startRange + 1)];

            System.out.println("Checksum received: " + getJobOutputResult.getChecksum());
            System.out.println("Content range " + getJobOutputResult.getContentRange());

            
            int totalRead = 0;
            while (totalRead < buffer.length) {
                int bytesRemaining = buffer.length - totalRead;
                int read = is.read(buffer, totalRead, bytesRemaining);
                if (read > 0) {
                    totalRead = totalRead + read;                             
                } else {
                    break;
                }
                
            }
            System.out.println("Calculated checksum: " + TreeHashGenerator.calculateTreeHash(new ByteArrayInputStream(buffer)));
            System.out.println("read = " + totalRead);
            fstream.write(buffer);
            
            startRange = startRange + (long)totalRead;
            endRange = ((endRange + downloadChunkSize) >  archiveSizeInBytes) ? archiveSizeInBytes : (endRange + downloadChunkSize); 
            is.close();
        } while (endRange <= archiveSizeInBytes  && startRange < archiveSizeInBytes);
        
        fstream.close();
        System.out.println("Retrieved file to " + fileName);

    }
    
    private static void cleanUp() {
        snsClient.unsubscribe(new UnsubscribeRequest(snsSubscriptionARN));
        snsClient.deleteTopic(new DeleteTopicRequest(snsTopicARN));
        sqsClient.deleteQueue(new DeleteQueueRequest(sqsQueueURL));
    }
}
```