Skip to content

Commit

Permalink
Fixing merge issue
Browse files Browse the repository at this point in the history
  • Loading branch information
glenrobson committed Jul 16, 2024
1 parent df355d7 commit b02b98d
Showing 1 changed file with 0 additions and 153 deletions.
153 changes: 0 additions & 153 deletions src/main/java/edu/illinois/library/cantaloupe/cache/S3Cache.java
Original file line number Diff line number Diff line change
Expand Up @@ -62,159 +62,6 @@
*/
class S3Cache implements DerivativeCache {

<<<<<<< HEAD
=======
/**
* <p>Wraps a {@link ByteArrayOutputStream} for upload to S3.</p>
*
* <p>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}:</p>
*
* <blockquote>"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."</blockquote>
*
* <p>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.)</p>
*/
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);

Expand Down

0 comments on commit b02b98d

Please sign in to comment.