package com.orange.clara.cloud.dbdump.s3;

import com.google.common.collect.Maps;
import com.google.common.net.MediaType;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.blobstore.KeyNotFoundException;
import org.jclouds.blobstore.domain.Blob;
import org.jclouds.io.ContentMetadata;
import org.jclouds.io.Payload;
import org.jclouds.io.payloads.ByteArrayPayload;
import org.jclouds.s3.S3Client;
import org.jclouds.s3.domain.ObjectMetadataBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;

import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.SortedMap;

/**
 * Copyright (C) 2015 Orange
 * <p/>
 * This software is distributed under the terms and conditions of the 'MIT'
 * license which can be found in the file 'LICENSE' in this package distribution
 * or at 'http://opensource.org/licenses/MIT'.
 * <p/>
 * Author: Arthur Halet
 * Date: 28/09/2015
 */
public class UploadS3Stream {

    public final static Integer CHUNK_SIZE = 5 * 1024 * 1024;

    @Autowired
    @Qualifier(value = "blobStoreContext")
    protected BlobStoreContext blobStoreContext;

    @Autowired
    @Qualifier(value = "bucketName")
    protected String bucketName;

    public String upload(InputStream content, Blob blob) throws IOException {
        S3Client client = this.getS3Client();
        String key = blob.getMetadata().getName();
        ContentMetadata metadata = blob.getMetadata().getContentMetadata();
        ObjectMetadataBuilder builder = ObjectMetadataBuilder.create().key(key)
                .contentType(MediaType.OCTET_STREAM.toString())
                .contentDisposition(key)
                .contentEncoding(metadata.getContentEncoding())
                .contentLanguage(metadata.getContentLanguage())
                .userMetadata(blob.getMetadata().getUserMetadata());
        String uploadId = client.initiateMultipartUpload(bucketName, builder.build());
        Integer partNum = 1;
        Payload part = null;
        int bytesRead = 0;
        try {
            SortedMap<Integer, String> etags = Maps.newTreeMap();
            while (true) {
                byte[] buffer = new byte[CHUNK_SIZE];
                bytesRead = content.read(buffer);
                if (bytesRead == -1) {
                    break;
                }
                if (bytesRead < CHUNK_SIZE) {
                    buffer = Arrays.copyOf(buffer, bytesRead);
                }
                part = new ByteArrayPayload(buffer);
                prepareUploadPart(bucketName, key, uploadId, partNum, part, etags);
                partNum++;
            }
            return client.completeMultipartUpload(bucketName, key, uploadId, etags);
        } catch (RuntimeException ex) {
            client.abortMultipartUpload(bucketName, key, uploadId);
            throw ex;
        }
    }

    private void prepareUploadPart(String container, String key, String uploadId, int part, Payload chunkedPart, SortedMap<Integer, String> etags) {
        S3Client client = this.getS3Client();
        String eTag = null;
        try {
            eTag = client.uploadPart(container, key, part, uploadId, chunkedPart);
            etags.put(Integer.valueOf(part), eTag);
        } catch (KeyNotFoundException e) {
            // note that because of eventual consistency, the upload id may not be
            // present yet we may wish to add this condition to the retry handler

            // we may also choose to implement ListParts and wait for the uploadId
            // to become available there.
            eTag = client.uploadPart(container, key, part, uploadId, chunkedPart);
            etags.put(Integer.valueOf(part), eTag);
        }
    }

    private S3Client getS3Client() {
        return this.blobStoreContext.unwrapApi(S3Client.class);
    }
}

@@ -585,16 +585,52 @@
 ifier;%0A%0A
+import java.io.BufferedInputStream;%0A
 import j
@@ -1398,16 +1398,80 @@
 ption %7B%0A
+        content = new BufferedInputStream(content, CHUNK_SIZE);%0A
         
@@ -2189,16 +2189,117 @@
 ad = 0;%0A
+        int i = 0;%0A        byte%5B%5D reader = new byte%5B1%5D;%0A        byte%5B%5D chunk = new byte%5BCHUNK_SIZE%5D;%0A
         
@@ -2421,90 +2421,74 @@
 byte
-%5B%5D buffer = new byte%5BCHUNK_SIZE%5D;%0A                bytesRead = content.read(buffer)
+sRead = content.read(reader);%0A                chunk%5Bi%5D = reader%5B0%5D
 ;%0A  
@@ -2520,16 +2520,34 @@
 ad == -1
+ && i %3C CHUNK_SIZE
 ) %7B%0A    
@@ -2566,13 +2566,39 @@
     
-break
+chunk = Arrays.copyOf(chunk, i)
 ;%0A  
@@ -2634,87 +2634,50 @@
    i
-f (bytesRead %3C CHUNK_SIZE) %7B%0A                    buffer = Arrays.copyOf(buffer,
+++;%0A                if (i == CHUNK_SIZE %7C%7C
  byt
@@ -2682,18 +2682,25 @@
 ytesRead
-);
+ == -1) %7B
 %0A       
@@ -2695,39 +2695,32 @@
 1) %7B%0A           
-     %7D%0A
                 
@@ -2708,31 +2708,24 @@
             
-       
 part = new B
@@ -2744,17 +2744,20 @@
 oad(
-buffer);%0A
+chunk);%0A    
     
@@ -2848,24 +2848,28 @@
             
+    
 partNum++;%0A 
@@ -2863,24 +2863,203 @@
  partNum++;%0A
+                    chunk = new byte%5BCHUNK_SIZE%5D;%0A                    i = 0;%0A                %7D%0A                if (bytesRead == -1) %7B%0A                    break;%0A                %7D%0A
             
@@ -3378,17 +3378,20 @@
 Id, int 
-p
+numP
 art, Pay
@@ -3577,33 +3577,36 @@
 container, key, 
-p
+numP
 art, uploadId, c
@@ -3648,33 +3648,36 @@
 Integer.valueOf(
-p
+numP
 art), eTag);%0A   
@@ -4060,17 +4060,20 @@
 r, key, 
-p
+numP
 art, upl
@@ -4131,17 +4131,20 @@
 valueOf(
-p
+numP
 art), eT

Change the way to upload a stream into s3