From 7c67275d6a4f2e71c09e7d3180aa64fb840eae98 Mon Sep 17 00:00:00 2001 From: Justyna Date: Thu, 18 Jun 2020 17:46:57 +0200 Subject: [PATCH 1/4] new featur --- pom.xml | 11 +++ .../com/justinefactory/domain/AwsInfo.java | 40 +++++++++++ .../com/justinefactory/domain/PathData.java | 29 -------- .../com/justinefactory/domain/PathInfo.java | 39 +++++++++++ .../justinefactory/domain/WritingInfo.java | 12 ++++ .../reading/readers/CsvContentReader.java | 24 ++++--- .../reading/readers/PlainContentReader.java | 24 +++---- .../AwsSecurityCredentialsException.java | 9 +++ .../access/AwsSecurityCredentials.java | 40 +++++++++++ .../communication/clients/AwsClient.java | 10 +++ .../communication/clients/AwsS3Client.java | 24 +++++++ .../util/FileNotEmptyAndExistChecker.java | 8 +-- .../justinefactory/util/PathToResources.java | 19 ++++++ .../AwsContentWritingException.java | 13 ++++ .../RandomStringGeneratorFromFile.java | 16 ++--- .../writing/util/BucketCreator.java | 29 ++++++++ .../util/CheckerIfContentAlreadyWritten.java | 5 +- .../util/CheckerIfFileAlreadyWritten.java | 10 +-- .../CheckerIfServerContentAlreadyWritten.java | 25 +++++++ .../writing/util/DirectoriesCreator.java | 13 ++-- .../writing/util/StorageContainerCreator.java | 9 +++ .../writing/writers/ContentWriter.java | 8 +-- .../writers/ContentWritingService.java | 39 ++++++----- .../writers/file/writers/CsvFileWriter.java | 8 +-- .../writers/file/writers/PlainFileWriter.java | 8 +-- .../writers/server/writers/JsonAwsWriter.java | 29 ++++++++ .../readers/ContentReadingServiceTest.java | 6 +- .../reading/readers/CsvContentReaderTest.java | 6 +- .../readers/PlainContentReaderTest.java | 6 +- .../testutil/AwsClientCreatorBeforeEach.java | 17 +++++ .../RandomStringGeneratorFromFileTest.java | 8 +-- .../ThreeElementContentGeneratorTest.java | 4 +- .../writing/util/BucketCreatorTest.java | 58 ++++++++++++++++ .../util/CheckerIfFileAlreadyWrittenTest.java | 4 +- ...ckerIfServerContentAlreadyWrittenTest.java | 58 ++++++++++++++++ .../writing/writers/CsvFileWriterTest.java | 4 +- .../writing/writers/PlainFileWriterTest.java | 6 +- .../server/writers/JsonAwsWriterTest.java | 67 +++++++++++++++++++ src/test/resources/AwsRootKey.csv | 2 + 39 files changed, 614 insertions(+), 133 deletions(-) create mode 100644 src/main/java/com/justinefactory/domain/AwsInfo.java delete mode 100644 src/main/java/com/justinefactory/domain/PathData.java create mode 100644 src/main/java/com/justinefactory/domain/PathInfo.java create mode 100644 src/main/java/com/justinefactory/domain/WritingInfo.java create mode 100644 src/main/java/com/justinefactory/sending/exceptions/AwsSecurityCredentialsException.java create mode 100644 src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java create mode 100644 src/main/java/com/justinefactory/server/communication/clients/AwsClient.java create mode 100644 src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java create mode 100644 src/main/java/com/justinefactory/util/PathToResources.java create mode 100644 src/main/java/com/justinefactory/writing/exceptions/AwsContentWritingException.java create mode 100644 src/main/java/com/justinefactory/writing/util/BucketCreator.java create mode 100644 src/main/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWritten.java create mode 100644 src/main/java/com/justinefactory/writing/util/StorageContainerCreator.java create mode 100644 src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java create mode 100644 src/test/java/com/justinefactory/testutil/AwsClientCreatorBeforeEach.java create mode 100644 src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java create mode 100644 src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java create mode 100644 src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java create mode 100644 src/test/resources/AwsRootKey.csv diff --git a/pom.xml b/pom.xml index 45b9f8f..a3db297 100644 --- a/pom.xml +++ b/pom.xml @@ -58,6 +58,17 @@ gson 2.8.6 + + com.amazonaws + aws-java-sdk + 1.11.799 + + + javax.xml.bind + jaxb-api + 2.4.0-b180830.0359 + + diff --git a/src/main/java/com/justinefactory/domain/AwsInfo.java b/src/main/java/com/justinefactory/domain/AwsInfo.java new file mode 100644 index 0000000..1b274f8 --- /dev/null +++ b/src/main/java/com/justinefactory/domain/AwsInfo.java @@ -0,0 +1,40 @@ +package com.justinefactory.domain; + +import java.net.URI; +import java.util.UUID; + +public class AwsInfo implements WritingInfo { + + private final URI uri; + private final UUID id; + private final String BUCKET_NAME; + private final String KEY_NAME; + + + public AwsInfo(String bucketName, String keyName) { + BUCKET_NAME = bucketName; + KEY_NAME = keyName; + uri = URI.create(BUCKET_NAME + "/" + KEY_NAME); + id = UUID.randomUUID(); + } + + + @Override + public URI getURI() { + return uri; + } + + @Override + public UUID getId() { + return id; + } + + public String getBucketName() { + return BUCKET_NAME; + } + + public String getKeyName() { + return KEY_NAME; + } + +} diff --git a/src/main/java/com/justinefactory/domain/PathData.java b/src/main/java/com/justinefactory/domain/PathData.java deleted file mode 100644 index 2f30e20..0000000 --- a/src/main/java/com/justinefactory/domain/PathData.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.justinefactory.domain; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.lang.invoke.MethodHandles; -import java.nio.file.Path; -import java.util.UUID; - -public class PathData { - - private final Path filePath; - private final UUID fileId; - private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - - public PathData(Path filePath) { - this.filePath = filePath; - this.fileId = UUID.randomUUID(); - logger.debug("New file {} has been initialized with path {}", fileId, filePath); - } - - public Path getFilePath() { - return filePath; - } - - public UUID getFileId() { - return fileId; - } -} diff --git a/src/main/java/com/justinefactory/domain/PathInfo.java b/src/main/java/com/justinefactory/domain/PathInfo.java new file mode 100644 index 0000000..485284c --- /dev/null +++ b/src/main/java/com/justinefactory/domain/PathInfo.java @@ -0,0 +1,39 @@ +package com.justinefactory.domain; + +import java.net.URI; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.UUID; + +public class PathInfo implements WritingInfo { + + private final Path path; + private final URI uri; + private final UUID id; + + public PathInfo(Path filePath) { + path = filePath; + uri = path.toUri(); + id = UUID.randomUUID(); + } + + public PathInfo(URI u) { + uri = u; + path = Paths.get(uri); + id = UUID.randomUUID(); + } + + @Override + public URI getURI() { + return uri; + } + + @Override + public UUID getId() { + return id; + } + + public Path getPath() { + return path; + } +} diff --git a/src/main/java/com/justinefactory/domain/WritingInfo.java b/src/main/java/com/justinefactory/domain/WritingInfo.java new file mode 100644 index 0000000..102f224 --- /dev/null +++ b/src/main/java/com/justinefactory/domain/WritingInfo.java @@ -0,0 +1,12 @@ +package com.justinefactory.domain; + +import java.net.URI; +import java.util.UUID; + +public interface WritingInfo { + + URI getURI(); + + UUID getId(); + +} diff --git a/src/main/java/com/justinefactory/reading/readers/CsvContentReader.java b/src/main/java/com/justinefactory/reading/readers/CsvContentReader.java index d515d41..6fd4c59 100644 --- a/src/main/java/com/justinefactory/reading/readers/CsvContentReader.java +++ b/src/main/java/com/justinefactory/reading/readers/CsvContentReader.java @@ -1,6 +1,6 @@ package com.justinefactory.reading.readers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.reading.exceptions.ContentReadingException; import com.justinefactory.reading.exceptions.ReadingContentFromFileException; import com.justinefactory.reading.exceptions.SourceFileIsEmptyException; @@ -12,36 +12,38 @@ import java.io.Reader; import java.lang.invoke.MethodHandles; import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; import static com.justinefactory.util.FileNotEmptyAndExistChecker.checkIfFileExistsIsNotDirAndNotEmpty; class CsvContentReader implements ContentReader { - private final PathData fileData; + private final PathInfo fileData; private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - CsvContentReader(PathData fd) { + CsvContentReader(PathInfo fd) { fileData = fd; } @Override public ContentStorage readContent() throws ContentReadingException { - logger.debug("Reading data from file id {}", fileData.getFileId()); - if (!checkIfFileExistsIsNotDirAndNotEmpty(fileData.getFilePath())) { - logger.warn("Reading data from file id {} failed. File does not exist or is empty.", fileData.getFileId()); - throw new SourceFileIsEmptyException("Reading data from file id " + fileData.getFileId() + " - failed. File does not exist or is empty."); + logger.debug("Reading data from file id {}", fileData.getId()); + if (!checkIfFileExistsIsNotDirAndNotEmpty(fileData.getPath())) { + logger.warn("Reading data from file id {} failed. File does not exist or is empty.", fileData.getId()); + throw new SourceFileIsEmptyException("Reading data from file id " + fileData.getId() + " - failed. File does not exist or is empty."); } - try (Reader reader = Files.newBufferedReader(fileData.getFilePath()); + try (Reader reader = Files.newBufferedReader(fileData.getPath()); CSVReader csvReader = new CSVReader(reader) ) { ContentStorage rawContent = new ContentStorage<>(csvReader.readAll()); - logger.debug("Reading data from file id {} - success.", fileData.getFileId()); + logger.debug("Reading data from file id {} - success.", fileData.getId()); return rawContent; } catch (Throwable e) { - logger.warn("Reading data from file id {} failed.", fileData.getFileId(), e); - throw new ReadingContentFromFileException(e, "Reading data from file id " + fileData.getFileId() + " - failed."); + logger.warn("Reading data from file id {} failed.", fileData.getId(), e); + throw new ReadingContentFromFileException(e, "Reading data from file id " + fileData.getId() + " - failed."); } } } diff --git a/src/main/java/com/justinefactory/reading/readers/PlainContentReader.java b/src/main/java/com/justinefactory/reading/readers/PlainContentReader.java index 723b5da..61405bd 100644 --- a/src/main/java/com/justinefactory/reading/readers/PlainContentReader.java +++ b/src/main/java/com/justinefactory/reading/readers/PlainContentReader.java @@ -1,6 +1,6 @@ package com.justinefactory.reading.readers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.reading.exceptions.ContentReadingException; import com.justinefactory.reading.exceptions.ReadingContentFromFileException; import com.justinefactory.reading.exceptions.SourceFileIsEmptyException; @@ -15,30 +15,30 @@ class PlainContentReader implements ContentReader { - private final PathData fileData; + private final PathInfo fileData; private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - PlainContentReader(PathData fd) { + PlainContentReader(PathInfo fd) { fileData = fd; } @Override public ContentStorage readContent() throws ContentReadingException { - logger.debug("Reading data from file id {}", fileData.getFileId()); - if (!checkIfFileExistsIsNotDirAndNotEmpty(fileData.getFilePath())) { - logger.warn("Reading data from file id {} failed. File does not exist or is empty.", fileData.getFileId()); - throw new SourceFileIsEmptyException("Reading data from file id " + fileData.getFileId() + " - failed. File does not exist or is empty."); + logger.debug("Reading data from file id {}", fileData.getId()); + if (!checkIfFileExistsIsNotDirAndNotEmpty(fileData.getPath())) { + logger.warn("Reading data from file id {} failed. File does not exist or is empty.", fileData.getId()); + throw new SourceFileIsEmptyException("Reading data from file id " + fileData.getId() + " - failed. File does not exist or is empty."); } - try{ - ContentStorage rawContent = new ContentStorage<>(Files.readAllLines(fileData.getFilePath())); - logger.debug("Reading data from file id {} - success.", fileData.getFileId()); + ContentStorage rawContent = new ContentStorage<>(Files.readAllLines(fileData.getPath())); + logger.debug("Reading data from file id {} - success.", fileData.getId()); return rawContent; } catch (Throwable e) { - logger.warn("Reading data from file id {} failed.", fileData.getFileId(), e); - throw new ReadingContentFromFileException(e, "Reading data from file id " + fileData.getFileId() + " - failed. Problem while reading all lines."); + logger.warn("Reading data from file id {} failed.", fileData.getId(), e); + throw new ReadingContentFromFileException(e, "Reading data from file id " + fileData.getId() + " - failed. Problem while reading all lines."); } } + } diff --git a/src/main/java/com/justinefactory/sending/exceptions/AwsSecurityCredentialsException.java b/src/main/java/com/justinefactory/sending/exceptions/AwsSecurityCredentialsException.java new file mode 100644 index 0000000..9552c24 --- /dev/null +++ b/src/main/java/com/justinefactory/sending/exceptions/AwsSecurityCredentialsException.java @@ -0,0 +1,9 @@ +package com.justinefactory.sending.exceptions; + +public class AwsSecurityCredentialsException extends Exception { + + public AwsSecurityCredentialsException(Throwable cause, String message) { + super(message, cause); + } + +} diff --git a/src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java b/src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java new file mode 100644 index 0000000..cb7c607 --- /dev/null +++ b/src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java @@ -0,0 +1,40 @@ +package com.justinefactory.server.communication.access; + +import com.amazonaws.auth.AWSCredentials; +import com.amazonaws.auth.BasicAWSCredentials; +import com.justinefactory.sending.exceptions.AwsSecurityCredentialsException; + +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; + +import static com.justinefactory.util.PathToResources.getPathToResource; + +public class AwsSecurityCredentials { + + private final String ACCESS_KEY_ID; + private final String SECRET_ACCESS_KEY; + + + public AwsSecurityCredentials() throws AwsSecurityCredentialsException { + List securityInfo = getAccessKeys(); + ACCESS_KEY_ID = securityInfo.get(0); + SECRET_ACCESS_KEY = securityInfo.get(1); + } + + + public AWSCredentials getCredentials() { + return new BasicAWSCredentials(ACCESS_KEY_ID, SECRET_ACCESS_KEY); + } + + + private List getAccessKeys() throws AwsSecurityCredentialsException { + try { + Path path = getPathToResource("AwsRootKey.csv"); + return Files.readAllLines(path); + } catch (Throwable e) { + throw new AwsSecurityCredentialsException(e, "Trouble while acquiring security credentials."); + } + } + +} diff --git a/src/main/java/com/justinefactory/server/communication/clients/AwsClient.java b/src/main/java/com/justinefactory/server/communication/clients/AwsClient.java new file mode 100644 index 0000000..b06c453 --- /dev/null +++ b/src/main/java/com/justinefactory/server/communication/clients/AwsClient.java @@ -0,0 +1,10 @@ +package com.justinefactory.server.communication.clients; + +import com.amazonaws.regions.Regions; +import com.amazonaws.services.s3.internal.S3DirectSpi; +import com.justinefactory.server.communication.access.AwsSecurityCredentials; + +public interface AwsClient { + + S3DirectSpi buildClient(Regions region, AwsSecurityCredentials awsSecurityCredentials); +} diff --git a/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java b/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java new file mode 100644 index 0000000..64c2e0d --- /dev/null +++ b/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java @@ -0,0 +1,24 @@ +package com.justinefactory.server.communication.clients; + +import com.amazonaws.AmazonClientException; +import com.amazonaws.auth.AWSStaticCredentialsProvider; +import com.amazonaws.regions.Regions; +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.AmazonS3ClientBuilder; +import com.justinefactory.server.communication.access.AwsSecurityCredentials; + +public class AwsS3Client implements AwsClient { + + @Override + public AmazonS3 buildClient(Regions region, AwsSecurityCredentials awsSecurityCredentials) { + try { + return AmazonS3ClientBuilder + .standard() + .withCredentials(new AWSStaticCredentialsProvider(awsSecurityCredentials.getCredentials())) + .withRegion(region) + .build(); + } catch (Throwable e) { + throw new AmazonClientException("Trouble while building an AWSS3 client. Incorrect credentials or region.", e); + } + } +} diff --git a/src/main/java/com/justinefactory/util/FileNotEmptyAndExistChecker.java b/src/main/java/com/justinefactory/util/FileNotEmptyAndExistChecker.java index 4b15d89..88269f0 100644 --- a/src/main/java/com/justinefactory/util/FileNotEmptyAndExistChecker.java +++ b/src/main/java/com/justinefactory/util/FileNotEmptyAndExistChecker.java @@ -12,12 +12,12 @@ public class FileNotEmptyAndExistChecker { private static final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - public static boolean checkIfFileExistsIsNotDirAndNotEmpty(Path filePath) throws ContentReadingException { + public static boolean checkIfFileExistsIsNotDirAndNotEmpty(Path path) throws ContentReadingException { try { - return (Files.exists(filePath) & Files.size(filePath) > 0 & !Files.isDirectory(filePath)); + return (Files.exists(path) & Files.size(path) > 0 & !Files.isDirectory(path)); } catch (Throwable e) { - logger.warn("Reading data from file id {} failed.", filePath, e); - throw new ContentReadingException(e,"Reading data from file id " + filePath + " - failed."); + logger.warn("Reading data from file id {} failed.", path, e); + throw new ContentReadingException(e,"Reading data from file id " + path + " - failed."); } } diff --git a/src/main/java/com/justinefactory/util/PathToResources.java b/src/main/java/com/justinefactory/util/PathToResources.java new file mode 100644 index 0000000..73b8e9a --- /dev/null +++ b/src/main/java/com/justinefactory/util/PathToResources.java @@ -0,0 +1,19 @@ +package com.justinefactory.util; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class PathToResources { + + public static Path getPathToResource(String name) throws Exception { + if (name.startsWith("/")) { + return getPath(name); + } else { + return getPath("/" + name); + } + } + + private static Path getPath(String name) throws Exception { + return Paths.get(PathToResources.class.getResource(name).toURI()); + } +} diff --git a/src/main/java/com/justinefactory/writing/exceptions/AwsContentWritingException.java b/src/main/java/com/justinefactory/writing/exceptions/AwsContentWritingException.java new file mode 100644 index 0000000..9344931 --- /dev/null +++ b/src/main/java/com/justinefactory/writing/exceptions/AwsContentWritingException.java @@ -0,0 +1,13 @@ +package com.justinefactory.writing.exceptions; + +public class AwsContentWritingException extends ContentWritingException { + + public AwsContentWritingException(Throwable cause, String message) { + super(cause, message); + } + + public AwsContentWritingException(String message) { + super(message); + } + +} diff --git a/src/main/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFile.java b/src/main/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFile.java index 79b9e48..4346670 100644 --- a/src/main/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFile.java +++ b/src/main/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFile.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.generators; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.domain.TwoElemContent; import com.justinefactory.writing.exceptions.ContentGeneratingException; @@ -24,7 +24,7 @@ public class RandomStringGeneratorFromFile implements ContentGenerator generateContent(int nLines) { } - private List readStringsFromFile(PathData stringFile) throws ContentInitializationException { - logger.debug("Reading file id {} containing strings for random generator.", stringFile.getFileId()); + private List readStringsFromFile(PathInfo stringFile) throws ContentInitializationException { + logger.debug("Reading file id {} containing strings for random generator.", stringFile.getId()); try { - List randomStrings = Files.readAllLines(stringFile.getFilePath()); + List randomStrings = Files.readAllLines(stringFile.getPath()); if (randomStrings.isEmpty()) { - logger.warn("File id {} containing strings for random generator is empty.", stringFile.getFileId()); + logger.warn("File id {} containing strings for random generator is empty.", stringFile.getId()); throw new FileWithStringsToGenerateContentIsEmptyException("File containing strings for random generator is empty."); } - logger.info("File id {} containing strings for random generator has been read successfully.", stringFile.getFileId()); + logger.info("File id {} containing strings for random generator has been read successfully.", stringFile.getId()); return randomStrings; } catch (IOException e) { - logger.error("Could not read file id {} containing strings for random generator.", stringFile.getFileId()); + logger.error("Could not read file id {} containing strings for random generator.", stringFile.getId()); throw new ContentGeneratingException(e, "Could not read file containing strings for random generator."); } } diff --git a/src/main/java/com/justinefactory/writing/util/BucketCreator.java b/src/main/java/com/justinefactory/writing/util/BucketCreator.java new file mode 100644 index 0000000..a8547fb --- /dev/null +++ b/src/main/java/com/justinefactory/writing/util/BucketCreator.java @@ -0,0 +1,29 @@ +package com.justinefactory.writing.util; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.writing.exceptions.AwsContentWritingException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class BucketCreator implements StorageContainerCreator { + + private final AmazonS3 client; + private final Logger logger = LogManager.getLogger(this.getClass()); + + + public BucketCreator(AmazonS3 awsClient) { + client = awsClient; + } + + @Override + public void createNonExistingStorageContainers(AwsInfo awsInfo) throws AwsContentWritingException { + if (client.doesBucketExistV2(awsInfo.getBucketName())) return; + try { + client.createBucket(awsInfo.getBucketName()); + } catch (Throwable e) { + logger.warn("Trouble while creating new AWS Bucket {}", awsInfo.getBucketName(), e); + throw new AwsContentWritingException(e, "Trouble while creating new AWS Bucket." + awsInfo.getBucketName()); + } + } +} diff --git a/src/main/java/com/justinefactory/writing/util/CheckerIfContentAlreadyWritten.java b/src/main/java/com/justinefactory/writing/util/CheckerIfContentAlreadyWritten.java index c42adf4..03802f7 100644 --- a/src/main/java/com/justinefactory/writing/util/CheckerIfContentAlreadyWritten.java +++ b/src/main/java/com/justinefactory/writing/util/CheckerIfContentAlreadyWritten.java @@ -1,10 +1,9 @@ package com.justinefactory.writing.util; -import com.justinefactory.domain.PathData; import com.justinefactory.writing.exceptions.ContentWritingException; -public interface CheckerIfContentAlreadyWritten { +public interface CheckerIfContentAlreadyWritten { - public void assureNotExist(PathData fileData) throws ContentWritingException; + void assureNotExist(WritingInfo writingInfo) throws ContentWritingException; } diff --git a/src/main/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWritten.java b/src/main/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWritten.java index e4e03be..be8a519 100644 --- a/src/main/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWritten.java +++ b/src/main/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWritten.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.util; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.writing.exceptions.ContentWritingException; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -8,13 +8,13 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Files; -public class CheckerIfFileAlreadyWritten implements CheckerIfContentAlreadyWritten { +public class CheckerIfFileAlreadyWritten implements CheckerIfContentAlreadyWritten { private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - public void assureNotExist(PathData fileData) throws ContentWritingException { - if (Files.exists(fileData.getFilePath())) { - logger.info("Could not create file {}. File {} already exists.", fileData.getFileId(), fileData.getFilePath()); + public void assureNotExist(PathInfo fileData) throws ContentWritingException { + if (Files.exists(fileData.getPath())) { + logger.info("Could not create file {}. File {} already exists.", fileData.getId(), fileData.getURI()); throw new ContentWritingException("Could not create file. File already exists."); } } diff --git a/src/main/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWritten.java b/src/main/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWritten.java new file mode 100644 index 0000000..b688494 --- /dev/null +++ b/src/main/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWritten.java @@ -0,0 +1,25 @@ +package com.justinefactory.writing.util; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.writing.exceptions.AwsContentWritingException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class CheckerIfServerContentAlreadyWritten implements CheckerIfContentAlreadyWritten { + + private final AmazonS3 client; + private final Logger logger = LogManager.getLogger(this.getClass()); + + public CheckerIfServerContentAlreadyWritten(AmazonS3 awsClient) { + client = awsClient; + } + + @Override + public void assureNotExist(AwsInfo awsInfo) throws AwsContentWritingException { + if (client.doesObjectExist(awsInfo.getBucketName(), awsInfo.getKeyName())) { + logger.warn("Could not create a file {}. File already exists.", awsInfo.getURI()); + throw new AwsContentWritingException("Could not create file " + awsInfo.getURI() + ". File already exists."); + } + } +} diff --git a/src/main/java/com/justinefactory/writing/util/DirectoriesCreator.java b/src/main/java/com/justinefactory/writing/util/DirectoriesCreator.java index ddf4e79..608414b 100644 --- a/src/main/java/com/justinefactory/writing/util/DirectoriesCreator.java +++ b/src/main/java/com/justinefactory/writing/util/DirectoriesCreator.java @@ -1,17 +1,18 @@ package com.justinefactory.writing.util; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.writing.exceptions.ContentWritingException; import java.nio.file.Files; -public class DirectoriesCreator { +public class DirectoriesCreator implements StorageContainerCreator { - public void createNonExistingDirectories(PathData fileData) throws ContentWritingException { + @Override + public void createNonExistingStorageContainers(PathInfo fileData) throws ContentWritingException { try { - Files.createDirectories(fileData.getFilePath().getParent()); - } catch (Throwable e){ - throw new ContentWritingException(e, "Trouble while creating parent directories of file {}." + fileData.getFilePath()); + Files.createDirectories(fileData.getPath().getParent()); + } catch (Throwable e) { + throw new ContentWritingException(e, "Trouble while creating parent directories of file {}." + fileData.getPath()); } } diff --git a/src/main/java/com/justinefactory/writing/util/StorageContainerCreator.java b/src/main/java/com/justinefactory/writing/util/StorageContainerCreator.java new file mode 100644 index 0000000..493699b --- /dev/null +++ b/src/main/java/com/justinefactory/writing/util/StorageContainerCreator.java @@ -0,0 +1,9 @@ +package com.justinefactory.writing.util; + +import com.justinefactory.writing.exceptions.ContentWritingException; + +public interface StorageContainerCreator { + + void createNonExistingStorageContainers(WritingInfo writingInfo) throws ContentWritingException; + +} diff --git a/src/main/java/com/justinefactory/writing/writers/ContentWriter.java b/src/main/java/com/justinefactory/writing/writers/ContentWriter.java index 2df0317..68d738d 100644 --- a/src/main/java/com/justinefactory/writing/writers/ContentWriter.java +++ b/src/main/java/com/justinefactory/writing/writers/ContentWriter.java @@ -1,12 +1,10 @@ package com.justinefactory.writing.writers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.WritingInfo; import com.justinefactory.writing.exceptions.ContentWritingException; -import java.io.IOException; +public interface ContentWriter { -public interface ContentWriter { - - void writeContent(Content content, PathData pathData) throws ContentWritingException; + void writeContent(Content content, WritingInfo info) throws ContentWritingException; } diff --git a/src/main/java/com/justinefactory/writing/writers/ContentWritingService.java b/src/main/java/com/justinefactory/writing/writers/ContentWritingService.java index be5e92f..4821611 100644 --- a/src/main/java/com/justinefactory/writing/writers/ContentWritingService.java +++ b/src/main/java/com/justinefactory/writing/writers/ContentWritingService.java @@ -1,11 +1,10 @@ package com.justinefactory.writing.writers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.WritingInfo; import com.justinefactory.writing.converters.ContentConverter; import com.justinefactory.writing.exceptions.ContentWritingException; import com.justinefactory.writing.util.CheckerIfContentAlreadyWritten; -import com.justinefactory.writing.util.CheckerIfFileAlreadyWritten; -import com.justinefactory.writing.util.DirectoriesCreator; +import com.justinefactory.writing.util.StorageContainerCreator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -13,35 +12,35 @@ public class ContentWritingService { - private final PathData pathData; - private final CheckerIfContentAlreadyWritten checkerIfContentWritten; - private final DirectoriesCreator directoriesCreator; + private final WritingInfo writingInfo; + private final CheckerIfContentAlreadyWritten checkerIfContentWritten; + private final StorageContainerCreator storageContainerCreator; private final ContentConverter converter; - private final ContentWriter writer; + private final ContentWriter writer; private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - ContentWritingService(PathData fd, CheckerIfFileAlreadyWritten ciaw, DirectoriesCreator dc, ContentConverter cr, ContentWriter wt) { - pathData = fd; - checkerIfContentWritten = ciaw; - directoriesCreator = dc; + ContentWritingService(WritingInfo fd, CheckerIfContentAlreadyWritten cicaw, StorageContainerCreator scc, ContentConverter cr, ContentWriter wt) { + writingInfo = fd; + checkerIfContentWritten = cicaw; + storageContainerCreator = scc; converter = cr; writer = wt; } public void writeContent(Content content) throws ContentWritingException { - logger.info("Writing content to path {} - initialization.", pathData.getFilePath()); + logger.info("Writing content to path {} - initialization.", writingInfo.getURI()); if (content == null) { - throw new ContentWritingException("Problem while Writing content to path " + pathData.getFilePath() + " content " + content + " is empty or does not exist."); + throw new ContentWritingException("Problem while Writing content to path " + writingInfo.getURI() + " content " + content + " is empty or does not exist."); } - checkerIfContentWritten.assureNotExist(pathData); - directoriesCreator.createNonExistingDirectories(pathData); - logger.debug("Writing content to path {} - all dirs to path have been created.", pathData.getFilePath()); + checkerIfContentWritten.assureNotExist(writingInfo); + storageContainerCreator.createNonExistingStorageContainers(writingInfo); + logger.debug("Writing content to path {} - all dirs to path have been created.", writingInfo.getURI()); ReadyToWriteContent readyToWriteContent = converter.convertContent(content); - logger.debug("Writing content to path {} - content has been converted to lines.", pathData.getFilePath()); - writer.writeContent(readyToWriteContent, pathData); - logger.debug("Writing content to path {} - lines have been written and appended into path.", pathData.getFilePath()); - logger.info("Writing content to path {} - success.", pathData.getFilePath()); + logger.debug("Writing content to path {} - content has been converted to lines.", writingInfo.getURI()); + writer.writeContent(readyToWriteContent, writingInfo); + logger.debug("Writing content to path {} - lines have been written and appended into path.", writingInfo.getURI()); + logger.info("Writing content to path {} - success.", writingInfo.getURI()); } diff --git a/src/main/java/com/justinefactory/writing/writers/file/writers/CsvFileWriter.java b/src/main/java/com/justinefactory/writing/writers/file/writers/CsvFileWriter.java index 696831f..f58e186 100644 --- a/src/main/java/com/justinefactory/writing/writers/file/writers/CsvFileWriter.java +++ b/src/main/java/com/justinefactory/writing/writers/file/writers/CsvFileWriter.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.writers.file.writers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.exceptions.ContentWritingException; import com.justinefactory.writing.writers.ContentWriter; @@ -13,14 +13,14 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Files; -public class CsvFileWriter implements ContentWriter> { +public class CsvFileWriter implements ContentWriter, PathInfo> { private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); @Override - public void writeContent(ContentStorage content, PathData fileData) throws ContentWritingException { - try (BufferedWriter writer = Files.newBufferedWriter(fileData.getFilePath()); + public void writeContent(ContentStorage content, PathInfo fileData) throws ContentWritingException { + try (BufferedWriter writer = Files.newBufferedWriter(fileData.getPath()); CSVWriter csvWriter = new CSVWriter(writer) ) { for (String[] item : content.getAllContent()) { diff --git a/src/main/java/com/justinefactory/writing/writers/file/writers/PlainFileWriter.java b/src/main/java/com/justinefactory/writing/writers/file/writers/PlainFileWriter.java index f56a4f9..1f7c5b7 100644 --- a/src/main/java/com/justinefactory/writing/writers/file/writers/PlainFileWriter.java +++ b/src/main/java/com/justinefactory/writing/writers/file/writers/PlainFileWriter.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.writers.file.writers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.exceptions.ContentWritingException; import com.justinefactory.writing.writers.ContentWriter; @@ -12,13 +12,13 @@ import java.lang.invoke.MethodHandles; import java.nio.file.Files; -public class PlainFileWriter implements ContentWriter> { +public class PlainFileWriter implements ContentWriter, PathInfo> { private final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); @Override - public void writeContent(ContentStorage content, PathData fileData) throws ContentWritingException { - try (BufferedWriter writer = Files.newBufferedWriter(fileData.getFilePath())) { + public void writeContent(ContentStorage content, PathInfo fileData) throws ContentWritingException { + try (BufferedWriter writer = Files.newBufferedWriter(fileData.getPath())) { for (String item : content.getAllContent()) { writer.write(item); writer.newLine(); diff --git a/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java b/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java new file mode 100644 index 0000000..b0b0b49 --- /dev/null +++ b/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java @@ -0,0 +1,29 @@ +package com.justinefactory.writing.writers.server.writers; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.writing.domain.ContentStorage; +import com.justinefactory.writing.exceptions.AwsContentWritingException; +import com.justinefactory.writing.writers.ContentWriter; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +public class JsonAwsWriter implements ContentWriter, AwsInfo> { + + private final AmazonS3 client; + private final Logger logger = LogManager.getLogger(this.getClass()); + + public JsonAwsWriter(AmazonS3 awsClient) { + client = awsClient; + } + + @Override + public void writeContent(ContentStorage json, AwsInfo awsInfo) throws AwsContentWritingException { + try { + client.putObject(awsInfo.getBucketName(), awsInfo.getKeyName(), json.getAllContent().toString()); + } catch (Throwable e) { + logger.warn("Trouble while writing content {} to AWS server", json.getAllContent().toString(), e); + throw new AwsContentWritingException(e, "Trouble while writing content " + json.getAllContent().toString() + "to AWS server"); + } + } +} diff --git a/src/test/java/com/justinefactory/reading/readers/ContentReadingServiceTest.java b/src/test/java/com/justinefactory/reading/readers/ContentReadingServiceTest.java index fced84a..ca5350f 100644 --- a/src/test/java/com/justinefactory/reading/readers/ContentReadingServiceTest.java +++ b/src/test/java/com/justinefactory/reading/readers/ContentReadingServiceTest.java @@ -1,6 +1,6 @@ package com.justinefactory.reading.readers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.domain.ThreeElemContent; import com.justinefactory.reading.parsers.IntegerPlainContentParser; import com.justinefactory.reading.parsers.ThreeElementCsvParser; @@ -27,7 +27,7 @@ void processContentWhenProcessingCSVFile() throws Exception { //when - PathData fileData = new PathData(filePath); + PathInfo fileData = new PathInfo(filePath); CsvContentReader contentReader = new CsvContentReader(fileData); ThreeElementCsvParser csvParser = new ThreeElementCsvParser(); ContentReadingService contentReadingService = new ContentReadingService(contentReader, csvParser); @@ -41,7 +41,7 @@ void processContentWhenProcessingCSVFile() throws Exception { @Test void processContentWhenProcessingPlainFile() throws Exception { //given - PathData fileData = new PathData(getPathToResource("txt-file-content-integers.txt")); + PathInfo fileData = new PathInfo(getPathToResource("txt-file-content-integers.txt")); ContentStorage expectedContent = new ContentStorage<>(); expectedContent.addContent(40000000); expectedContent.addContent(800000); diff --git a/src/test/java/com/justinefactory/reading/readers/CsvContentReaderTest.java b/src/test/java/com/justinefactory/reading/readers/CsvContentReaderTest.java index 4598e97..367d25e 100644 --- a/src/test/java/com/justinefactory/reading/readers/CsvContentReaderTest.java +++ b/src/test/java/com/justinefactory/reading/readers/CsvContentReaderTest.java @@ -1,6 +1,6 @@ package com.justinefactory.reading.readers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.reading.exceptions.SourceFileIsEmptyException; import com.justinefactory.writing.domain.ContentStorage; import org.junit.jupiter.api.Assertions; @@ -18,7 +18,7 @@ void readContentWhenFileMeetsConditions() throws Exception { //given Path filePath = getPathToResource("example-csv-file-for-tests.csv"); //when - PathData fileData = new PathData(filePath); + PathInfo fileData = new PathInfo(filePath); CsvContentReader contentReader = new CsvContentReader(fileData); ContentStorage content = contentReader.readContent(); //then @@ -31,7 +31,7 @@ void readContentWhenFileIsEmpty() throws Exception { //given Path filePath = getPathToResource("empty-string-content.csv"); //when - PathData fileData = new PathData(filePath); + PathInfo fileData = new PathInfo(filePath); CsvContentReader contentReader = new CsvContentReader(fileData); //then Assertions.assertThrows(SourceFileIsEmptyException.class, contentReader::readContent); diff --git a/src/test/java/com/justinefactory/reading/readers/PlainContentReaderTest.java b/src/test/java/com/justinefactory/reading/readers/PlainContentReaderTest.java index eef63e6..8788b7d 100644 --- a/src/test/java/com/justinefactory/reading/readers/PlainContentReaderTest.java +++ b/src/test/java/com/justinefactory/reading/readers/PlainContentReaderTest.java @@ -1,6 +1,6 @@ package com.justinefactory.reading.readers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.reading.exceptions.SourceFileIsEmptyException; import com.justinefactory.writing.domain.ContentStorage; import org.junit.jupiter.api.Assertions; @@ -17,7 +17,7 @@ class PlainContentReaderTest { @Test void readContentWhenFileContentMeetsConditions() throws Exception { //given - PathData fileData = new PathData(getPathToResource("txt-file-content-integers.txt")); + PathInfo fileData = new PathInfo(getPathToResource("txt-file-content-integers.txt")); ContentStorage expectedContent = new ContentStorage<>(Arrays.asList("40000000", "800000", "3245", "2143567")); //when @@ -33,7 +33,7 @@ void readContentWhenFileContentMeetsConditions() throws Exception { void readContentWhenFileIsEmpty() throws Exception { //given Path filePath = getPathToResource("empty-string-content.csv"); - PathData fileData = new PathData(filePath); + PathInfo fileData = new PathInfo(filePath); //when PlainContentReader contentReader = new PlainContentReader(fileData); diff --git a/src/test/java/com/justinefactory/testutil/AwsClientCreatorBeforeEach.java b/src/test/java/com/justinefactory/testutil/AwsClientCreatorBeforeEach.java new file mode 100644 index 0000000..e9aa9c7 --- /dev/null +++ b/src/test/java/com/justinefactory/testutil/AwsClientCreatorBeforeEach.java @@ -0,0 +1,17 @@ +package com.justinefactory.testutil; + +import com.amazonaws.regions.Regions; +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.sending.exceptions.AwsSecurityCredentialsException; +import com.justinefactory.server.communication.access.AwsSecurityCredentials; +import com.justinefactory.server.communication.clients.AwsS3Client; + +public class AwsClientCreatorBeforeEach { + + public static AmazonS3 createAwsClient() throws AwsSecurityCredentialsException { + AwsSecurityCredentials credentials = new AwsSecurityCredentials(); + AwsS3Client client = new AwsS3Client(); + return client.buildClient(Regions.EU_CENTRAL_1, credentials); + } + +} diff --git a/src/test/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFileTest.java b/src/test/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFileTest.java index 4320ce8..df24902 100644 --- a/src/test/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFileTest.java +++ b/src/test/java/com/justinefactory/writing/generators/RandomStringGeneratorFromFileTest.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.generators; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.domain.TwoElemContent; import com.justinefactory.writing.exceptions.FileWithStringsToGenerateContentIsEmptyException; @@ -24,7 +24,7 @@ void generateStringContentWhenStringFileEmpty() throws Exception { Path filePathRandomStrings = getPathToResource("empty-string-content.csv"); //when - PathData fileDataRanStr = new PathData(filePathRandomStrings); + PathInfo fileDataRanStr = new PathInfo(filePathRandomStrings); //then Assertions.assertThrows(FileWithStringsToGenerateContentIsEmptyException.class, () -> new RandomStringGeneratorFromFile(newRandom, fileDataRanStr)); @@ -35,7 +35,7 @@ void generateStringContentWhen1String() throws Exception { //given Random newRandom = new Random(); Path filePathRandomStrings = getPathToResource("string-content-only-1string.csv"); - PathData fileDataRanStr = new PathData(filePathRandomStrings); + PathInfo fileDataRanStr = new PathInfo(filePathRandomStrings); RandomStringGeneratorFromFile newGenerator = new RandomStringGeneratorFromFile(newRandom, fileDataRanStr); //when @@ -55,7 +55,7 @@ void generateTimeStampContent() throws Exception { //given Random newRandom = new Random(); Path filePathRandomStrings = getPathToResource("string-content-for-tests.csv"); - PathData fileDataRanStr = new PathData(filePathRandomStrings); + PathInfo fileDataRanStr = new PathInfo(filePathRandomStrings); RandomStringGeneratorFromFile newGenerator = new RandomStringGeneratorFromFile(newRandom, fileDataRanStr); //when diff --git a/src/test/java/com/justinefactory/writing/generators/ThreeElementContentGeneratorTest.java b/src/test/java/com/justinefactory/writing/generators/ThreeElementContentGeneratorTest.java index 3be49d6..d85bb26 100644 --- a/src/test/java/com/justinefactory/writing/generators/ThreeElementContentGeneratorTest.java +++ b/src/test/java/com/justinefactory/writing/generators/ThreeElementContentGeneratorTest.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.generators; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.domain.ThreeElemContent; import com.justinefactory.writing.domain.ContentStorage; import org.junit.jupiter.api.Test; @@ -17,7 +17,7 @@ class ThreeElementContentGeneratorTest { void generateContentWhenRandom() throws Exception { //given Path filePathRanStrings = getPathToResource("string-content-for-tests.csv"); - PathData fileDataRanStr = new PathData(filePathRanStrings); + PathInfo fileDataRanStr = new PathInfo(filePathRanStrings); Random newRandom = new Random(); RandomIntegerGenerator newIntGenerator = new RandomIntegerGenerator(newRandom); RandomStringGeneratorFromFile new2ElemGenerator = new RandomStringGeneratorFromFile(newRandom, fileDataRanStr); diff --git a/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java b/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java new file mode 100644 index 0000000..13e65e7 --- /dev/null +++ b/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java @@ -0,0 +1,58 @@ +package com.justinefactory.writing.util; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.sending.exceptions.AwsSecurityCredentialsException; +import com.justinefactory.writing.exceptions.AwsContentWritingException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; +import static org.junit.jupiter.api.Assertions.assertTrue; + +class BucketCreatorTest { + + private static AmazonS3 awsClient; + private static String additionalBucket = "com.justyna.lisok.factory.content-bucket-test"; + + @BeforeEach + public void createAwsClientAccessKeyAndAwsInfo() throws AwsSecurityCredentialsException { + awsClient = createAwsClient(); + } + + + @AfterAll + public static void removeAdditionalBucket() { + awsClient.deleteBucket(additionalBucket); + } + + + @Test + void createNonExistingStorageContainersWhenBucketExists() throws AwsContentWritingException { + //given + AwsInfo info = new AwsInfo("com.justyna.lisok.factory.content-bucket", "content.json"); + + //when + BucketCreator creator = new BucketCreator(awsClient); + + //then + creator.createNonExistingStorageContainers(info); + } + + + @Test + void createNonExistingStorageContainersWhenBucketDoesNotExist() throws AwsContentWritingException { + //given + AwsInfo info = new AwsInfo(additionalBucket, "content.json"); + + //when + BucketCreator creator = new BucketCreator(awsClient); + creator.createNonExistingStorageContainers(info); + + //then + assertTrue(awsClient.doesBucketExistV2(info.getBucketName())); + } + + +} \ No newline at end of file diff --git a/src/test/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWrittenTest.java b/src/test/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWrittenTest.java index 6ed60ee..959a424 100644 --- a/src/test/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWrittenTest.java +++ b/src/test/java/com/justinefactory/writing/util/CheckerIfFileAlreadyWrittenTest.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.util; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.testutil.CreateAndDeleteFilesBeforeAfterAll; import com.justinefactory.writing.exceptions.ContentWritingException; import org.junit.jupiter.api.AfterAll; @@ -31,7 +31,7 @@ static void removeDirsAfterAll() throws Exception { void checkIfFileWrittenWhenFileDoesExist() throws Exception { //given Path file = Files.createTempFile(dir, "doc", ".csv"); - PathData filePath = new PathData(file); + PathInfo filePath = new PathInfo(file); //when CheckerIfFileAlreadyWritten checker = new CheckerIfFileAlreadyWritten(); diff --git a/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java b/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java new file mode 100644 index 0000000..c16f8e1 --- /dev/null +++ b/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java @@ -0,0 +1,58 @@ +package com.justinefactory.writing.util; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.sending.exceptions.AwsSecurityCredentialsException; +import com.justinefactory.writing.exceptions.AwsContentWritingException; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class CheckerIfServerContentAlreadyWrittenTest { + + private static AmazonS3 awsClient; + + @BeforeEach + public void createAwsClientAccessKeyAndAwsInfo() throws AwsSecurityCredentialsException { + awsClient = createAwsClient(); + } + + @Test + public void assureNotExistWhenFileDoesNotExistButBucketExists() throws AwsContentWritingException { + //given + AwsInfo info = new AwsInfo("com.justyna.lisok.factory.content-bucket", "content.json"); + + //when + CheckerIfServerContentAlreadyWritten checker = new CheckerIfServerContentAlreadyWritten(awsClient); + + //then + checker.assureNotExist(info); + } + + @Test + public void assureNotExistWhenFileAndBucketDoesNotExist() throws AwsContentWritingException { + //given + AwsInfo info = new AwsInfo("com.justyna.lisok.factory.content", "content.json"); + + //when + CheckerIfServerContentAlreadyWritten checker = new CheckerIfServerContentAlreadyWritten(awsClient); + + //then + checker.assureNotExist(info); + } + + @Test + public void assureNotExistWhenFileAndBucketExists() { + //given + AwsInfo info = new AwsInfo("com.justyna.lisok.factory.content-bucket", "test.txt"); + + //when + CheckerIfServerContentAlreadyWritten checker = new CheckerIfServerContentAlreadyWritten(awsClient); + + //then + assertThrows(AwsContentWritingException.class, () -> checker.assureNotExist(info)); + } + +} \ No newline at end of file diff --git a/src/test/java/com/justinefactory/writing/writers/CsvFileWriterTest.java b/src/test/java/com/justinefactory/writing/writers/CsvFileWriterTest.java index 83f059f..173e561 100644 --- a/src/test/java/com/justinefactory/writing/writers/CsvFileWriterTest.java +++ b/src/test/java/com/justinefactory/writing/writers/CsvFileWriterTest.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.writers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.testutil.CreateAndDeleteFilesBeforeAfterAll; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.writers.file.writers.CsvFileWriter; @@ -32,7 +32,7 @@ static void removeDirsAfterAll() throws Exception { void write2FileWhenFileDoesNotExist() throws Exception { //given Path filePath = dir.resolve("doc.csv"); - PathData file2writeData = new PathData(filePath); + PathInfo file2writeData = new PathInfo(filePath); ContentStorage readyToWriteContent = new ContentStorage<>(new String[]{"1590147349818750700", "1345882450", "Owl"}); CsvFileWriter newFileWriter = new CsvFileWriter(); diff --git a/src/test/java/com/justinefactory/writing/writers/PlainFileWriterTest.java b/src/test/java/com/justinefactory/writing/writers/PlainFileWriterTest.java index 5ee01af..6d65ede 100644 --- a/src/test/java/com/justinefactory/writing/writers/PlainFileWriterTest.java +++ b/src/test/java/com/justinefactory/writing/writers/PlainFileWriterTest.java @@ -1,6 +1,6 @@ package com.justinefactory.writing.writers; -import com.justinefactory.domain.PathData; +import com.justinefactory.domain.PathInfo; import com.justinefactory.testutil.CreateAndDeleteFilesBeforeAfterAll; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.writers.file.writers.PlainFileWriter; @@ -32,7 +32,7 @@ static void removeDirsAfterAll() throws Exception { void write2FileWhenWritingRandomInteger() throws Exception { //given Path filePath = dir.resolve("doc.csv"); - PathData file2writeData = new PathData(filePath); + PathInfo file2writeData = new PathInfo(filePath); ContentStorage readyToWriteContent = new ContentStorage<>(List.of("1","2")); //when @@ -49,7 +49,7 @@ void write2FileWhenWritingRandomInteger() throws Exception { void write2FileWhenWritingJSON() throws Exception { //given Path filePath = dir.resolve("doc.json"); - PathData file2writeData = new PathData(filePath); + PathInfo file2writeData = new PathInfo(filePath); ContentStorage readyToWriteContent = new ContentStorage<>(); readyToWriteContent.addContent("\"{\\n\" +\n" + " \" \\\"content\\\": {\\n\" +\n" + diff --git a/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java b/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java new file mode 100644 index 0000000..05474a2 --- /dev/null +++ b/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java @@ -0,0 +1,67 @@ +package com.justinefactory.writing.writers.server.writers; + +import com.amazonaws.services.s3.AmazonS3; +import com.amazonaws.services.s3.model.DeleteObjectRequest; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.sending.exceptions.AwsSecurityCredentialsException; +import com.justinefactory.writing.domain.ContentStorage; +import com.justinefactory.writing.exceptions.AwsContentWritingException; +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; +import static org.junit.jupiter.api.Assertions.*; + +class JsonAwsWriterTest { + + private static AmazonS3 awsClient; + private static String jsonName = "content.json"; + private static String bucketName = "com.justyna.lisok.factory.content-bucket"; + + @BeforeEach + public void createClient() throws AwsSecurityCredentialsException { + awsClient = createAwsClient(); + } + + @AfterAll + public static void removeObjectFromAws() { + awsClient.deleteObject(new DeleteObjectRequest(bucketName, jsonName)); + } + + @Test + void writeContentWhenContentDoesNotExist() throws AwsContentWritingException { + //given + AwsInfo info = new AwsInfo(bucketName, jsonName); + + ContentStorage readyToWriteContent = new ContentStorage<>(); + readyToWriteContent.addContent("\"{\\n\" +\n" + + " \" \\\"content\\\": {\\n\" +\n" + + " \" \\\"content\\\": [\\n\" +\n" + + " \" {\\n\" +\n" + + " \" \\\"timeStamp\\\": 1590147349818750700,\\n\" +\n" + + " \" \\\"randomInt\\\": -840762737,\\n\" +\n" + + " \" \\\"randomString\\\": \\\"ChristopherRobin\\\"\\n\" +\n" + + " \" }\\n\" +\n" + + " \" ]\\n\" +\n" + + " \" },\\n\" +\n" + + " \" \\\"stats\\\": {\\n\" +\n" + + " \" \\\"count\\\": 1,\\n\" +\n" + + " \" \\\"distinctCount\\\": 1,\\n\" +\n" + + " \" \\\"max\\\": {\\n\" +\n" + + " \" \\\"timeStamp\\\": 1590147349818750700,\\n\" +\n" + + " \" \\\"randomInt\\\": -840762737,\\n\" +\n" + + " \" \\\"randomString\\\": \\\"ChristopherRobin\\\"\\n\" +\n" + + " \" }\\n\" +\n" + + " \" }\\n\" +\n" + + " \"}\";"); + JsonAwsWriter writer = new JsonAwsWriter(awsClient); + + //when + writer.writeContent(readyToWriteContent, info); + + //then + assertTrue(awsClient.doesObjectExist(info.getBucketName(),info.getKeyName())); + assertTrue(awsClient.getObjectMetadata(info.getBucketName(),info.getKeyName()).getContentLength() > 0); + } +} \ No newline at end of file diff --git a/src/test/resources/AwsRootKey.csv b/src/test/resources/AwsRootKey.csv new file mode 100644 index 0000000..8f4343f --- /dev/null +++ b/src/test/resources/AwsRootKey.csv @@ -0,0 +1,2 @@ +AKIAIUXLVTYXTE7XWITA +w1/oJ8Ysz3qkC8lagYkxFmUaG6rAQN6oR3E53a91 From dba402773e17c594fcc1a26799840c2ad49496cb Mon Sep 17 00:00:00 2001 From: Justyna Date: Fri, 19 Jun 2020 18:18:10 +0200 Subject: [PATCH 2/4] json chores and new functionality: generating url --- .../com/justinefactory/domain/AwsInfo.java | 14 ++--- .../communication/clients/AwsS3Client.java | 2 +- .../distribution/PresignedUrlRequest.java | 16 +++++ .../ServerObjectDownloadByUrlCreator.java | 44 +++++++++++++ .../ServerObjectsManagementService.java | 34 ++++++++++ ...urrentTimStampWithPrecisionConversion.java | 2 + .../justinefactory/util/TimeCalculator.java | 20 ++++++ .../writers/server/writers/JsonAwsWriter.java | 7 ++- .../ServerObjectDownloadByUrlCreatorTest.java | 43 +++++++++++++ .../util/TimeCalculatorTest.java | 63 +++++++++++++++++++ .../writing/util/BucketCreatorTest.java | 13 +++- ...ckerIfServerContentAlreadyWrittenTest.java | 8 ++- .../server/writers/JsonAwsWriterTest.java | 47 +++++++------- 13 files changed, 274 insertions(+), 39 deletions(-) create mode 100644 src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java create mode 100644 src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java create mode 100644 src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java create mode 100644 src/main/java/com/justinefactory/util/TimeCalculator.java create mode 100644 src/test/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreatorTest.java create mode 100644 src/test/java/com/justinefactory/util/TimeCalculatorTest.java diff --git a/src/main/java/com/justinefactory/domain/AwsInfo.java b/src/main/java/com/justinefactory/domain/AwsInfo.java index 1b274f8..99ce44a 100644 --- a/src/main/java/com/justinefactory/domain/AwsInfo.java +++ b/src/main/java/com/justinefactory/domain/AwsInfo.java @@ -7,14 +7,14 @@ public class AwsInfo implements WritingInfo { private final URI uri; private final UUID id; - private final String BUCKET_NAME; - private final String KEY_NAME; + private final String bucketName; + private final String keyName; public AwsInfo(String bucketName, String keyName) { - BUCKET_NAME = bucketName; - KEY_NAME = keyName; - uri = URI.create(BUCKET_NAME + "/" + KEY_NAME); + this.bucketName = bucketName; + this.keyName = keyName; + uri = URI.create("s3://" + this.bucketName + "/" + this.keyName); id = UUID.randomUUID(); } @@ -30,11 +30,11 @@ public UUID getId() { } public String getBucketName() { - return BUCKET_NAME; + return bucketName; } public String getKeyName() { - return KEY_NAME; + return keyName; } } diff --git a/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java b/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java index 64c2e0d..2d78a9c 100644 --- a/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java +++ b/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java @@ -18,7 +18,7 @@ public AmazonS3 buildClient(Regions region, AwsSecurityCredentials awsSecurityCr .withRegion(region) .build(); } catch (Throwable e) { - throw new AmazonClientException("Trouble while building an AWSS3 client. Incorrect credentials or region.", e); + throw new AmazonClientException("Trouble while building an AWSS3 client.", e); } } } diff --git a/src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java b/src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java new file mode 100644 index 0000000..03596a9 --- /dev/null +++ b/src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java @@ -0,0 +1,16 @@ +package com.justinefactory.server.communication.distribution; + +import com.amazonaws.HttpMethod; +import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; +import com.justinefactory.domain.AwsInfo; + +import java.util.Date; + +public class PresignedUrlRequest { + + public GeneratePresignedUrlRequest generateRequest(AwsInfo info, Date expiration) { + return new GeneratePresignedUrlRequest(info.getBucketName(), info.getKeyName()) + .withMethod(HttpMethod.GET) + .withExpiration(expiration); + } +} diff --git a/src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java b/src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java new file mode 100644 index 0000000..3714885 --- /dev/null +++ b/src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java @@ -0,0 +1,44 @@ +package com.justinefactory.server.communication.distribution; + +import com.amazonaws.AmazonServiceException; +import com.amazonaws.SdkClientException; +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.util.TimeCalculator; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.net.URL; +import java.time.Duration; +import java.time.Instant; +import java.util.Date; + +public class ServerObjectDownloadByUrlCreator { + + private final TimeCalculator timeCalculator; + private final PresignedUrlRequest urlRequest; + private final Logger logger = LogManager.getLogger(this.getClass()); + + public ServerObjectDownloadByUrlCreator(TimeCalculator timeCalculator, PresignedUrlRequest urlRequest) { + this.timeCalculator = timeCalculator; + this.urlRequest = urlRequest; + + } + + + public URL createAccessWithPresignedUrl(AmazonS3 client, AwsInfo info, Duration duration) { + try { + Date expiration = timeCalculator.calculateExpirationTime(Instant.now(), duration); + URL url = client.generatePresignedUrl(urlRequest.generateRequest(info, expiration)); + logger.debug("Creating URL {} to the object {} - success", url, info.getURI()); + return url; + } catch (AmazonServiceException e) { + logger.warn("Trouble while creating URL to the object {} due to an error in the request.", info.getURI(), e); + throw new AmazonServiceException("Trouble while creating URL to the object " + info.getURI() + " due to an error in the request.", e); + } catch (SdkClientException e) { + logger.warn("Trouble while creating URL to the object {} due to an error in service connection.", info.getURI(), e); + throw new SdkClientException("Trouble while creating URL to the object " + info.getURI() + " due to an error in service connection.", e); + } + } +} + diff --git a/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java b/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java new file mode 100644 index 0000000..1572d66 --- /dev/null +++ b/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java @@ -0,0 +1,34 @@ +package com.justinefactory.server.communication.distribution.service; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.reading.exceptions.ContentReadingException; +import com.justinefactory.sending.service.ContentSendingService; +import com.justinefactory.server.communication.distribution.ServerObjectDownloadByUrlCreator; +import com.justinefactory.stats.exceptions.StatsCalculatingException; +import com.justinefactory.writing.domain.ContentStorage; +import com.justinefactory.writing.exceptions.ContentWritingException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.lang.invoke.MethodHandles; +import java.time.Duration; + +public class ServerObjectsManagementService { + + ContentSendingService> sendingService; + ServerObjectDownloadByUrlCreator urlCreator; + private static final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); + + public ServerObjectsManagementService(ContentSendingService> sendingService, ServerObjectDownloadByUrlCreator urlCreator) { + logger.debug("Creating, sending and management of server objects - initialization"); + this.sendingService = sendingService; + this.urlCreator = urlCreator; + } + + public void manageContent(AmazonS3 client, AwsInfo info, Duration duration) throws ContentWritingException, StatsCalculatingException, ContentReadingException { + sendingService.sendContent(); + urlCreator.createAccessWithPresignedUrl(client, info, duration); + logger.debug("Creating, sending and management of server objects - success"); + } +} diff --git a/src/main/java/com/justinefactory/util/CurrentTimStampWithPrecisionConversion.java b/src/main/java/com/justinefactory/util/CurrentTimStampWithPrecisionConversion.java index 7fa4215..405673e 100644 --- a/src/main/java/com/justinefactory/util/CurrentTimStampWithPrecisionConversion.java +++ b/src/main/java/com/justinefactory/util/CurrentTimStampWithPrecisionConversion.java @@ -10,8 +10,10 @@ public static Long getCurrentTimeInNanoSeconds(){ return recalculateInstantToNanoSeconds(now); } + private static Long recalculateInstantToNanoSeconds(Instant tstmp) { return TimeUnit.SECONDS.toNanos(tstmp.getEpochSecond()) + tstmp.getNano(); } + } diff --git a/src/main/java/com/justinefactory/util/TimeCalculator.java b/src/main/java/com/justinefactory/util/TimeCalculator.java new file mode 100644 index 0000000..e40963c --- /dev/null +++ b/src/main/java/com/justinefactory/util/TimeCalculator.java @@ -0,0 +1,20 @@ +package com.justinefactory.util; + +import java.time.Duration; +import java.time.Instant; +import java.util.Date; + +public class TimeCalculator { + + public Date calculateExpirationTime(Instant now, Duration duration) { + if (duration.isNegative()) { + throw new IllegalArgumentException("Delta time cannot be negative."); + } + Long nowInMillis = now.toEpochMilli(); + Date expiration = new Date(); + Long deltaTimeInMillis = duration.toMillis(); + expiration.setTime(nowInMillis + deltaTimeInMillis); + return expiration; + } + +} diff --git a/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java b/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java index b0b0b49..e0ae649 100644 --- a/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java +++ b/src/main/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriter.java @@ -19,11 +19,12 @@ public JsonAwsWriter(AmazonS3 awsClient) { @Override public void writeContent(ContentStorage json, AwsInfo awsInfo) throws AwsContentWritingException { + String jsonToSend = String.join(System.lineSeparator(), json.getAllContent()); try { - client.putObject(awsInfo.getBucketName(), awsInfo.getKeyName(), json.getAllContent().toString()); + client.putObject(awsInfo.getBucketName(), awsInfo.getKeyName(), jsonToSend); } catch (Throwable e) { - logger.warn("Trouble while writing content {} to AWS server", json.getAllContent().toString(), e); - throw new AwsContentWritingException(e, "Trouble while writing content " + json.getAllContent().toString() + "to AWS server"); + logger.warn("Trouble while writing content {} to AWS server", jsonToSend, e); + throw new AwsContentWritingException(e, "Trouble while writing content " + jsonToSend + "to AWS server"); } } } diff --git a/src/test/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreatorTest.java b/src/test/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreatorTest.java new file mode 100644 index 0000000..ead9a65 --- /dev/null +++ b/src/test/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreatorTest.java @@ -0,0 +1,43 @@ +package com.justinefactory.server.communication.distribution; + +import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.domain.AwsInfo; +import com.justinefactory.sending.exceptions.AwsSecurityCredentialsException; +import com.justinefactory.util.TimeCalculator; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import java.net.URL; +import java.time.Duration; + +import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; +import static org.junit.jupiter.api.Assertions.assertFalse; + +class ServerObjectDownloadByUrlCreatorTest { + + private static AmazonS3 awsClient; + private static AwsInfo info; + private static TimeCalculator timeCalculator; + private static PresignedUrlRequest urlRequest; + + @BeforeEach + public void createAwsClientAccessKeyAndAwsInfo() throws AwsSecurityCredentialsException { + awsClient = createAwsClient(); + timeCalculator = new TimeCalculator(); + urlRequest = new PresignedUrlRequest(); + info = new AwsInfo("com.justyna.lisok.factory.content-bucket", "test.txt"); + } + + @Test + void createAccessWithPresignedUrl() { + //given + ServerObjectDownloadByUrlCreator urlCreator = new ServerObjectDownloadByUrlCreator(timeCalculator, urlRequest); + + //when + Duration duration = Duration.ofMinutes(30); + URL url = urlCreator.createAccessWithPresignedUrl(awsClient, info, duration); + + //then + assertFalse(url.toString().isEmpty()); + } +} \ No newline at end of file diff --git a/src/test/java/com/justinefactory/util/TimeCalculatorTest.java b/src/test/java/com/justinefactory/util/TimeCalculatorTest.java new file mode 100644 index 0000000..b32d276 --- /dev/null +++ b/src/test/java/com/justinefactory/util/TimeCalculatorTest.java @@ -0,0 +1,63 @@ +package com.justinefactory.util; + +import org.junit.jupiter.api.Test; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.Arguments; +import org.junit.jupiter.params.provider.MethodSource; + +import java.time.Duration; +import java.time.Instant; +import java.util.Date; +import java.util.stream.Stream; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertThrows; + +class TimeCalculatorTest { + + @Test + void calculateExpirationTimeWhenDurationBelowZero() { + //given + TimeCalculator calculator = new TimeCalculator(); + Instant now = Instant.now(); + + //when + Duration duration = Duration.ofMinutes(-20); + + //then + assertThrows(IllegalArgumentException.class, () -> calculator.calculateExpirationTime(now, duration)); + } + + + @ParameterizedTest + @MethodSource("testData") + void calculateExpirationTimeWhenDurationMeetsConditions(Instant now, Duration duration, Date expected) { + //given + TimeCalculator calculator = new TimeCalculator(); + + //when + Date actual = calculator.calculateExpirationTime(now, duration); + + //then + assertEquals(expected, actual); + + } + + static Stream testData() { + Instant now = Instant.now(); + return Stream.of( + Arguments.arguments(now, Duration.ofMinutes(0), calculateExpected(now, 0)), + Arguments.arguments(now, Duration.ofMinutes(10), calculateExpected(now, 10)), + Arguments.arguments(now, Duration.ofMinutes(60), calculateExpected(now, 60)), + Arguments.arguments(now, Duration.ofHours(24), calculateExpected(now, 60 * 24)) + ); + } + + private static Date calculateExpected(Instant now, Integer time) { + Date expected = new Date(); + expected.setTime(now.toEpochMilli() + Duration.ofMinutes(time).toMillis()); + return expected; + } + + +} \ No newline at end of file diff --git a/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java b/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java index 13e65e7..c344dfc 100644 --- a/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java +++ b/src/test/java/com/justinefactory/writing/util/BucketCreatorTest.java @@ -8,17 +8,22 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.Random; + import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; class BucketCreatorTest { private static AmazonS3 awsClient; - private static String additionalBucket = "com.justyna.lisok.factory.content-bucket-test"; + private static String additionalBucket; @BeforeEach public void createAwsClientAccessKeyAndAwsInfo() throws AwsSecurityCredentialsException { awsClient = createAwsClient(); + Random random = new Random(); + additionalBucket = "com.justyna.lisok.factory.content-bucket-test-" + random.nextInt(); } @@ -32,12 +37,14 @@ public static void removeAdditionalBucket() { void createNonExistingStorageContainersWhenBucketExists() throws AwsContentWritingException { //given AwsInfo info = new AwsInfo("com.justyna.lisok.factory.content-bucket", "content.json"); + assertTrue(awsClient.doesBucketExistV2(info.getBucketName())); //when BucketCreator creator = new BucketCreator(awsClient); + creator.createNonExistingStorageContainers(info); //then - creator.createNonExistingStorageContainers(info); + assertTrue(awsClient.doesBucketExistV2(info.getBucketName())); } @@ -45,6 +52,8 @@ void createNonExistingStorageContainersWhenBucketExists() throws AwsContentWriti void createNonExistingStorageContainersWhenBucketDoesNotExist() throws AwsContentWritingException { //given AwsInfo info = new AwsInfo(additionalBucket, "content.json"); + assertFalse(awsClient.doesBucketExistV2(info.getBucketName())); + //when BucketCreator creator = new BucketCreator(awsClient); diff --git a/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java b/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java index c16f8e1..b7490a5 100644 --- a/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java +++ b/src/test/java/com/justinefactory/writing/util/CheckerIfServerContentAlreadyWrittenTest.java @@ -8,6 +8,7 @@ import org.junit.jupiter.api.Test; import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; +import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertThrows; class CheckerIfServerContentAlreadyWrittenTest { @@ -26,9 +27,10 @@ public void assureNotExistWhenFileDoesNotExistButBucketExists() throws AwsConten //when CheckerIfServerContentAlreadyWritten checker = new CheckerIfServerContentAlreadyWritten(awsClient); + checker.assureNotExist(info); //then - checker.assureNotExist(info); + assertFalse(awsClient.doesObjectExist(info.getBucketName(), info.getKeyName())); } @Test @@ -38,9 +40,11 @@ public void assureNotExistWhenFileAndBucketDoesNotExist() throws AwsContentWriti //when CheckerIfServerContentAlreadyWritten checker = new CheckerIfServerContentAlreadyWritten(awsClient); + checker.assureNotExist(info); //then - checker.assureNotExist(info); + assertFalse(awsClient.doesObjectExist(info.getBucketName(), info.getKeyName())); + } @Test diff --git a/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java b/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java index 05474a2..0b16b13 100644 --- a/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java +++ b/src/test/java/com/justinefactory/writing/writers/server/writers/JsonAwsWriterTest.java @@ -11,7 +11,7 @@ import org.junit.jupiter.api.Test; import static com.justinefactory.testutil.AwsClientCreatorBeforeEach.createAwsClient; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertTrue; class JsonAwsWriterTest { @@ -33,35 +33,34 @@ public static void removeObjectFromAws() { void writeContentWhenContentDoesNotExist() throws AwsContentWritingException { //given AwsInfo info = new AwsInfo(bucketName, jsonName); - ContentStorage readyToWriteContent = new ContentStorage<>(); - readyToWriteContent.addContent("\"{\\n\" +\n" + - " \" \\\"content\\\": {\\n\" +\n" + - " \" \\\"content\\\": [\\n\" +\n" + - " \" {\\n\" +\n" + - " \" \\\"timeStamp\\\": 1590147349818750700,\\n\" +\n" + - " \" \\\"randomInt\\\": -840762737,\\n\" +\n" + - " \" \\\"randomString\\\": \\\"ChristopherRobin\\\"\\n\" +\n" + - " \" }\\n\" +\n" + - " \" ]\\n\" +\n" + - " \" },\\n\" +\n" + - " \" \\\"stats\\\": {\\n\" +\n" + - " \" \\\"count\\\": 1,\\n\" +\n" + - " \" \\\"distinctCount\\\": 1,\\n\" +\n" + - " \" \\\"max\\\": {\\n\" +\n" + - " \" \\\"timeStamp\\\": 1590147349818750700,\\n\" +\n" + - " \" \\\"randomInt\\\": -840762737,\\n\" +\n" + - " \" \\\"randomString\\\": \\\"ChristopherRobin\\\"\\n\" +\n" + - " \" }\\n\" +\n" + - " \" }\\n\" +\n" + - " \"}\";"); + readyToWriteContent.addContent("{\n" + + " \"content\": {\n" + + " \"content\": [\n" + + " {\n" + + " \"timeStamp\": 1590147349818750700,\n" + + " \"randomInt\": -840762737,\n" + + " \"randomString\": \"ChristopherRobin\"\n" + + " }\n" + + " ]\n" + + " },\n" + + " \"stats\": {\n" + + " \"count\": 1,\n" + + " \"distinctCount\": 1,\n" + + " \"max\": {\n" + + " \"timeStamp\": 1590147349818750700,\n" + + " \"randomInt\": -840762737,\n" + + " \"randomString\": \"ChristopherRobin\"\n" + + " }\n" + + " }\n" + + "}"); JsonAwsWriter writer = new JsonAwsWriter(awsClient); //when writer.writeContent(readyToWriteContent, info); //then - assertTrue(awsClient.doesObjectExist(info.getBucketName(),info.getKeyName())); - assertTrue(awsClient.getObjectMetadata(info.getBucketName(),info.getKeyName()).getContentLength() > 0); + assertTrue(awsClient.doesObjectExist(info.getBucketName(), info.getKeyName())); + assertTrue(awsClient.getObjectMetadata(info.getBucketName(), info.getKeyName()).getContentLength() > 0); } } \ No newline at end of file From e2b7b4b9cadd7fc75889dfd97a03b1b32950ad07 Mon Sep 17 00:00:00 2001 From: Justyna Date: Fri, 19 Jun 2020 18:29:40 +0200 Subject: [PATCH 3/4] small chores on management service - ops ;) --- .../distribution/service/ServerObjectsManagementService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java b/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java index 1572d66..e7a0ef4 100644 --- a/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java +++ b/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java @@ -12,6 +12,7 @@ import org.apache.logging.log4j.Logger; import java.lang.invoke.MethodHandles; +import java.net.URL; import java.time.Duration; public class ServerObjectsManagementService { @@ -28,7 +29,7 @@ public ServerObjectsManagementService(ContentSendingService Date: Thu, 25 Jun 2020 18:06:07 +0200 Subject: [PATCH 4/4] changes in timecalculator output and small chores concerning this issue --- .../access/AwsSecurityCredentials.java | 2 +- .../communication/clients/AwsClient.java | 4 ++-- .../communication/clients/AwsS3Client.java | 4 ++-- .../distribution/PresignedUrlRequest.java | 8 +++++--- .../ServerObjectDownloadByUrlCreator.java | 5 ++--- .../service/CloudObjectsManagementService.java} | 15 +++++++-------- .../com/justinefactory/util/TimeCalculator.java | 10 ++-------- .../ServerObjectDownloadByUrlCreatorTest.java | 2 +- .../testutil/AwsClientCreatorBeforeEach.java | 4 ++-- .../justinefactory/util/TimeCalculatorTest.java | 12 +++++------- 10 files changed, 29 insertions(+), 37 deletions(-) rename src/main/java/com/justinefactory/{server => cloud}/communication/access/AwsSecurityCredentials.java (95%) rename src/main/java/com/justinefactory/{server => cloud}/communication/clients/AwsClient.java (61%) rename src/main/java/com/justinefactory/{server => cloud}/communication/clients/AwsS3Client.java (85%) rename src/main/java/com/justinefactory/{server => cloud}/communication/distribution/PresignedUrlRequest.java (65%) rename src/main/java/com/justinefactory/{server => cloud}/communication/distribution/ServerObjectDownloadByUrlCreator.java (90%) rename src/main/java/com/justinefactory/{server/communication/distribution/service/ServerObjectsManagementService.java => cloud/communication/distribution/service/CloudObjectsManagementService.java} (64%) rename src/test/java/com/justinefactory/{server => cloud}/communication/distribution/ServerObjectDownloadByUrlCreatorTest.java (95%) diff --git a/src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java b/src/main/java/com/justinefactory/cloud/communication/access/AwsSecurityCredentials.java similarity index 95% rename from src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java rename to src/main/java/com/justinefactory/cloud/communication/access/AwsSecurityCredentials.java index cb7c607..af729ec 100644 --- a/src/main/java/com/justinefactory/server/communication/access/AwsSecurityCredentials.java +++ b/src/main/java/com/justinefactory/cloud/communication/access/AwsSecurityCredentials.java @@ -1,4 +1,4 @@ -package com.justinefactory.server.communication.access; +package com.justinefactory.cloud.communication.access; import com.amazonaws.auth.AWSCredentials; import com.amazonaws.auth.BasicAWSCredentials; diff --git a/src/main/java/com/justinefactory/server/communication/clients/AwsClient.java b/src/main/java/com/justinefactory/cloud/communication/clients/AwsClient.java similarity index 61% rename from src/main/java/com/justinefactory/server/communication/clients/AwsClient.java rename to src/main/java/com/justinefactory/cloud/communication/clients/AwsClient.java index b06c453..3afbf9a 100644 --- a/src/main/java/com/justinefactory/server/communication/clients/AwsClient.java +++ b/src/main/java/com/justinefactory/cloud/communication/clients/AwsClient.java @@ -1,8 +1,8 @@ -package com.justinefactory.server.communication.clients; +package com.justinefactory.cloud.communication.clients; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.internal.S3DirectSpi; -import com.justinefactory.server.communication.access.AwsSecurityCredentials; +import com.justinefactory.cloud.communication.access.AwsSecurityCredentials; public interface AwsClient { diff --git a/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java b/src/main/java/com/justinefactory/cloud/communication/clients/AwsS3Client.java similarity index 85% rename from src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java rename to src/main/java/com/justinefactory/cloud/communication/clients/AwsS3Client.java index 2d78a9c..9975ce0 100644 --- a/src/main/java/com/justinefactory/server/communication/clients/AwsS3Client.java +++ b/src/main/java/com/justinefactory/cloud/communication/clients/AwsS3Client.java @@ -1,11 +1,11 @@ -package com.justinefactory.server.communication.clients; +package com.justinefactory.cloud.communication.clients; import com.amazonaws.AmazonClientException; import com.amazonaws.auth.AWSStaticCredentialsProvider; import com.amazonaws.regions.Regions; import com.amazonaws.services.s3.AmazonS3; import com.amazonaws.services.s3.AmazonS3ClientBuilder; -import com.justinefactory.server.communication.access.AwsSecurityCredentials; +import com.justinefactory.cloud.communication.access.AwsSecurityCredentials; public class AwsS3Client implements AwsClient { diff --git a/src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java b/src/main/java/com/justinefactory/cloud/communication/distribution/PresignedUrlRequest.java similarity index 65% rename from src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java rename to src/main/java/com/justinefactory/cloud/communication/distribution/PresignedUrlRequest.java index 03596a9..fcbffd1 100644 --- a/src/main/java/com/justinefactory/server/communication/distribution/PresignedUrlRequest.java +++ b/src/main/java/com/justinefactory/cloud/communication/distribution/PresignedUrlRequest.java @@ -1,16 +1,18 @@ -package com.justinefactory.server.communication.distribution; +package com.justinefactory.cloud.communication.distribution; import com.amazonaws.HttpMethod; import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest; import com.justinefactory.domain.AwsInfo; import java.util.Date; +import java.time.Instant; public class PresignedUrlRequest { - public GeneratePresignedUrlRequest generateRequest(AwsInfo info, Date expiration) { + public GeneratePresignedUrlRequest generateRequest(AwsInfo info, Instant expiration) { + Date expirationDate = Date.from(expiration); return new GeneratePresignedUrlRequest(info.getBucketName(), info.getKeyName()) .withMethod(HttpMethod.GET) - .withExpiration(expiration); + .withExpiration(expirationDate); } } diff --git a/src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java b/src/main/java/com/justinefactory/cloud/communication/distribution/ServerObjectDownloadByUrlCreator.java similarity index 90% rename from src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java rename to src/main/java/com/justinefactory/cloud/communication/distribution/ServerObjectDownloadByUrlCreator.java index 3714885..9a2c5b3 100644 --- a/src/main/java/com/justinefactory/server/communication/distribution/ServerObjectDownloadByUrlCreator.java +++ b/src/main/java/com/justinefactory/cloud/communication/distribution/ServerObjectDownloadByUrlCreator.java @@ -1,4 +1,4 @@ -package com.justinefactory.server.communication.distribution; +package com.justinefactory.cloud.communication.distribution; import com.amazonaws.AmazonServiceException; import com.amazonaws.SdkClientException; @@ -11,7 +11,6 @@ import java.net.URL; import java.time.Duration; import java.time.Instant; -import java.util.Date; public class ServerObjectDownloadByUrlCreator { @@ -28,7 +27,7 @@ public ServerObjectDownloadByUrlCreator(TimeCalculator timeCalculator, Presigned public URL createAccessWithPresignedUrl(AmazonS3 client, AwsInfo info, Duration duration) { try { - Date expiration = timeCalculator.calculateExpirationTime(Instant.now(), duration); + Instant expiration = timeCalculator.calculateExpirationTime(Instant.now(), duration); URL url = client.generatePresignedUrl(urlRequest.generateRequest(info, expiration)); logger.debug("Creating URL {} to the object {} - success", url, info.getURI()); return url; diff --git a/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java b/src/main/java/com/justinefactory/cloud/communication/distribution/service/CloudObjectsManagementService.java similarity index 64% rename from src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java rename to src/main/java/com/justinefactory/cloud/communication/distribution/service/CloudObjectsManagementService.java index e7a0ef4..4863989 100644 --- a/src/main/java/com/justinefactory/server/communication/distribution/service/ServerObjectsManagementService.java +++ b/src/main/java/com/justinefactory/cloud/communication/distribution/service/CloudObjectsManagementService.java @@ -1,10 +1,10 @@ -package com.justinefactory.server.communication.distribution.service; +package com.justinefactory.cloud.communication.distribution.service; import com.amazonaws.services.s3.AmazonS3; +import com.justinefactory.cloud.communication.distribution.ServerObjectDownloadByUrlCreator; import com.justinefactory.domain.AwsInfo; import com.justinefactory.reading.exceptions.ContentReadingException; import com.justinefactory.sending.service.ContentSendingService; -import com.justinefactory.server.communication.distribution.ServerObjectDownloadByUrlCreator; import com.justinefactory.stats.exceptions.StatsCalculatingException; import com.justinefactory.writing.domain.ContentStorage; import com.justinefactory.writing.exceptions.ContentWritingException; @@ -12,16 +12,15 @@ import org.apache.logging.log4j.Logger; import java.lang.invoke.MethodHandles; -import java.net.URL; import java.time.Duration; -public class ServerObjectsManagementService { +public class CloudObjectsManagementService { - ContentSendingService> sendingService; - ServerObjectDownloadByUrlCreator urlCreator; + private final ContentSendingService> sendingService; + private final ServerObjectDownloadByUrlCreator urlCreator; private static final Logger logger = LogManager.getLogger(MethodHandles.lookup().lookupClass()); - public ServerObjectsManagementService(ContentSendingService> sendingService, ServerObjectDownloadByUrlCreator urlCreator) { + public CloudObjectsManagementService(ContentSendingService> sendingService, ServerObjectDownloadByUrlCreator urlCreator) { logger.debug("Creating, sending and management of server objects - initialization"); this.sendingService = sendingService; this.urlCreator = urlCreator; @@ -29,7 +28,7 @@ public ServerObjectsManagementService(ContentSendingService testData() { ); } - private static Date calculateExpected(Instant now, Integer time) { - Date expected = new Date(); - expected.setTime(now.toEpochMilli() + Duration.ofMinutes(time).toMillis()); - return expected; + private static Instant calculateExpected(Instant now, Integer time) { + Duration durationMinutes = Duration.ofMinutes(time); + return now.plus(durationMinutes); }