diff --git a/core-api/src/main/java/org/codice/imaging/nitf/core/common/NitfReader.java b/core-api/src/main/java/org/codice/imaging/nitf/core/common/NitfReader.java index 2ba9ce7ed..285874940 100644 --- a/core-api/src/main/java/org/codice/imaging/nitf/core/common/NitfReader.java +++ b/core-api/src/main/java/org/codice/imaging/nitf/core/common/NitfReader.java @@ -164,4 +164,12 @@ This is used to ignore some of the file content (e.g. data segments, when only p @throws NitfFormatException if something went wrong during parsing (e.g. end of file). */ void skip(final long count) throws NitfFormatException; + + /** + Closes the file. + + @throws Exception if there is an error closing the file. + */ + + void close() throws Exception; } diff --git a/core/src/main/java/org/codice/imaging/nitf/core/common/impl/FileReader.java b/core/src/main/java/org/codice/imaging/nitf/core/common/impl/FileReader.java index 89e35853b..720beff1e 100644 --- a/core/src/main/java/org/codice/imaging/nitf/core/common/impl/FileReader.java +++ b/core/src/main/java/org/codice/imaging/nitf/core/common/impl/FileReader.java @@ -31,7 +31,7 @@ /** NitfReader implementation using a (random access) File. */ -public class FileReader extends SharedReader implements NitfReader { +public class FileReader extends SharedReader implements NitfReader, AutoCloseable { // Error Messages static final String GENERIC_READ_ERROR_MESSAGE = "Error reading from NITF file: "; static final String FILE_NOT_FOUND_EXCEPTION_MESSAGE = "File Not Found Exception opening file:"; diff --git a/core/src/main/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReader.java b/core/src/main/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReader.java index f1802f1d7..8cc637e78 100644 --- a/core/src/main/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReader.java +++ b/core/src/main/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReader.java @@ -25,7 +25,7 @@ /** NitfReader implementation using an InputStream. */ -public class NitfInputStreamReader extends SharedReader implements NitfReader { +public class NitfInputStreamReader extends SharedReader implements NitfReader, AutoCloseable { private static final Logger LOG = LoggerFactory.getLogger(NitfInputStreamReader.class); @@ -125,4 +125,11 @@ public final void skip(final long count) throws NitfFormatException { throw new NitfFormatException(GENERIC_READ_ERROR_MESSAGE + ex.getMessage(), numBytesRead); } } + + @Override + public final void close() throws Exception { + if (input != null) { + input.close(); + } + } } diff --git a/core/src/main/java/org/codice/imaging/nitf/core/common/impl/SharedReader.java b/core/src/main/java/org/codice/imaging/nitf/core/common/impl/SharedReader.java index 3f9703dd1..14917cbcb 100644 --- a/core/src/main/java/org/codice/imaging/nitf/core/common/impl/SharedReader.java +++ b/core/src/main/java/org/codice/imaging/nitf/core/common/impl/SharedReader.java @@ -21,7 +21,7 @@ /** Shared NitfReader implementation. */ -abstract class SharedReader extends NitfReaderDefaultImpl implements NitfReader { +abstract class SharedReader extends NitfReaderDefaultImpl implements NitfReader, AutoCloseable { @Override public final Integer readBytesAsInteger(final int count) throws NitfFormatException { diff --git a/core/src/main/java/org/codice/imaging/nitf/core/impl/NitfReaderDefaultImpl.java b/core/src/main/java/org/codice/imaging/nitf/core/impl/NitfReaderDefaultImpl.java index 97e78cb1d..4f86a7f89 100644 --- a/core/src/main/java/org/codice/imaging/nitf/core/impl/NitfReaderDefaultImpl.java +++ b/core/src/main/java/org/codice/imaging/nitf/core/impl/NitfReaderDefaultImpl.java @@ -27,7 +27,7 @@ combination of shared methods and default implementation methods that a concrete implementation class can call. */ -public abstract class NitfReaderDefaultImpl implements NitfReader { +public abstract class NitfReaderDefaultImpl implements NitfReader, AutoCloseable { /** The type (version) of NITF file. diff --git a/core/src/test/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReaderTest.java b/core/src/test/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReaderTest.java index 1b7597fe6..1764d5cab 100644 --- a/core/src/test/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReaderTest.java +++ b/core/src/test/java/org/codice/imaging/nitf/core/common/impl/NitfInputStreamReaderTest.java @@ -53,4 +53,33 @@ public void testEndOfFileException() throws IOException, NitfFormatException { NitfReader reader = new NitfInputStreamReader(mockInputStream); reader.readBytes(100); } + + @Test(expected = NitfFormatException.class) + public void testIOExceptionReadingFromClosedStream() throws Exception { + InputStream mockInputStream = new InputStream() { + boolean closed = false; + @Override public int read() throws IOException { + throwIOExceptionIfClosed(); + return 100; + } + @Override public int read(byte[] buff, int offset, int len) throws IOException { + throwIOExceptionIfClosed(); + return 100; + } + public void close() throws IOException { + throwIOExceptionIfClosed(); + closed = true; + } + private void throwIOExceptionIfClosed() throws IOException { + if (closed) { + throw new IOException("Stream already closed"); + } + } + }; + + // IOException is rethrown as NitfFormatException + NitfReader reader = new NitfInputStreamReader(mockInputStream); + reader.close(); + reader.readBytes(100); + } } diff --git a/fluent/src/main/java/org/codice/imaging/nitf/fluent/impl/NitfParserParsingFlowImpl.java b/fluent/src/main/java/org/codice/imaging/nitf/fluent/impl/NitfParserParsingFlowImpl.java index b13eac9d9..f33e0480d 100644 --- a/fluent/src/main/java/org/codice/imaging/nitf/fluent/impl/NitfParserParsingFlowImpl.java +++ b/fluent/src/main/java/org/codice/imaging/nitf/fluent/impl/NitfParserParsingFlowImpl.java @@ -39,7 +39,7 @@ /** * A builder class that handles parsing. */ -public class NitfParserParsingFlowImpl implements NitfParserParsingFlow { +public class NitfParserParsingFlowImpl implements NitfParserParsingFlow, AutoCloseable { private final NitfReader reader; private HeapStrategy imageDataStrategy = @@ -128,4 +128,9 @@ public final NitfSegmentsFlow build(final ParseStrategy parseStrategy) NitfParser.parse(reader, parseStrategy); return new NitfSegmentsFlowImpl(parseStrategy.getDataSource(), imageDataStrategy::cleanUp); } + + @Override + public final void close() throws Exception { + this.reader.close(); + } }