diff --git a/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStream.java b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStream.java new file mode 100644 index 0000000000000000000000000000000000000000..c4c8ddfcf21552cc5a6b05ce6b74d9ab92b229d3 --- /dev/null +++ b/src/main/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStream.java @@ -0,0 +1,39 @@ +package de.ozgcloud.nachrichten.postfach.osiv2.storage; + +import java.io.IOException; +import java.io.InputStream; + +import lombok.RequiredArgsConstructor; + +@RequiredArgsConstructor +public class LimitedInputStream extends InputStream { + private final InputStream parentStream; + private final int limit; + private int readOffset = 0; + + @Override + public int read() throws IOException { + var buffer = new byte[1]; + var result = read(buffer, 0, 1); + return result < 0 ? result : buffer[0]; + } + + + @Override + public int read(byte[] buffer, int offset, int length) throws IOException { + var remainingLength = limit - readOffset; + if (remainingLength > 0) { + var readLength = parentStream.read(buffer, offset, Math.min(remainingLength, length)); + if (readLength > 0) { + readOffset += readLength; + return readLength; + } + } + return -1; + } + + @Override + public void close() { + // Keep parent stream open + } +} diff --git a/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStreamTest.java b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStreamTest.java new file mode 100644 index 0000000000000000000000000000000000000000..15c160042176f8ccac26c35f2cc6b2041460f462 --- /dev/null +++ b/src/test/java/de/ozgcloud/nachrichten/postfach/osiv2/storage/LimitedInputStreamTest.java @@ -0,0 +1,54 @@ +package de.ozgcloud.nachrichten.postfach.osiv2.storage; + +import static org.junit.jupiter.api.Assertions.*; + +import java.io.ByteArrayInputStream; + +import org.apache.commons.io.IOUtils; +import org.junit.jupiter.api.DisplayName; +import org.junit.jupiter.api.Test; + +import lombok.SneakyThrows; + +class LimitedInputStreamTest { + + @DisplayName("should limit input stream") + @Test + @SneakyThrows + void shouldLimitInputStream() { + var inputStream = createExampleLimitedInputStream(); + + var result = IOUtils.toByteArray(inputStream); + + assertEquals("12345", new String(result)); + } + + @DisplayName("should read one") + @Test + @SneakyThrows + void shouldReadOne() { + var inputStream = createExampleLimitedInputStream(); + + var result = inputStream.read(); + + assertEquals('1', result); + } + + @DisplayName("should keep parent stream usable") + @Test + @SneakyThrows + void shouldKeepParentStreamUsable() { + var parentStream = new ByteArrayInputStream("123456789".getBytes()); + var inputStream = new LimitedInputStream(parentStream, 5); + var inputStream2 = new LimitedInputStream(parentStream, 5); + IOUtils.toByteArray(inputStream); + + var result = IOUtils.toByteArray(inputStream2); + + assertEquals("6789", new String(result)); + } + + private LimitedInputStream createExampleLimitedInputStream() { + return new LimitedInputStream(new ByteArrayInputStream("123456789".getBytes()), 5); + } +} \ No newline at end of file