]>
git.argeo.org Git - lgpl/argeo-commons.git/blob - org.argeo.cms/src/org/argeo/cms/util/AsyncPipedOutputStream.java
1 package org
.argeo
.cms
.util
;
3 import java
.io
.IOException
;
4 import java
.io
.InputStream
;
5 import java
.io
.OutputStream
;
6 import java
.io
.PipedInputStream
;
7 import java
.io
.PipedOutputStream
;
8 import java
.io
.UncheckedIOException
;
9 import java
.util
.Objects
;
10 import java
.util
.concurrent
.CompletableFuture
;
11 import java
.util
.concurrent
.TimeUnit
;
12 import java
.util
.function
.Consumer
;
15 * An output stream whose {@link #close()} method will wait for read actions to
16 * be completed. It is meant to be used transparently as an
17 * {@link OutputStream}, fulfilling the expectation that everything has been
18 * done when the {@link #close()} method has returned.
20 public class AsyncPipedOutputStream
extends PipedOutputStream
{
21 // private final static Logger logger = System.getLogger(AsyncPipedOutputStream.class.getName());
23 private CompletableFuture
<Void
> readingDone
;
25 private long timeout
= 60 * 1000;
28 * Provides the actions which will read (and close) the related piped input
29 * stream. Reading starts immediately asynchronously, but the provided
30 * {@link InputStream} will block until data starts to be written to this output
33 public void asyncRead(Consumer
<InputStream
> readActions
) {
35 PipedInputStream in
= new PipedInputStream(this);
36 readingDone
= CompletableFuture
.runAsync(() -> {
37 readActions
.accept(in
);
39 } catch (IOException e
) {
40 throw new UncheckedIOException("Cannot create piped input stream", e
);
45 * Closes this output stream immediately but then wait for the reading of the
46 * related input stream to be completed.
49 public void close() throws IOException
{
50 Objects
.requireNonNull(readingDone
, "Async read must have started");
53 readingDone
.orTimeout(timeout
, TimeUnit
.MILLISECONDS
).join();
54 // logger.log(Logger.Level.DEBUG, "OUT waiting " + timeout);
56 // readingDone.get(timeout, TimeUnit.MILLISECONDS);
57 // } catch (InterruptedException | ExecutionException | TimeoutException e) {
58 // logger.log(Logger.Level.ERROR, "Reading was not completed", e);
60 // logger.log(Logger.Level.DEBUG, "OUT closed");
64 * Sets the timeout in milliseconds when waiting for reading to be completed
65 * before returning in the {@link #close()} method.
67 public void setTimeout(long timeout
) {
68 this.timeout
= timeout
;