AmazonS3Downloader { public S3Object fetch(@Nonnull final S3EventNotificationRecord record) throws AmazonS3ConstraintException, AmazonS3ZeroSizeException { final AmazonS3Object object = converter.convert(Objects.requireNonNull(record)); final GetObjectRequest request = new GetObjectRequest(object.getBucketName(), object.getKey()); object.getVersionId().ifPresent(request::setVersionId); object .getETag() .ifPresent(etag -> request.setMatchingETagConstraints(Collections.singletonList(etag))); LOGGER.debug("Fetching key: {}/{}", object.getBucketName(), object.getKey()); final S3Object download; try { download = s3.getObject(request); } catch (AmazonServiceException e) { LOGGER.error("Service error while fetching object from S3", e); throw e; } catch (AmazonClientException e) { LOGGER.error("Client error while fetching object from S3", e); throw e; } if (download == null) { LOGGER.error( "eTag from object did not match for key: {}/{}", object.getBucketName(), object.getKey()); throw new AmazonS3ConstraintException(object.getKey()); } final long contentLength = download.getObjectMetadata().getContentLength(); if (contentLength < 1) { try { download.close(); } catch (IOException e) { LOGGER.error( String.format( "Failed to close S3 stream for key: %s/%s", download.getBucketName(), download.getKey()), e); } LOGGER.debug( "Object size is zero for key: {}/{}", download.getBucketName(), download.getKey()); throw new AmazonS3ZeroSizeException(object.getKey()); } LOGGER.debug( "Streaming key ({} bytes): {}/{}", contentLength, download.getBucketName(), download.getKey()); return download; } AmazonS3Downloader(@Nonnull final AmazonS3 s3); S3Object fetch(@Nonnull final S3EventNotificationRecord record); static boolean isGZipped(@Nullable final S3Object object);  }
@Test public void testFetch() throws Exception { final S3Object expected = new S3Object(); expected.setKey("object-key"); expected.setBucketName("bucket-name"); expected.getObjectMetadata().setContentLength(100); when(mockS3.getObject(any(GetObjectRequest.class))).thenReturn(expected); final S3Object actual = downloader.fetch(record); verify(mockS3).getObject(any(GetObjectRequest.class)); assertThat(actual).isEqualTo(expected); }
@Test public void testFetchInvalidETag() throws Exception { when(mockS3.getObject(any(GetObjectRequest.class))).thenReturn(null); try { final S3Object download = downloader.fetch(record); assertThat(download).isNull(); failBecauseExceptionWasNotThrown(AmazonS3ConstraintException.class); } catch (AmazonS3ConstraintException e) { } verify(mockS3).getObject(any(GetObjectRequest.class)); }
@Test public void testFetchZeroSize() throws Exception { final S3Object expected = new S3Object(); expected.setKey("object-key"); expected.setBucketName("bucket-name"); when(mockS3.getObject(any(GetObjectRequest.class))).thenReturn(expected); try { final S3Object download = downloader.fetch(record); assertThat(download).isNotNull(); failBecauseExceptionWasNotThrown(AmazonS3ZeroSizeException.class); } catch (AmazonS3ZeroSizeException e) { } verify(mockS3).getObject(any(GetObjectRequest.class)); }
@Test public void testFetchServiceException() throws Exception { when(mockS3.getObject(any(GetObjectRequest.class))) .thenThrow(new AmazonServiceException("error")); try { downloader.fetch(record); failBecauseExceptionWasNotThrown(AmazonServiceException.class); } catch (AmazonServiceException e) { } verify(mockS3).getObject(any(GetObjectRequest.class)); }
@Test public void testFetchClientException() throws Exception { when(mockS3.getObject(any(GetObjectRequest.class))) .thenThrow(new AmazonClientException("error")); try { downloader.fetch(record); failBecauseExceptionWasNotThrown(AmazonClientException.class); } catch (AmazonClientException e) { } verify(mockS3).getObject(any(GetObjectRequest.class)); }