Search in sources :

Example 1 with ProgressListenerCallbackExecutor

use of com.amazonaws.event.ProgressListenerCallbackExecutor in project aws-sdk-android by aws-amplify.

the class AmazonS3Client method getObject.

/*
     * (non-Javadoc)
     * @see
     * com.amazonaws.services.s3.AmazonS3#getObject(com.amazonaws.services.s3
     * .model.GetObjectRequest)
     */
@Override
public S3Object getObject(GetObjectRequest getObjectRequest) throws AmazonClientException, AmazonServiceException {
    assertParameterNotNull(getObjectRequest, "The GetObjectRequest parameter must be specified when requesting an object");
    assertParameterNotNull(getObjectRequest.getBucketName(), "The bucket name parameter must be specified when requesting an object");
    assertParameterNotNull(getObjectRequest.getKey(), "The key parameter must be specified when requesting an object");
    final Request<GetObjectRequest> request = createRequest(getObjectRequest.getBucketName(), getObjectRequest.getKey(), getObjectRequest, HttpMethodName.GET);
    if (getObjectRequest.getVersionId() != null) {
        request.addParameter("versionId", getObjectRequest.getVersionId());
    }
    // Range
    final long[] range = getObjectRequest.getRange();
    if (range != null) {
        String rangeHeader = "bytes=" + Long.toString(range[0]) + "-";
        if (range[1] >= 0) {
            /*
                 * Negative value is invalid per S3 range get and will result in
                 * downloading the entire object. Leaving last byte empty so as
                 * to resume download from range[0].
                 */
            rangeHeader += Long.toString(range[1]);
        }
        request.addHeader(Headers.RANGE, rangeHeader);
    }
    populateRequesterPaysHeader(request, getObjectRequest.isRequesterPays());
    addResponseHeaderParameters(request, getObjectRequest.getResponseHeaders());
    addDateHeader(request, Headers.GET_OBJECT_IF_MODIFIED_SINCE, getObjectRequest.getModifiedSinceConstraint());
    addDateHeader(request, Headers.GET_OBJECT_IF_UNMODIFIED_SINCE, getObjectRequest.getUnmodifiedSinceConstraint());
    addStringListHeader(request, Headers.GET_OBJECT_IF_MATCH, getObjectRequest.getMatchingETagConstraints());
    addStringListHeader(request, Headers.GET_OBJECT_IF_NONE_MATCH, getObjectRequest.getNonmatchingETagConstraints());
    // Populate the SSE-CPK parameters to the request header
    populateSSE_C(request, getObjectRequest.getSSECustomerKey());
    /*
         * This is compatible with progress listener set by either the legacy
         * method GetObjectRequest#setProgressListener or the new method
         * GetObjectRequest#setGeneralProgressListener.
         */
    final ProgressListener progressListener = getObjectRequest.getGeneralProgressListener();
    final ProgressListenerCallbackExecutor progressListenerCallbackExecutor = ProgressListenerCallbackExecutor.wrapListener(progressListener);
    try {
        final S3Object s3Object = invoke(request, new S3ObjectResponseHandler(), getObjectRequest.getBucketName(), getObjectRequest.getKey());
        /*
             * TODO: For now, it's easiest to set there here in the client, but
             * we could push this back into the response handler with a little
             * more work.
             */
        s3Object.setBucketName(getObjectRequest.getBucketName());
        s3Object.setKey(getObjectRequest.getKey());
        InputStream input = s3Object.getObjectContent();
        // Hold a reference to this client while the InputStream is still
        // around - otherwise a finalizer in the HttpClient may reset the
        // underlying TCP connection out from under us.
        input = new ServiceClientHolderInputStream(input, this);
        // stream in a filter that will trigger progress reports.
        if (progressListenerCallbackExecutor != null) {
            @SuppressWarnings("resource") final ProgressReportingInputStream progressReportingInputStream = new ProgressReportingInputStream(input, progressListenerCallbackExecutor);
            progressReportingInputStream.setFireCompletedEvent(true);
            progressReportingInputStream.setNotificationThreshold(this.notificationThreshold);
            input = progressReportingInputStream;
            fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.STARTED_EVENT_CODE);
        }
        // Ensures the data received from S3 has the same length as the
        // expected content-length
        input = new LengthCheckInputStream(input, // expected length
        s3Object.getObjectMetadata().getContentLength(), // bytes received from S3 are all included even if skipped
        INCLUDE_SKIPPED_BYTES);
        // Re-wrap within an S3ObjectInputStream. Explicitly do not collect
        // metrics here because we know we're ultimately wrapping another
        // S3ObjectInputStream which will take care of that.
        s3Object.setObjectContent(new S3ObjectInputStream(input));
        return s3Object;
    } catch (final AmazonS3Exception ase) {
        /*
             * If the request failed because one of the specified constraints
             * was not met (ex: matching ETag, modified since date, etc.), then
             * return null, so that users don't have to wrap their code in
             * try/catch blocks and check for this status code if they want to
             * use constraints.
             */
        if (ase.getStatusCode() == 412 || ase.getStatusCode() == 304) {
            fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.CANCELED_EVENT_CODE);
            return null;
        }
        fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.FAILED_EVENT_CODE);
        throw ase;
    }
}
Also used : LengthCheckInputStream(com.amazonaws.util.LengthCheckInputStream) ServiceClientHolderInputStream(com.amazonaws.util.ServiceClientHolderInputStream) LengthCheckInputStream(com.amazonaws.util.LengthCheckInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) ProgressReportingInputStream(com.amazonaws.event.ProgressReportingInputStream) RepeatableFileInputStream(com.amazonaws.services.s3.internal.RepeatableFileInputStream) InputStream(java.io.InputStream) ProgressListenerCallbackExecutor(com.amazonaws.event.ProgressListenerCallbackExecutor) ProgressListener(com.amazonaws.event.ProgressListener) S3ObjectResponseHandler(com.amazonaws.services.s3.internal.S3ObjectResponseHandler) ProgressReportingInputStream(com.amazonaws.event.ProgressReportingInputStream) ServiceClientHolderInputStream(com.amazonaws.util.ServiceClientHolderInputStream)

Example 2 with ProgressListenerCallbackExecutor

use of com.amazonaws.event.ProgressListenerCallbackExecutor in project aws-sdk-android by aws-amplify.

the class AmazonS3Client method uploadPart.

/*
     * (non-Javadoc)
     * @see
     * com.amazonaws.services.s3.AmazonS3#uploadPart(com.amazonaws.services.
     * s3.model.UploadPartRequest)
     */
@Override
public UploadPartResult uploadPart(UploadPartRequest uploadPartRequest) throws AmazonClientException, AmazonServiceException {
    assertParameterNotNull(uploadPartRequest, "The request parameter must be specified when uploading a part");
    final String bucketName = uploadPartRequest.getBucketName();
    final String key = uploadPartRequest.getKey();
    final String uploadId = uploadPartRequest.getUploadId();
    final int partNumber = uploadPartRequest.getPartNumber();
    final long partSize = uploadPartRequest.getPartSize();
    assertParameterNotNull(bucketName, "The bucket name parameter must be specified when uploading a part");
    assertParameterNotNull(key, "The key parameter must be specified when uploading a part");
    assertParameterNotNull(uploadId, "The upload ID parameter must be specified when uploading a part");
    assertParameterNotNull(partNumber, "The part number parameter must be specified when uploading a part");
    assertParameterNotNull(partSize, "The part size parameter must be specified when uploading a part");
    final Request<UploadPartRequest> request = createRequest(bucketName, key, uploadPartRequest, HttpMethodName.PUT);
    request.addParameter("uploadId", uploadId);
    request.addParameter("partNumber", Integer.toString(partNumber));
    final ObjectMetadata objectMetadata = uploadPartRequest.getObjectMetadata();
    if (objectMetadata != null) {
        populateRequestMetadata(request, objectMetadata);
    }
    request.addHeader(Headers.CONTENT_LENGTH, Long.toString(partSize));
    /*
         * HttpUrlConnection seems to be buggy in terms of implementation of
         * expect continue.
         */
    // request.addHeader("Expect", "100-continue");
    populateRequesterPaysHeader(request, uploadPartRequest.isRequesterPays());
    // Populate the SSE-CPK parameters to the request header
    populateSSE_C(request, uploadPartRequest.getSSECustomerKey());
    InputStream inputStream = null;
    if (uploadPartRequest.getInputStream() != null) {
        inputStream = uploadPartRequest.getInputStream();
    } else if (uploadPartRequest.getFile() != null) {
        try {
            inputStream = new InputSubstream(new RepeatableFileInputStream(uploadPartRequest.getFile()), uploadPartRequest.getFileOffset(), partSize, true);
        } catch (final FileNotFoundException e) {
            throw new IllegalArgumentException("The specified file doesn't exist", e);
        }
    } else {
        throw new IllegalArgumentException("A File or InputStream must be specified when uploading part");
    }
    // until request is invoked.
    if (uploadPartRequest.getMd5Digest() == null && !ServiceUtils.skipMd5CheckPerRequest(uploadPartRequest, clientOptions) && inputStream.markSupported()) {
        try {
            final String contentMd5_b64 = Md5Utils.md5AsBase64(inputStream);
            addHeaderIfNotNull(request, Headers.CONTENT_MD5, contentMd5_b64);
            inputStream.reset();
        } catch (final Exception e) {
            throw new AmazonClientException("Unable to calculate MD5 hash: " + e.getMessage(), e);
        }
    }
    /*
         * This is compatible with progress listener set by either the legacy
         * method UploadPartRequest#setProgressListener or the new method
         * UploadPartRequest#setGeneralProgressListener.
         */
    final ProgressListener progressListener = uploadPartRequest.getGeneralProgressListener();
    final ProgressListenerCallbackExecutor progressListenerCallbackExecutor = ProgressListenerCallbackExecutor.wrapListener(progressListener);
    if (progressListenerCallbackExecutor != null) {
        inputStream = new ProgressReportingInputStream(inputStream, progressListenerCallbackExecutor);
        ((ProgressReportingInputStream) inputStream).setNotificationThreshold(this.notificationThreshold);
        fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.PART_STARTED_EVENT_CODE);
    }
    try {
        request.setContent(inputStream);
        final ObjectMetadata metadata = invoke(request, new S3MetadataResponseHandler(), bucketName, key);
        fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.PART_COMPLETED_EVENT_CODE);
        final UploadPartResult result = new UploadPartResult();
        result.setETag(metadata.getETag());
        result.setPartNumber(partNumber);
        result.setSSEAlgorithm(metadata.getSSEAlgorithm());
        result.setSSECustomerAlgorithm(metadata.getSSECustomerAlgorithm());
        result.setSSECustomerKeyMd5(metadata.getSSECustomerKeyMd5());
        result.setRequesterCharged(metadata.isRequesterCharged());
        return result;
    } catch (final AmazonClientException ace) {
        fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.PART_FAILED_EVENT_CODE);
        throw ace;
    } finally {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (final Exception e) {
            }
        }
    }
}
Also used : ServiceClientHolderInputStream(com.amazonaws.util.ServiceClientHolderInputStream) LengthCheckInputStream(com.amazonaws.util.LengthCheckInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) ProgressReportingInputStream(com.amazonaws.event.ProgressReportingInputStream) RepeatableFileInputStream(com.amazonaws.services.s3.internal.RepeatableFileInputStream) InputStream(java.io.InputStream) AmazonClientException(com.amazonaws.AmazonClientException) FileNotFoundException(java.io.FileNotFoundException) RepeatableFileInputStream(com.amazonaws.services.s3.internal.RepeatableFileInputStream) AmazonServiceException(com.amazonaws.AmazonServiceException) AmazonClientException(com.amazonaws.AmazonClientException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) FileNotFoundException(java.io.FileNotFoundException) AbortedException(com.amazonaws.AbortedException) ProgressListenerCallbackExecutor(com.amazonaws.event.ProgressListenerCallbackExecutor) InputSubstream(com.amazonaws.services.s3.internal.InputSubstream) ProgressListener(com.amazonaws.event.ProgressListener) S3MetadataResponseHandler(com.amazonaws.services.s3.internal.S3MetadataResponseHandler) ProgressReportingInputStream(com.amazonaws.event.ProgressReportingInputStream)

Example 3 with ProgressListenerCallbackExecutor

use of com.amazonaws.event.ProgressListenerCallbackExecutor in project aws-sdk-android by aws-amplify.

the class AmazonS3Client method putObject.

/*
     * (non-Javadoc)
     * @see
     * com.amazonaws.services.s3.AmazonS3#putObject(com.amazonaws.services.s3
     * .model.PutObjectRequest)
     */
@Override
public PutObjectResult putObject(PutObjectRequest putObjectRequest) throws AmazonClientException, AmazonServiceException {
    assertParameterNotNull(putObjectRequest, "The PutObjectRequest parameter must be specified when uploading an object");
    final String bucketName = putObjectRequest.getBucketName();
    final String key = putObjectRequest.getKey();
    ObjectMetadata metadata = putObjectRequest.getMetadata();
    InputStream input = putObjectRequest.getInputStream();
    /*
         * This is compatible with progress listener set by either the legacy
         * method PutObjectRequest#setProgressListener or the new method
         * PutObjectRequest#setGeneralProgressListener.
         */
    final ProgressListener progressListener = putObjectRequest.getGeneralProgressListener();
    final ProgressListenerCallbackExecutor progressListenerCallbackExecutor = ProgressListenerCallbackExecutor.wrapListener(progressListener);
    if (metadata == null) {
        metadata = new ObjectMetadata();
    }
    assertParameterNotNull(bucketName, "The bucket name parameter must be specified when uploading an object");
    assertParameterNotNull(key, "The key parameter must be specified when uploading an object");
    final boolean skipContentMd5Check = ServiceUtils.skipMd5CheckPerRequest(putObjectRequest, clientOptions);
    // information from it to auto-configure a few options
    if (putObjectRequest.getFile() != null) {
        final File file = putObjectRequest.getFile();
        // Always set the content length, even if it's already set
        metadata.setContentLength(file.length());
        final boolean calculateMD5 = metadata.getContentMD5() == null;
        // Only set the content type if it hasn't already been set
        if (metadata.getContentType() == null) {
            metadata.setContentType(Mimetypes.getInstance().getMimetype(file));
        }
        if (calculateMD5 && !skipContentMd5Check) {
            try {
                final String contentMd5_b64 = Md5Utils.md5AsBase64(file);
                metadata.setContentMD5(contentMd5_b64);
            } catch (final Exception e) {
                throw new AmazonClientException("Unable to calculate MD5 hash: " + e.getMessage(), e);
            }
        }
        try {
            input = new RepeatableFileInputStream(file);
        } catch (final FileNotFoundException fnfe) {
            throw new AmazonClientException("Unable to find file to upload", fnfe);
        }
    }
    final Request<PutObjectRequest> request = createRequest(bucketName, key, putObjectRequest, HttpMethodName.PUT);
    if (putObjectRequest.getAccessControlList() != null) {
        addAclHeaders(request, putObjectRequest.getAccessControlList());
    } else if (putObjectRequest.getCannedAcl() != null) {
        request.addHeader(Headers.S3_CANNED_ACL, putObjectRequest.getCannedAcl().toString());
    }
    if (putObjectRequest.getStorageClass() != null) {
        request.addHeader(Headers.STORAGE_CLASS, putObjectRequest.getStorageClass());
    }
    if (putObjectRequest.getRedirectLocation() != null) {
        request.addHeader(Headers.REDIRECT_LOCATION, putObjectRequest.getRedirectLocation());
        if (input == null) {
            setZeroContentLength(request);
            input = new ByteArrayInputStream(new byte[0]);
        }
    }
    addHeaderIfNotNull(request, Headers.S3_TAGGING, urlEncodeTags(putObjectRequest.getTagging()));
    populateRequesterPaysHeader(request, putObjectRequest.isRequesterPays());
    // Populate the SSE-CPK parameters to the request header
    populateSSE_C(request, putObjectRequest.getSSECustomerKey());
    // Use internal interface to differentiate 0 from unset.
    final Long contentLength = (Long) metadata.getRawMetadataValue(Headers.CONTENT_LENGTH);
    if (contentLength == null) {
        /*
             * There's nothing we can do except for let the HTTP client buffer
             * the input stream contents if the caller doesn't tell us how much
             * data to expect in a stream since we have to explicitly tell
             * Amazon S3 how much we're sending before we start sending any of
             * it.
             */
        if (!input.markSupported()) {
            log.warn("No content length specified for stream data.  " + "Stream contents will be buffered in memory and could result in " + "out of memory errors.");
            final ByteArrayInputStream bais = toByteArray(input);
            request.addHeader(Headers.CONTENT_LENGTH, String.valueOf(bais.available()));
            request.setStreaming(true);
            input = bais;
        } else {
            final long len = calculateContentLength(input);
            request.addHeader(Headers.CONTENT_LENGTH, String.valueOf(len));
        }
    } else {
        final long expectedLength = contentLength.longValue();
        if (expectedLength >= 0) {
            // Performs length check on the underlying data stream.
            // For S3 encryption client, the underlying data stream here
            // refers to the cipher-text data stream (ie not the underlying
            // plain-text data stream which in turn may have been wrapped
            // with it's own length check input stream.)
            @SuppressWarnings("resource") final LengthCheckInputStream lcis = new LengthCheckInputStream(input, // expected data length to be uploaded
            expectedLength, EXCLUDE_SKIPPED_BYTES);
            input = lcis;
            request.addHeader(Headers.CONTENT_LENGTH, contentLength.toString());
        }
    }
    if (progressListenerCallbackExecutor != null) {
        input = new ProgressReportingInputStream(input, progressListenerCallbackExecutor);
        ((ProgressReportingInputStream) input).setNotificationThreshold(this.notificationThreshold);
        fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.STARTED_EVENT_CODE);
    }
    if (metadata.getContentType() == null) {
        /*
             * Default to the "application/octet-stream" if the user hasn't
             * specified a content type.
             */
        metadata.setContentType(Mimetypes.MIMETYPE_OCTET_STREAM);
    }
    populateRequestMetadata(request, metadata);
    populateSSE_KMS(request, putObjectRequest.getSSEAwsKeyManagementParams());
    request.setContent(input);
    /*
         * Enable 100-continue support for PUT operations, since this is where
         * we're potentially uploading large amounts of data and want to find
         * out as early as possible if an operation will fail. We don't want to
         * do this for all operations since it will cause extra latency in the
         * network interaction.
         */
    /*
         * HttpUrlConnection seems to be buggy in terms of implementation of
         * expect continue.
         */
    // request.addHeader("Expect", "100-continue");
    ObjectMetadata returnedMetadata = null;
    try {
        returnedMetadata = invoke(request, new S3MetadataResponseHandler(), bucketName, key);
    } catch (final AmazonClientException ace) {
        fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.FAILED_EVENT_CODE);
        throw ace;
    } finally {
        try {
            input.close();
        } catch (final AbortedException ignore) {
        } catch (final Exception e) {
            log.debug("Unable to cleanly close input stream: " + e.getMessage(), e);
        }
    }
    fireProgressEvent(progressListenerCallbackExecutor, ProgressEvent.COMPLETED_EVENT_CODE);
    final PutObjectResult result = new PutObjectResult();
    result.setVersionId(returnedMetadata.getVersionId());
    result.setSSEAlgorithm(returnedMetadata.getSSEAlgorithm());
    result.setSSECustomerAlgorithm(returnedMetadata.getSSECustomerAlgorithm());
    result.setSSECustomerKeyMd5(returnedMetadata.getSSECustomerKeyMd5());
    result.setExpirationTime(returnedMetadata.getExpirationTime());
    result.setExpirationTimeRuleId(returnedMetadata.getExpirationTimeRuleId());
    result.setETag(returnedMetadata.getETag());
    result.setMetadata(returnedMetadata);
    result.setRequesterCharged(returnedMetadata.isRequesterCharged());
    result.setContentMd5(returnedMetadata.getContentMD5());
    return result;
}
Also used : LengthCheckInputStream(com.amazonaws.util.LengthCheckInputStream) ServiceClientHolderInputStream(com.amazonaws.util.ServiceClientHolderInputStream) LengthCheckInputStream(com.amazonaws.util.LengthCheckInputStream) ByteArrayInputStream(java.io.ByteArrayInputStream) ProgressReportingInputStream(com.amazonaws.event.ProgressReportingInputStream) RepeatableFileInputStream(com.amazonaws.services.s3.internal.RepeatableFileInputStream) InputStream(java.io.InputStream) AmazonClientException(com.amazonaws.AmazonClientException) FileNotFoundException(java.io.FileNotFoundException) RepeatableFileInputStream(com.amazonaws.services.s3.internal.RepeatableFileInputStream) AmazonServiceException(com.amazonaws.AmazonServiceException) AmazonClientException(com.amazonaws.AmazonClientException) IOException(java.io.IOException) URISyntaxException(java.net.URISyntaxException) FileNotFoundException(java.io.FileNotFoundException) AbortedException(com.amazonaws.AbortedException) ProgressListenerCallbackExecutor(com.amazonaws.event.ProgressListenerCallbackExecutor) ProgressListener(com.amazonaws.event.ProgressListener) ByteArrayInputStream(java.io.ByteArrayInputStream) AbortedException(com.amazonaws.AbortedException) File(java.io.File) S3MetadataResponseHandler(com.amazonaws.services.s3.internal.S3MetadataResponseHandler) ProgressReportingInputStream(com.amazonaws.event.ProgressReportingInputStream)

Aggregations

ProgressListener (com.amazonaws.event.ProgressListener)3 ProgressListenerCallbackExecutor (com.amazonaws.event.ProgressListenerCallbackExecutor)3 ProgressReportingInputStream (com.amazonaws.event.ProgressReportingInputStream)3 RepeatableFileInputStream (com.amazonaws.services.s3.internal.RepeatableFileInputStream)3 LengthCheckInputStream (com.amazonaws.util.LengthCheckInputStream)3 ServiceClientHolderInputStream (com.amazonaws.util.ServiceClientHolderInputStream)3 ByteArrayInputStream (java.io.ByteArrayInputStream)3 InputStream (java.io.InputStream)3 AbortedException (com.amazonaws.AbortedException)2 AmazonClientException (com.amazonaws.AmazonClientException)2 AmazonServiceException (com.amazonaws.AmazonServiceException)2 S3MetadataResponseHandler (com.amazonaws.services.s3.internal.S3MetadataResponseHandler)2 FileNotFoundException (java.io.FileNotFoundException)2 IOException (java.io.IOException)2 URISyntaxException (java.net.URISyntaxException)2 InputSubstream (com.amazonaws.services.s3.internal.InputSubstream)1 S3ObjectResponseHandler (com.amazonaws.services.s3.internal.S3ObjectResponseHandler)1 File (java.io.File)1