001 /**
002 * Copyright 2010-2012 The Kuali Foundation
003 *
004 * Licensed under the Educational Community License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.opensource.org/licenses/ecl2.php
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package org.kuali.maven.wagon;
017
018 import java.io.File;
019
020 import org.slf4j.Logger;
021 import org.slf4j.LoggerFactory;
022
023 import com.amazonaws.services.s3.AmazonS3Client;
024 import com.amazonaws.services.s3.model.AmazonS3Exception;
025 import com.amazonaws.services.s3.model.PutObjectRequest;
026 import com.amazonaws.services.s3.transfer.TransferManager;
027 import com.amazonaws.services.s3.transfer.Upload;
028
029 public class S3Utils {
030 private static final int KILOBYTE = 1024;
031 private static final int MEGABYTE = 1024 * KILOBYTE;
032 private static final int MULTI_PART_UPLOAD_THRESHOLD = 100 * MEGABYTE;
033 private static final Logger log = LoggerFactory.getLogger(S3Utils.class);
034
035 /**
036 * Upload a single file to Amazon S3. If the file is larger than 100MB a multi-part upload is used. This splits the file into multiple
037 * smaller chunks with each chunk being uploaded in a different thread. Once all the threads have completed the file is reassembled on
038 * Amazon's side as a single file again.
039 */
040 public static final void upload(File file, PutObjectRequest request, AmazonS3Client client, TransferManager manager) {
041 // Store the file on S3
042 if (file.length() < MULTI_PART_UPLOAD_THRESHOLD) {
043 // Use normal upload for small files
044 client.putObject(request);
045 } else {
046 log.debug("Blocking multi-part upload: " + file.getAbsolutePath());
047 // Use multi-part upload for large files
048 blockingMultiPartUpload(request, manager);
049 }
050 }
051
052 /**
053 * Use this method to reliably upload large files by splitting it up into manageable chunks and using separate threads to upload each
054 * chunk. Amazon recommends using a multi-part upload on files larger than 100MB. When this method returns all of the upload threads
055 * that handle portions of the file have completed. The file has also been reassembled on Amazon S3 and is ready for use.
056 */
057 public static final void blockingMultiPartUpload(PutObjectRequest request, TransferManager manager) {
058 // Use multi-part upload for large files
059 Upload upload = manager.upload(request);
060 try {
061 // Block and wait for the upload to finish
062 upload.waitForCompletion();
063 } catch (Exception e) {
064 throw new AmazonS3Exception("Unexpected error uploading file", e);
065 }
066 }
067
068 }