class S3BinaryStore extends AbstractBinaryStore {

    @Override
    public BinaryValue storeValue(InputStream stream, boolean markAsUnused) throws BinaryStoreException {
        // Cache file on the file system in order to have SHA-1 hash calculated
        // File is marked as used (unused=false)
        BinaryValue cachedFile = fileSystemCache.storeValue(stream, false);
        try {
            // Retrieve SHA-1 hash
            BinaryKey key = new BinaryKey(cachedFile.getKey().toString());

            // If file is NOT already in S3 storage, store it
            if (!s3Client.doesObjectExist(bucketName, key.toString())) {
                ObjectMetadata metadata = new ObjectMetadata();
                metadata.setContentLength(cachedFile.getSize());
                // Set Mimetype
                metadata.setContentType(fileSystemCache.getMimeType(cachedFile, key.toString()));
                // Store content in S3
                s3Client.putObject(bucketName, key.toString(), fileSystemCache.getInputStream(key), metadata);
            }

            // Set the unused value, if necessary
            if (markAsUnused) {
                markAsUnused(Collections.singleton(key));
            } else {
                markAsUsed(Collections.singleton(key));
            }

            return new StoredBinaryValue(this, key, cachedFile.getSize());
        } catch (AmazonClientException|RepositoryException |IOException e) {
            throw new BinaryStoreException(e);
        } finally {
            // Remove cached file
            fileSystemCache.markAsUnused(Collections.singleton(cachedFile.getKey()));
            fileSystemCache.removeValuesUnusedLongerThan(1, TimeUnit.MICROSECONDS);
        }
    }

    public  S3BinaryStore(String accessKey, String secretKey, String bucketName);
    public  S3BinaryStore(String accessKey, String secretKey, String bucketName, String endPoint);
    public  S3BinaryStore( String accessKey,
                          String secretKey,
                          String bucketName,
                          String endPoint,
                          Boolean deleteUnusedNatively );
    protected  S3BinaryStore(String bucketName, AmazonS3 s3Client, boolean deleteUnusedNatively);

}