Initial commit
This commit is contained in:
parent
1df3e2ad81
commit
6447b1d90b
19 changed files with 565 additions and 54 deletions
|
|
@ -1,19 +0,0 @@
|
|||
package ch.illgner;
|
||||
|
||||
public class OrderCalculator {
|
||||
|
||||
/**
|
||||
* Berechnet den Endpreis nach Rabatt und inklusive 19% MwSt.
|
||||
*
|
||||
* @param basePrice Der Nettopreis
|
||||
* @param discountRate Der Rabatt (z.B. 0.1 für 10%)
|
||||
* @return Der Endpreis gerundet auf 2 Nachkommastellen
|
||||
*/
|
||||
public double calculateFinalPrice(double basePrice, double discountRate) {
|
||||
double discountedPrice = basePrice * discountRate;
|
||||
|
||||
double priceWithTax = discountedPrice * 1.19;
|
||||
|
||||
return priceWithTax;
|
||||
}
|
||||
}
|
||||
138
src/main/java/illgner/ch/createzip/PostBoxZipFileWriter.java
Executable file
138
src/main/java/illgner/ch/createzip/PostBoxZipFileWriter.java
Executable file
|
|
@ -0,0 +1,138 @@
|
|||
package illgner.ch.createzip;
|
||||
|
||||
import illgner.ch.encryption.IOutputStreamEnhancer;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.output.CountingOutputStream;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.Closeable;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import static java.nio.file.attribute.PosixFilePermission.GROUP_READ;
|
||||
import static java.nio.file.attribute.PosixFilePermission.OTHERS_READ;
|
||||
import static java.nio.file.attribute.PosixFilePermission.OWNER_READ;
|
||||
import static java.nio.file.attribute.PosixFilePermission.OWNER_WRITE;
|
||||
|
||||
public class PostBoxZipFileWriter implements Closeable {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PostBoxZipFileWriter.class);
|
||||
|
||||
private static final Set<PosixFilePermission> ZIP_FILE_PERMISSIONS = EnumSet.of(OWNER_READ, OWNER_WRITE, GROUP_READ, OTHERS_READ);
|
||||
|
||||
private final Path destinationDir;
|
||||
private final String baseName;
|
||||
private final int chunkSize;
|
||||
private final int bufferSize;
|
||||
private final ZipResult zipResult;
|
||||
IOutputStreamEnhancer outputStreamEnhancer;
|
||||
|
||||
private ZipOutputStream zipOutputStream;
|
||||
|
||||
private int fileCount = 1;
|
||||
private long bytesWritten = 0;
|
||||
private File actualZipFile;
|
||||
private CountingOutputStream countingOutputStream;
|
||||
|
||||
public PostBoxZipFileWriter(Path destinationDir, String baseName, int chunkSize, int bufferSize, IOutputStreamEnhancer outputStreamEnhancer) {
|
||||
this.destinationDir = destinationDir;
|
||||
this.baseName = baseName;
|
||||
this.chunkSize = chunkSize;
|
||||
this.bufferSize = bufferSize;
|
||||
this.zipResult = new ZipResult();
|
||||
this.outputStreamEnhancer = outputStreamEnhancer;
|
||||
}
|
||||
|
||||
private ZipOutputStream createNewZipOutputStream() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException,
|
||||
NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
|
||||
String actualZipFilename = createOutputFilename();
|
||||
actualZipFile = destinationDir.resolve(actualZipFilename).toFile();
|
||||
|
||||
LOG.info("Creating zip part {}: {}", fileCount, actualZipFilename);
|
||||
|
||||
countingOutputStream = new CountingOutputStream(outputStreamEnhancer.enhance(new BufferedOutputStream(new FileOutputStream(actualZipFile), bufferSize)));
|
||||
return new ZipOutputStream(countingOutputStream);
|
||||
}
|
||||
|
||||
private String createOutputFilename() {
|
||||
return String.format("%s_%02d.zip", baseName, fileCount);
|
||||
}
|
||||
|
||||
public void write(InputStream inputStream, String path) throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException,
|
||||
NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
|
||||
if (countingOutputStream == null) {
|
||||
zipOutputStream = createNewZipOutputStream();
|
||||
}
|
||||
if (bytesWritten >= chunkSize) {
|
||||
switchOutputFile();
|
||||
}
|
||||
LOG.info("Writing file {} to zip", path);
|
||||
zipOutputStream.putNextEntry(new ZipEntry(path));
|
||||
bytesWritten += IOUtils.copyLarge(inputStream, zipOutputStream);
|
||||
zipOutputStream.closeEntry();
|
||||
}
|
||||
|
||||
private void switchOutputFile() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
LOG.info("Switching zip");
|
||||
zipOutputStream.flush();
|
||||
zipOutputStream.close();
|
||||
addZipToResult();
|
||||
fileCount++;
|
||||
zipOutputStream = createNewZipOutputStream();
|
||||
bytesWritten = 0;
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
LOG.info("Closing zip {}", actualZipFile.getName());
|
||||
zipOutputStream.flush();
|
||||
zipOutputStream.close();
|
||||
addZipToResult();
|
||||
}
|
||||
|
||||
public void writeReadMe() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException,
|
||||
NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
|
||||
if (zipOutputStream != null) {
|
||||
LOG.info("Skip adding Readme");
|
||||
return;
|
||||
}
|
||||
|
||||
try (InputStream readmeStream = this.getClass().getClassLoader().getResourceAsStream("Readme.txt")) {
|
||||
if (readmeStream == null) {
|
||||
throw new IOException("Cannot open Readme");
|
||||
}
|
||||
|
||||
LOG.info("Writing Readme");
|
||||
write(readmeStream, "Readme.txt");
|
||||
} catch (IOException e) {
|
||||
throw new IOException("Could not write Readme", e);
|
||||
}
|
||||
}
|
||||
|
||||
public ZipResult getZipResult() {
|
||||
return this.zipResult;
|
||||
}
|
||||
|
||||
private void addZipToResult() throws IOException {
|
||||
zipResult.add(actualZipFile.getName(), countingOutputStream.getCount());
|
||||
Files.setPosixFilePermissions(actualZipFile.toPath(), ZIP_FILE_PERMISSIONS);
|
||||
}
|
||||
}
|
||||
23
src/main/java/illgner/ch/createzip/ZipResult.java
Executable file
23
src/main/java/illgner/ch/createzip/ZipResult.java
Executable file
|
|
@ -0,0 +1,23 @@
|
|||
package illgner.ch.createzip;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class ZipResult {
|
||||
|
||||
private final List<String> zipFilenames = new ArrayList<>();
|
||||
private final List<Long> zipFileLengths = new ArrayList<>();
|
||||
|
||||
void add(String fileName, long bytesWritten) {
|
||||
zipFilenames.add(fileName);
|
||||
zipFileLengths.add(bytesWritten);
|
||||
}
|
||||
|
||||
public List<Long> getFileLengths() {
|
||||
return zipFileLengths;
|
||||
}
|
||||
|
||||
public List<String> getFilenames() {
|
||||
return zipFilenames;
|
||||
}
|
||||
}
|
||||
15
src/main/java/illgner/ch/encryption/IInputStreamEnhancer.java
Executable file
15
src/main/java/illgner/ch/encryption/IInputStreamEnhancer.java
Executable file
|
|
@ -0,0 +1,15 @@
|
|||
package illgner.ch.encryption;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
public interface IInputStreamEnhancer {
|
||||
|
||||
InputStream enhance(InputStream inputStream) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidAlgorithmParameterException, NoSuchProviderException;
|
||||
|
||||
}
|
||||
18
src/main/java/illgner/ch/encryption/IOutputStreamEnhancer.java
Executable file
18
src/main/java/illgner/ch/encryption/IOutputStreamEnhancer.java
Executable file
|
|
@ -0,0 +1,18 @@
|
|||
package illgner.ch.encryption;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
|
||||
public interface IOutputStreamEnhancer {
|
||||
/**
|
||||
* This method enhances the given input stream {@link OutputStream} wrapping with the additional functionality (in our case with encryption)
|
||||
* @param outputStream the original stream {@link OutputStream} to be enhanced.
|
||||
* @return A new {@link OutputStream} that wraps the functionality to input stream.
|
||||
*/
|
||||
OutputStream enhance(OutputStream outputStream) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException, InvalidAlgorithmParameterException, NoSuchProviderException;
|
||||
}
|
||||
|
|
@ -1,32 +0,0 @@
|
|||
package ch.illgner;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class OrderCalculatorTest {
|
||||
|
||||
@Test
|
||||
public void testCalculateFinalPrice_NormalScenario() {
|
||||
OrderCalculator calculator = new OrderCalculator();
|
||||
|
||||
// Szenario: 100€ Basis, 10% Rabatt = 90€.
|
||||
// 90€ + 19% MwSt (17.10€) = 107.10€
|
||||
double result = calculator.calculateFinalPrice(100.0, 0.10);
|
||||
|
||||
assertEquals(107.10, result, "Der Endpreis für 100€ mit 10% Rabatt muss 107.10 sein.");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCalculateFinalPrice_Rounding() {
|
||||
OrderCalculator calculator = new OrderCalculator();
|
||||
|
||||
// Szenario: 10.55€ Basis, 5% Rabatt = 10.0225€
|
||||
// 10.0225€ + 19% MwSt = 11.926775€ -> Gerundet: 11.93€
|
||||
double result = calculator.calculateFinalPrice(10.55, 0.05);
|
||||
|
||||
assertEquals(11.93, result, "Der Preis muss korrekt auf 2 Stellen gerundet werden.");
|
||||
}
|
||||
}
|
||||
306
src/test/java/illgner/ch/jobs/postboxbulk/service/PostBoxZipFileWriterTest.java
Executable file
306
src/test/java/illgner/ch/jobs/postboxbulk/service/PostBoxZipFileWriterTest.java
Executable file
|
|
@ -0,0 +1,306 @@
|
|||
package illgner.ch.jobs.postboxbulk.service;
|
||||
|
||||
import illgner.ch.createzip.PostBoxZipFileWriter;
|
||||
import illgner.ch.createzip.ZipResult;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.BeforeAll;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import javax.crypto.NoSuchPaddingException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.security.InvalidAlgorithmParameterException;
|
||||
import java.security.InvalidKeyException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.NoSuchProviderException;
|
||||
import java.util.Objects;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipInputStream;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.hamcrest.collection.IsCollectionWithSize.hasSize;
|
||||
import static org.hamcrest.io.FileMatchers.aFileNamed;
|
||||
import static org.hamcrest.io.FileMatchers.anExistingFile;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class PostBoxZipFileWriterTest {
|
||||
|
||||
private static final Path DESTINATION_DIR = Paths.get("./destination");
|
||||
private static final int ONE_BYTE = 1024;
|
||||
private static final int HALF_BYTE = ONE_BYTE / 2;
|
||||
private static final int ZIP_BUFFER_SIZE_IN_BYTE = 2 * ONE_BYTE;
|
||||
private static final int ZIP_CHUNK_SIZE_IN_BYTE = 3 * ONE_BYTE;
|
||||
|
||||
@BeforeAll
|
||||
static void setUp() throws IOException {
|
||||
FileUtils.deleteDirectory(DESTINATION_DIR.toFile());
|
||||
boolean directoryCreated = DESTINATION_DIR.toFile().mkdir();
|
||||
assertTrue(directoryCreated);
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
static void cleanUp() throws IOException {
|
||||
FileUtils.deleteDirectory(DESTINATION_DIR.toFile());
|
||||
boolean directoryCreated = DESTINATION_DIR.toFile().mkdir();
|
||||
assertTrue(directoryCreated);
|
||||
}
|
||||
|
||||
@Test
|
||||
void singleFileSmallerThanChunkSizeToOneZip() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
byte[] fileSimpleContent = RandomStringUtils.randomAlphanumeric(2 * ONE_BYTE).getBytes(StandardCharsets.UTF_8);
|
||||
ZipResult zipResult;
|
||||
String outputFileName = RandomStringUtils.randomAlphanumeric(10);
|
||||
String inputFileName = "singleFileSmallerThanChunkSizeToOneZip.txt";
|
||||
PostBoxZipFileWriter postBoxZipFileWriter = new PostBoxZipFileWriter(
|
||||
DESTINATION_DIR, outputFileName, ZIP_CHUNK_SIZE_IN_BYTE, ZIP_BUFFER_SIZE_IN_BYTE, (OutputStream outputStream) -> outputStream);
|
||||
try (postBoxZipFileWriter) {
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(fileSimpleContent), inputFileName);
|
||||
}
|
||||
String expectedZippedFileName = outputFileName + "_01.zip";
|
||||
zipResult = postBoxZipFileWriter.getZipResult();
|
||||
File createdZipFile = DESTINATION_DIR.resolve(expectedZippedFileName).toFile();
|
||||
|
||||
assertThat(zipResult.getFilenames(), hasSize(1));
|
||||
assertThat(zipResult.getFileLengths(), hasSize(1));
|
||||
assertThat(zipResult.getFilenames().get(0), is(equalTo(expectedZippedFileName)));
|
||||
assertThat(zipResult.getFileLengths().get(0), is(equalTo(createdZipFile.length())));
|
||||
assertThat(createdZipFile, is(anExistingFile()));
|
||||
assertThat(createdZipFile, is(aFileNamed(equalTo(expectedZippedFileName))));
|
||||
|
||||
// check zip content
|
||||
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(createdZipFile))) {
|
||||
assertThat(Objects.requireNonNull(zipInputStream.getNextEntry()).getName(), is(equalTo(inputFileName)));
|
||||
assertThat(IOUtils.toByteArray(zipInputStream), is(equalTo(fileSimpleContent)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void singleFileGreaterThanChunkSizeToOneZip() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
byte[] fileSimpleContent = RandomStringUtils.randomAlphanumeric(4 * ONE_BYTE).getBytes(StandardCharsets.UTF_8);
|
||||
ZipResult zipResult;
|
||||
String outputFileName = RandomStringUtils.randomAlphanumeric(10);
|
||||
String inputFileName = "singleFileGreaterThanChunkSizeToOneZip.txt";
|
||||
PostBoxZipFileWriter postBoxZipFileWriter = new PostBoxZipFileWriter(
|
||||
DESTINATION_DIR, outputFileName, ZIP_CHUNK_SIZE_IN_BYTE, ZIP_BUFFER_SIZE_IN_BYTE, (OutputStream outputStream) -> outputStream);
|
||||
try (postBoxZipFileWriter) {
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(fileSimpleContent), inputFileName);
|
||||
}
|
||||
String expectedZippedFileNamePartOne = outputFileName + "_01.zip";
|
||||
zipResult = postBoxZipFileWriter.getZipResult();
|
||||
assertThat(zipResult.getFilenames(), hasSize(1));
|
||||
assertThat(zipResult.getFileLengths(), hasSize(1));
|
||||
assertTrue(zipResult.getFilenames().contains(expectedZippedFileNamePartOne));
|
||||
|
||||
File createdZipOne = DESTINATION_DIR.resolve(expectedZippedFileNamePartOne).toFile();
|
||||
|
||||
assertThat(createdZipOne, is(anExistingFile()));
|
||||
assertThat(createdZipOne, is(aFileNamed(equalTo(expectedZippedFileNamePartOne))));
|
||||
|
||||
// check zip content
|
||||
extractSplitZipFiles(new File[]{createdZipOne});
|
||||
File extractedFile = new File(DESTINATION_DIR + "/" + inputFileName);
|
||||
byte[] extractedFileBytes = IOUtils.toByteArray(new FileInputStream(extractedFile));
|
||||
assertThat(extractedFileBytes, is(equalTo(fileSimpleContent)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleFileSmallerThanChunkSizeToSingleZip() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
byte[] firstFile = RandomStringUtils.randomAlphanumeric(ONE_BYTE).getBytes(StandardCharsets.UTF_8);
|
||||
byte[] secondFile = "uts öäü ÖÄÜ ß".getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
String outputFileName = RandomStringUtils.randomAlphanumeric(10);
|
||||
String inputFileNameOne = "multipleFileSmallerThanChunkSizeToSingleZip1.txt";
|
||||
String inputFileNameTwo = "multipleFileSmallerThanChunkSizeToSingleZip2.txt";
|
||||
|
||||
ZipResult zipResult;
|
||||
PostBoxZipFileWriter postBoxZipFileWriter = new PostBoxZipFileWriter(
|
||||
DESTINATION_DIR, outputFileName, ZIP_CHUNK_SIZE_IN_BYTE, ZIP_BUFFER_SIZE_IN_BYTE, (OutputStream outputStream) -> outputStream);
|
||||
try (postBoxZipFileWriter) {
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(firstFile), inputFileNameOne);
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(secondFile), inputFileNameTwo);
|
||||
}
|
||||
|
||||
zipResult = postBoxZipFileWriter.getZipResult();
|
||||
String expectedZippedFileNamePartOne = outputFileName + "_01.zip";
|
||||
File createdZip = DESTINATION_DIR.resolve(expectedZippedFileNamePartOne).toFile();
|
||||
|
||||
assertThat(zipResult.getFilenames(), hasSize(1));
|
||||
assertThat(zipResult.getFileLengths(), hasSize(1));
|
||||
assertThat(createdZip, is(anExistingFile()));
|
||||
assertThat(createdZip, is(aFileNamed(equalTo(expectedZippedFileNamePartOne))));
|
||||
assertThat(zipResult.getFilenames().get(0), is(equalTo(expectedZippedFileNamePartOne)));
|
||||
assertThat(zipResult.getFileLengths().get(0), is(equalTo(createdZip.length())));
|
||||
|
||||
// check zip content
|
||||
try (ZipInputStream zipInputStream = new ZipInputStream(new FileInputStream(createdZip))) {
|
||||
assertThat(Objects.requireNonNull(zipInputStream.getNextEntry()).getName(), is(equalTo(inputFileNameOne)));
|
||||
assertThat(IOUtils.toByteArray(zipInputStream), is(equalTo(firstFile)));
|
||||
assertThat(zipInputStream.getNextEntry().getName(), is(equalTo(inputFileNameTwo)));
|
||||
assertThat(IOUtils.toByteArray(zipInputStream), is(equalTo(secondFile)));
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleFilesTogetherGreaterThanChunkSizeToSingleZip() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
String text1 = RandomStringUtils.randomAlphanumeric(2 * ONE_BYTE + HALF_BYTE);
|
||||
String text2 = RandomStringUtils.randomAlphanumeric(2 * ONE_BYTE + HALF_BYTE);
|
||||
byte[] firstFile = text1.getBytes(StandardCharsets.UTF_8);
|
||||
byte[] secondFile = text2.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
String outputFileName = RandomStringUtils.randomAlphanumeric(10);
|
||||
String inputFileNameOne = "multipleFilesTogetherGreaterThanChunkSizeToSingleZip1.txt";
|
||||
String inputFileNameTwo = "multipleFilesTogetherGreaterThanChunkSizeToSingleZip2.txt";
|
||||
|
||||
ZipResult zipResult;
|
||||
PostBoxZipFileWriter postBoxZipFileWriter = new PostBoxZipFileWriter(
|
||||
DESTINATION_DIR, outputFileName, ZIP_CHUNK_SIZE_IN_BYTE, ZIP_BUFFER_SIZE_IN_BYTE, (OutputStream outputStream) -> outputStream);
|
||||
try (postBoxZipFileWriter) {
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(firstFile), inputFileNameOne);
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(secondFile), inputFileNameTwo);
|
||||
} finally {
|
||||
zipResult = postBoxZipFileWriter.getZipResult();
|
||||
}
|
||||
|
||||
String expectedZippedFileNamePartOne = outputFileName + "_01.zip";
|
||||
|
||||
assertThat(zipResult.getFilenames(), hasSize(1));
|
||||
assertThat(zipResult.getFileLengths(), hasSize(1));
|
||||
assertTrue(zipResult.getFilenames().contains(expectedZippedFileNamePartOne));
|
||||
|
||||
File createdZipOne = DESTINATION_DIR.resolve(expectedZippedFileNamePartOne).toFile();
|
||||
|
||||
assertThat(createdZipOne, is(anExistingFile()));
|
||||
assertThat(createdZipOne, is(aFileNamed(equalTo(expectedZippedFileNamePartOne))));
|
||||
|
||||
// check zip content
|
||||
extractSplitZipFiles(new File[]{createdZipOne});
|
||||
File extractedFile = new File(DESTINATION_DIR + "/" + inputFileNameOne);
|
||||
byte[] extractedFileBytes = IOUtils.toByteArray(new FileInputStream(extractedFile));
|
||||
assertThat(extractedFileBytes, is(equalTo(firstFile)));
|
||||
|
||||
extractedFile = new File(DESTINATION_DIR + "/" + inputFileNameTwo);
|
||||
extractedFileBytes = IOUtils.toByteArray(new FileInputStream(extractedFile));
|
||||
assertThat(extractedFileBytes, is(equalTo(secondFile)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void multipleBigFilesToMultipleZip() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
ZipResult zipResult;
|
||||
int bigChuckSize = ONE_BYTE * 50;
|
||||
int bigBufferSize = ONE_BYTE * 10;
|
||||
// First two files will be zipped together and third file will be zipped in the second file.
|
||||
byte[] firstFile = RandomStringUtils.randomAlphanumeric(40 * ONE_BYTE).getBytes(StandardCharsets.UTF_8);
|
||||
byte[] secondFile = RandomStringUtils.randomAlphanumeric(70 * ONE_BYTE).getBytes(StandardCharsets.UTF_8);
|
||||
byte[] thirdFile = RandomStringUtils.randomAlphanumeric(10 * ONE_BYTE).getBytes(StandardCharsets.UTF_8);
|
||||
String[] originalFileNames = {"multipleBigFilesToMultipleZip1.txt", "multipleBigFilesToMultipleZip2.txt", "multipleBigFilesToMultipleZip3.txt"};
|
||||
String outputFileName = RandomStringUtils.randomAlphanumeric(10);
|
||||
|
||||
PostBoxZipFileWriter postBoxZipFileWriter = new PostBoxZipFileWriter(
|
||||
DESTINATION_DIR, outputFileName, bigChuckSize, bigBufferSize, (OutputStream outputStream) -> outputStream);
|
||||
try (postBoxZipFileWriter) {
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(firstFile), originalFileNames[0]);
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(secondFile), originalFileNames[1]);
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(thirdFile), originalFileNames[2]);
|
||||
} finally {
|
||||
zipResult = postBoxZipFileWriter.getZipResult();
|
||||
}
|
||||
|
||||
String expectedZippedFileNamePartOne = outputFileName + "_01.zip";
|
||||
String expectedZippedFileNamePartTwo = outputFileName + "_02.zip";
|
||||
|
||||
assertThat(zipResult.getFilenames(), hasSize(2));
|
||||
assertThat(zipResult.getFileLengths(), hasSize(2));
|
||||
assertTrue(zipResult.getFilenames().contains(expectedZippedFileNamePartOne));
|
||||
assertTrue(zipResult.getFilenames().contains(expectedZippedFileNamePartTwo));
|
||||
|
||||
File part1 = DESTINATION_DIR.resolve(expectedZippedFileNamePartOne).toFile();
|
||||
File part2 = DESTINATION_DIR.resolve(expectedZippedFileNamePartTwo).toFile();
|
||||
|
||||
File[] zippedFiles = {part1, part2};
|
||||
|
||||
assertThat(part1, is(anExistingFile()));
|
||||
assertThat(part1, is(aFileNamed(equalTo(expectedZippedFileNamePartOne))));
|
||||
assertThat(part2, is(anExistingFile()));
|
||||
assertThat(part2, is(aFileNamed(equalTo(expectedZippedFileNamePartTwo))));
|
||||
|
||||
extractSplitZipFiles(zippedFiles);
|
||||
|
||||
// check zip content
|
||||
File extractedFile = new File(DESTINATION_DIR + "/" + originalFileNames[0]);
|
||||
byte[] extractedFileBytes = IOUtils.toByteArray(new FileInputStream(extractedFile));
|
||||
assertThat(extractedFileBytes, is(equalTo(firstFile)));
|
||||
|
||||
extractedFile = new File(DESTINATION_DIR + "/" + originalFileNames[1]);
|
||||
extractedFileBytes = IOUtils.toByteArray(new FileInputStream(extractedFile));
|
||||
assertThat(extractedFileBytes, is(equalTo(secondFile)));
|
||||
|
||||
extractedFile = new File(DESTINATION_DIR + "/" + originalFileNames[2]);
|
||||
extractedFileBytes = IOUtils.toByteArray(new FileInputStream(extractedFile));
|
||||
assertThat(extractedFileBytes, is(equalTo(thirdFile)));
|
||||
}
|
||||
|
||||
@Test
|
||||
void createBigZip() throws IOException, InvalidAlgorithmParameterException, NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
// first implementation crashed with an OutOfMemoryException while copying an 50MB Stream,
|
||||
// so we added a test for this
|
||||
|
||||
try (PostBoxZipFileWriter zipFileWriter = new PostBoxZipFileWriter(
|
||||
DESTINATION_DIR, "testBigMulti", 100 * 1000 * 1000, ZIP_BUFFER_SIZE_IN_BYTE, (OutputStream outputStream) -> outputStream)) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
byte[] content = RandomStringUtils.randomAlphanumeric(50 * 1000 * 1000).getBytes();
|
||||
zipFileWriter.write(new ByteArrayInputStream(content), "test" + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void addCompressibleFiles() throws InvalidAlgorithmParameterException, NoSuchPaddingException, IOException, NoSuchAlgorithmException, InvalidKeyException, NoSuchProviderException {
|
||||
byte[] content1 = new byte[10000];
|
||||
byte[] content2 = new byte[10000];
|
||||
byte[] content3 = new byte[10000];
|
||||
|
||||
String outputFileName = RandomStringUtils.randomAlphanumeric(10);
|
||||
|
||||
ZipResult zipResult;
|
||||
try (PostBoxZipFileWriter postBoxZipFileWriter = new PostBoxZipFileWriter(DESTINATION_DIR, outputFileName, 1000, 2048, (OutputStream outputStream) -> outputStream)) {
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(content1), "file1");
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(content2), "file2");
|
||||
postBoxZipFileWriter.write(new ByteArrayInputStream(content3), "file3");
|
||||
zipResult = postBoxZipFileWriter.getZipResult();
|
||||
}
|
||||
assertThat("compressible files only containing zeroes should be compressed into one file", zipResult.getFileLengths().size(), is(1));
|
||||
}
|
||||
|
||||
public static void extractSplitZipFiles(File[] zipFiles) throws IOException {
|
||||
byte[] buffer = new byte[ZIP_BUFFER_SIZE_IN_BYTE];
|
||||
for (File zipFilePath : zipFiles) {
|
||||
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath))) {
|
||||
ZipEntry zipEntry = zis.getNextEntry();
|
||||
|
||||
while (zipEntry != null) {
|
||||
File newFile = new File(DESTINATION_DIR + "/" + zipEntry.getName());
|
||||
new File(newFile.getParent()).mkdirs(); // Create directories for nested files
|
||||
try (FileOutputStream fos = new FileOutputStream(newFile, true)) {
|
||||
int len;
|
||||
while ((len = zis.read(buffer)) > 0) {
|
||||
fos.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
zipEntry = zis.getNextEntry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Reference in a new issue