diff --git a/src/org/opendatakit/briefcase/reused/UncheckedFiles.java b/src/org/opendatakit/briefcase/reused/UncheckedFiles.java index e9a64b787..3a78baa07 100644 --- a/src/org/opendatakit/briefcase/reused/UncheckedFiles.java +++ b/src/org/opendatakit/briefcase/reused/UncheckedFiles.java @@ -305,6 +305,14 @@ public static InputStream newInputStream(Path path, OpenOption... options) { } } + public static void closeInputStream(InputStream inputStream) { + try { + inputStream.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + } + public static long size(Path path) { try { return Files.size(path); diff --git a/src/org/opendatakit/briefcase/reused/http/CommonsHttp.java b/src/org/opendatakit/briefcase/reused/http/CommonsHttp.java index 02f91af38..22550fcbd 100644 --- a/src/org/opendatakit/briefcase/reused/http/CommonsHttp.java +++ b/src/org/opendatakit/briefcase/reused/http/CommonsHttp.java @@ -39,12 +39,16 @@ import org.apache.http.impl.client.CloseableHttpClient; import org.apache.http.impl.client.HttpClientBuilder; import org.opendatakit.briefcase.reused.BriefcaseException; +import org.opendatakit.briefcase.reused.UncheckedFiles; import org.opendatakit.briefcase.reused.http.response.Response; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class CommonsHttp implements Http { private Executor executor; private final int maxConnections; private final BasicCookieStore cookieStore; + private static final Logger log = LoggerFactory.getLogger(CommonsHttp.class); private CommonsHttp(Executor executor, int maxConnections, BasicCookieStore cookieStore) { this.executor = executor; @@ -147,6 +151,12 @@ private Response uncheckedExecute(Request request, Executor executor) throw new HttpException("The connection has timed out", e); } catch (IOException e) { throw new UncheckedIOException(e); + } finally { + request.ifBody(UncheckedFiles::closeInputStream); + if (request.multipartMessages != null) + request.multipartMessages.stream() + .map(MultipartMessage::getBody) + .forEach(UncheckedFiles::closeInputStream); } } diff --git a/src/org/opendatakit/briefcase/reused/http/Request.java b/src/org/opendatakit/briefcase/reused/http/Request.java index c179d97e0..d3e7f917b 100644 --- a/src/org/opendatakit/briefcase/reused/http/Request.java +++ b/src/org/opendatakit/briefcase/reused/http/Request.java @@ -25,6 +25,7 @@ import java.util.Objects; import java.util.Optional; import java.util.function.BiConsumer; +import java.util.function.Consumer; import java.util.function.Function; import org.opendatakit.briefcase.reused.BriefcaseException; import org.slf4j.Logger; @@ -124,6 +125,10 @@ public InputStream getBody() { return body.orElseThrow(BriefcaseException::new); } + public void ifBody(Consumer consumer) { + body.ifPresent(consumer); + } + public boolean ignoreCookies() { return ignoreCookies; } diff --git a/test/java/org/opendatakit/briefcase/reused/UncheckedFilesInputStreamTest.java b/test/java/org/opendatakit/briefcase/reused/UncheckedFilesInputStreamTest.java new file mode 100644 index 000000000..72a4dbebd --- /dev/null +++ b/test/java/org/opendatakit/briefcase/reused/UncheckedFilesInputStreamTest.java @@ -0,0 +1,58 @@ +package org.opendatakit.briefcase.reused; + +import static org.opendatakit.briefcase.reused.UncheckedFiles.createFile; +import static org.opendatakit.briefcase.reused.UncheckedFiles.createTempDirectory; +import static org.opendatakit.briefcase.reused.UncheckedFiles.deleteRecursive; + +import java.io.IOException; +import java.io.InputStream; +import java.io.UncheckedIOException; +import java.nio.file.Path; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + + +public class UncheckedFilesInputStreamTest { + private Path tempDir; + private Path temp; + + + @Before + public void setUp() { + tempDir = createTempDirectory("briefcase"); + temp = tempDir.resolve("test.txt"); + createFile(temp); + } + + @After + public void tearDown() { + deleteRecursive(tempDir); + } + + @Test(expected = IOException.class) + public void closeInputStream_should_close() throws IOException { + InputStream inputStream = UncheckedFiles.newInputStream(temp); + + UncheckedFiles.closeInputStream(inputStream); + + // after close, .available() should throw exception + inputStream.available(); + } + + @Test(expected = UncheckedIOException.class) + public void closeInputStream_should_throw_exception() throws IOException { + InputStream is = new InputStream() { + @Override + public int read() throws IOException { + return 0; + } + @Override + public void close() throws IOException { + throw new IOException("chuchu"); + } + }; + UncheckedFiles.closeInputStream(is); + } +}