diff --git a/src/main/java/edu/illinois/library/cantaloupe/cache/S3Cache.java b/src/main/java/edu/illinois/library/cantaloupe/cache/S3Cache.java index 1ef50e7e0..d01117de1 100644 --- a/src/main/java/edu/illinois/library/cantaloupe/cache/S3Cache.java +++ b/src/main/java/edu/illinois/library/cantaloupe/cache/S3Cache.java @@ -62,159 +62,6 @@ */ class S3Cache implements DerivativeCache { -<<<<<<< HEAD -======= - /** - *

Wraps a {@link ByteArrayOutputStream} for upload to S3.

- * - *

N.B.: S3 does not allow uploads without a {@code Content-Length} - * header, which cannot be provided when streaming an unknown amount of - * data (which this class is going to be doing all the time). From the - * documentation of {@link PutObjectRequest}:

- * - *
"When uploading directly from an input stream, content - * length must be specified before data can be uploaded to Amazon S3. If - * not provided, the library will have to buffer the contents of the input - * stream in order to calculate it. Amazon S3 explicitly requires that the - * content length be sent in the request headers before any of the data is - * sent."
- * - *

Since it's not possible to write an {@link OutputStream} of unknown - * length to the S3 client as the {@link Cache} interface requires, this - * class buffers written data in a byte array before uploading it to S3 - * upon closure. (The upload is submitted to the - * {@link ThreadPool#getInstance() application thread pool} in order for - * {@link #close()} to be able to return immediately.)

- */ - private static class S3OutputStream extends CompletableOutputStream { - - private final ByteArrayOutputStream bufferStream = - new ByteArrayOutputStream(); - private final S3Client client; - private final String bucketName; - private final String objectKey; - private final String contentType; - - /** - * @param client S3 client. - * @param bucketName S3 bucket name. - * @param objectKey S3 object key. - * @param contentType Media type. - */ - S3OutputStream(final S3Client client, - final String bucketName, - final String objectKey, - final String contentType) { - this.client = client; - this.bucketName = bucketName; - this.objectKey = objectKey; - this.contentType = contentType; - } - - @Override - public void close() throws IOException { - try { - bufferStream.close(); - byte[] data = bufferStream.toByteArray(); - if (isComplete()) { - // At this point, the client has received all image data, - // but it is still waiting for the connection to close. - // Uploading in a separate thread will allow this to happen - // immediately. - ThreadPool.getInstance().submit(new S3Upload( - client, data, bucketName, objectKey, - contentType, null)); - } - } finally { - super.close(); - } - } - - @Override - public void flush() throws IOException { - bufferStream.flush(); - } - - @Override - public void write(int b) { - bufferStream.write(b); - } - - @Override - public void write(byte[] b) throws IOException { - bufferStream.write(b); - } - - @Override - public void write(byte[] b, int off, int len) { - bufferStream.write(b, off, len); - } - - } - - private static class S3Upload implements Runnable { - - private static final Logger UPLOAD_LOGGER = - LoggerFactory.getLogger(S3Upload.class); - - private final String bucketName, contentEncoding, contentType, objectKey; - private final byte[] data; - private final S3Client client; - - /** - * @param client S3 client. - * @param data Data to upload. - * @param bucketName S3 bucket name. - * @param objectKey S3 object key. - * @param contentType Media type. - * @param contentEncoding Content encoding. May be {@code null}. - */ - S3Upload(S3Client client, - byte[] data, - String bucketName, - String objectKey, - String contentType, - String contentEncoding) { - this.client = client; - this.bucketName = bucketName; - this.data = data; - this.contentType = contentType; - this.contentEncoding = contentEncoding; - this.objectKey = objectKey; - } - - @Override - public void run() { - if (data.length > 0) { - PutObjectRequest request = PutObjectRequest.builder() - .bucket(bucketName) - .key(objectKey) - .contentType(contentType) - .contentEncoding(contentEncoding) - .build(); - final Stopwatch watch = new Stopwatch(); - - UPLOAD_LOGGER.debug("Uploading {} bytes to {} in bucket {}", - data.length, request.key(), request.bucket()); - - try (ByteArrayInputStream is = new ByteArrayInputStream(data)) { - client.putObject(request, - RequestBody.fromInputStream(is, data.length)); - } catch (IOException e) { - UPLOAD_LOGGER.warn(e.getMessage(), e); - } - - UPLOAD_LOGGER.trace("Wrote {} bytes to {} in bucket {} in {}", - data.length, request.key(), request.bucket(), - watch); - } else { - UPLOAD_LOGGER.trace("No data to upload; returning"); - } - } - - } - ->>>>>>> 8a7e3cfe7 (Remove isCompletelyWritten() and replace with isComplete()) private static final Logger LOGGER = LoggerFactory.getLogger(S3Cache.class);