All Downloads are FREE. Search and download functionalities are using the official Maven repository.

technology.dice.dicewhere.downloader.destination.s3.S3FileAcceptor Maven / Gradle / Ivy

There is a newer version: 1.3.12
Show newest version
package technology.dice.dicewhere.downloader.destination.s3;

import com.fasterxml.jackson.databind.ObjectMapper;
import java.net.URI;
import java.nio.file.Paths;
import java.time.Clock;
import java.time.Instant;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.HeadObjectRequest;
import software.amazon.awssdk.services.s3.model.HeadObjectResponse;
import software.amazon.awssdk.services.s3.model.NoSuchKeyException;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.StorageClass;
import software.amazon.awssdk.utils.StringInputStream;
import technology.dice.dicewhere.downloader.destination.FileAcceptor;
import technology.dice.dicewhere.downloader.md5.MD5Checksum;
import technology.dice.dicewhere.downloader.stream.StreamConsumer;

public class S3FileAcceptor implements FileAcceptor {

  private static final String LATEST_KEY = "latest";
  public static final String MD5_METADATA_KEY = "md5";
  public static final String TIMESTAMP_METADATA_KEY = "ts";
  private final S3Client client;
  private final String bucket;
  private final String key;
  private final Clock clock;
  private final ObjectMapper mapper;

  public S3FileAcceptor(
      S3Client client, String bucket, String key, ObjectMapper mapper, Clock clock) {
    this.client = client;
    this.bucket = bucket;
    this.key = key;
    this.mapper = mapper;
    this.clock = clock;
  }

  @Override
  public StreamConsumer getStreamConsumer(
      MD5Checksum originalFileMd5, Instant originalFileTimestamp) {
    return (StreamConsumer)
        (stream, size) -> {
          Map objectMetadata = new HashMap<>();
          objectMetadata.put(MD5_METADATA_KEY, originalFileMd5.stringFormat());
          objectMetadata.put(
              TIMESTAMP_METADATA_KEY, String.valueOf(originalFileTimestamp.toEpochMilli()));
          PutObjectRequest putObjectRequest =
              PutObjectRequest.builder()
                  .key(key)
                  .bucket(bucket)
                  .metadata(objectMetadata)
                  .contentLength(size)
                  .storageClass(StorageClass.INTELLIGENT_TIERING)
                  .build();
          client.putObject(putObjectRequest, RequestBody.fromInputStream(stream, size));

          Latest latest = new Latest(clock.instant(), key);
          String latestContent = mapper.writeValueAsString(latest);

          PutObjectRequest putLatest =
              PutObjectRequest.builder()
                  .key(Paths.get(key).getParent().toString() + "/" + LATEST_KEY)
                  .bucket(bucket)
                  .contentLength(new Long(latestContent.length()))
                  .storageClass(StorageClass.INTELLIGENT_TIERING)
                  .build();
          client.putObject(
              putLatest,
              RequestBody.fromInputStream(
                  new StringInputStream(latestContent), latestContent.length()));

          return null;
        };
  }

  @Override
  public boolean destinationExists() {
    HeadObjectRequest headObjectRequest =
        HeadObjectRequest.builder().bucket(bucket).key(key).build();

    try {
      client.headObject(headObjectRequest);
      return true;
    } catch (NoSuchKeyException e) {
      return false;
    }
  }

  @Override
  public boolean destinationWritable() {
    return true;
  }

  @Override
  public Optional existingFileMd5() {
    HeadObjectRequest headObjectRequest =
        HeadObjectRequest.builder().bucket(bucket).key(key).build();

    try {
      final HeadObjectResponse headObjectResponse = client.headObject(headObjectRequest);
      final Map metadata = headObjectResponse.metadata();
      return Optional.ofNullable(metadata.get(MD5_METADATA_KEY)).map(m -> MD5Checksum.of(m));
    } catch (NoSuchKeyException e) {
      return Optional.empty();
    }
  }

  @Override
  public URI getUri() {
    return URI.create("s3://" + bucket + "/" + key);
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy