protected final ObjectMetadata updateMetadataWithContentCryptoMaterial(
     ObjectMetadata metadata, File file, ContentCryptoMaterial instruction) {
   if (metadata == null) metadata = new ObjectMetadata();
   if (file != null) {
     Mimetypes mimetypes = Mimetypes.getInstance();
     metadata.setContentType(mimetypes.getMimetype(file));
   }
   return instruction.toObjectMetadata(metadata);
 }
 protected final PutObjectRequest createInstructionPutRequest(
     String bucketName, String key, ContentCryptoMaterial cekMaterial) {
   byte[] bytes = cekMaterial.toJsonString().getBytes(UTF8);
   InputStream is = new ByteArrayInputStream(bytes);
   ObjectMetadata metadata = new ObjectMetadata();
   metadata.setContentLength(bytes.length);
   metadata.addUserMetadata(Headers.CRYPTO_INSTRUCTION_FILE, "");
   return new PutObjectRequest(bucketName, key + INSTRUCTION_SUFFIX, is, metadata);
 }
  private CipherLiteInputStream newS3CipherLiteInputStream(
      PutObjectRequest req, ContentCryptoMaterial cekMaterial, long plaintextLength) {
    try {
      InputStream is = req.getInputStream();
      if (req.getFile() != null) is = new RepeatableFileInputStream(req.getFile());
      if (plaintextLength > -1) {
        // S3 allows a single PUT to be no more than 5GB, which
        // therefore won't exceed the maximum length that can be
        // encrypted either using any cipher such as CBC or GCM.

        // This ensures the plain-text read from the underlying data
        // stream has the same length as the expected total.
        is = new LengthCheckInputStream(is, plaintextLength, EXCLUDE_SKIPPED_BYTES);
      }
      return new CipherLiteInputStream(is, cekMaterial.getCipherLite(), DEFAULT_BUFFER_SIZE);
    } catch (Exception e) {
      throw new AmazonClientException("Unable to create cipher input stream: " + e.getMessage(), e);
    }
  }
 /**
  * Updates put request to store the specified instruction object in S3.
  *
  * @param request The put request for the original object to be stored in S3.
  * @param cekMaterial The instruction object to be stored in S3.
  * @return A put request to store the specified instruction object in S3.
  */
 protected final PutObjectRequest upateInstructionPutRequest(
     PutObjectRequest request, ContentCryptoMaterial cekMaterial) {
   byte[] bytes = cekMaterial.toJsonString().getBytes(UTF8);
   InputStream is = new ByteArrayInputStream(bytes);
   ObjectMetadata metadata = request.getMetadata();
   if (metadata == null) {
     metadata = new ObjectMetadata();
     request.setMetadata(metadata);
   }
   // Set the content-length of the upload
   metadata.setContentLength(bytes.length);
   // Set the crypto instruction file header
   metadata.addUserMetadata(Headers.CRYPTO_INSTRUCTION_FILE, "");
   // Update the instruction request
   request.setKey(request.getKey() + INSTRUCTION_SUFFIX);
   request.setMetadata(metadata);
   request.setInputStream(is);
   request.setFile(null);
   return request;
 }