From 09facea48526939f4995b0ecff9c421e5bcf9299 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Fri, 3 Mar 2023 21:49:39 +0400 Subject: [PATCH 01/13] LogOutputStream.create(LineConsumer) --- .../exec/stream/LogOutputStream.java | 24 ++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java index 53cdc32..a0c1bad 100644 --- a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java +++ b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java @@ -21,7 +21,6 @@ import java.io.IOException; import java.io.OutputStream; import java.io.UnsupportedEncodingException; -import java.nio.charset.Charset; /** * Base class to connect a logging system to the output and/or @@ -159,4 +158,27 @@ protected void processBuffer() { */ protected abstract void processLine(String line); + /** + * This is equivalent to {@code java.util.function.Consumer} while staying compatible with + * earlier java version. + */ + public interface LineConsumer { + void accept(String line); + } + + /** + * Creates LogOutputStream passing each line to the specified consumer. + * This method is supposed to be used in java 8+, providing consumer as a lambda expression. + */ + public static LogOutputStream create(final LineConsumer consumer) { + if (consumer == null) { + throw new IllegalArgumentException("Line consumer must be provided."); + } + return new LogOutputStream() { + @Override + protected void processLine(String line) { + consumer.accept(line); + } + }; + } } From 190dfcaeca9783f09e5f7229c7d754ff94bc81d6 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Fri, 3 Mar 2023 21:55:50 +0400 Subject: [PATCH 02/13] typo INITIAL_SIZE --- .../java/org/zeroturnaround/exec/stream/LogOutputStream.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java index a0c1bad..db8b3a5 100644 --- a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java +++ b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java @@ -31,7 +31,7 @@ public abstract class LogOutputStream extends OutputStream { /** Initial buffer size. */ - private static final int INTIAL_SIZE = 132; + private static final int INITIAL_SIZE = 132; /** Carriage return */ private static final int CR = 0x0d; @@ -41,7 +41,7 @@ public abstract class LogOutputStream extends OutputStream { /** the internal buffer */ private final ByteArrayOutputStream buffer = new ByteArrayOutputStream( - INTIAL_SIZE); + INITIAL_SIZE); byte lastReceivedByte; From 334e0f6c24fe827a6e37638360bb80aae64506d6 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 08:52:00 +0200 Subject: [PATCH 03/13] Update src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java Co-authored-by: Neeme Praks --- .../java/org/zeroturnaround/exec/stream/LogOutputStream.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java index db8b3a5..8708d06 100644 --- a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java +++ b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java @@ -160,7 +160,7 @@ protected void processBuffer() { /** * This is equivalent to {@code java.util.function.Consumer} while staying compatible with - * earlier java version. + * Java versions earlier than 8. */ public interface LineConsumer { void accept(String line); From 4b63c174588853a62f8f0a0edf348ad660847c44 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 08:53:23 +0200 Subject: [PATCH 04/13] Update src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java Co-authored-by: Neeme Praks --- .../org/zeroturnaround/exec/stream/LogOutputStream.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java index 8708d06..5a5c0b1 100644 --- a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java +++ b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java @@ -167,8 +167,11 @@ public interface LineConsumer { } /** - * Creates LogOutputStream passing each line to the specified consumer. - * This method is supposed to be used in java 8+, providing consumer as a lambda expression. + * Factory method to create a LogOutputStream that passes each line to the specified consumer. + *

Mostly useful with Java 8+, so the consumer can be passed as a lambda expression.

+ * + * @param consumer the consumer to consume the log lines + * @return the created LogOutputStream, passing each line to the specified consumer. */ public static LogOutputStream create(final LineConsumer consumer) { if (consumer == null) { From 3a4f9ccc31477d079b53e518839dfc655cc4fcd5 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 10:57:59 +0400 Subject: [PATCH 05/13] readme --- README.md | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 6d9d114..42b14a9 100644 --- a/README.md +++ b/README.md @@ -155,7 +155,17 @@ new ProcessExecutor().command("java", "-version")
-* Handling output line-by-line while process is running +* Handling output line-by-line while process is running (java 8+) + +```java +new ProcessExecutor().command("java", "-version") + .redirectOutput(LogOutputStream.create(line -> ...)) + .execute(); +``` + +
+ +* Handling output line-by-line while process is running (prior to java 8) ```java new ProcessExecutor().command("java", "-version") @@ -259,4 +269,3 @@ Future future = new ProcessExecutor() // do some stuff String output = future.get(60, TimeUnit.SECONDS).outputUTF8(); ``` - From f32ba3ecc7790bfb31acb228884c178fa8307954 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 10:58:18 +0400 Subject: [PATCH 06/13] formatting --- .../org/zeroturnaround/exec/stream/LogOutputStream.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java index 5a5c0b1..ee7797d 100644 --- a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java +++ b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java @@ -167,10 +167,10 @@ public interface LineConsumer { } /** - * Factory method to create a LogOutputStream that passes each line to the specified consumer. - *

Mostly useful with Java 8+, so the consumer can be passed as a lambda expression.

- * - * @param consumer the consumer to consume the log lines + * Factory method to create a LogOutputStream that passes each line to the specified consumer. + *

Mostly useful with Java 8+, so the consumer can be passed as a lambda expression.

+ * + * @param consumer the consumer to consume the log lines * @return the created LogOutputStream, passing each line to the specified consumer. */ public static LogOutputStream create(final LineConsumer consumer) { From e3ac714e29aad0a8ee020101a10d3ba74981af36 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 11:10:32 +0400 Subject: [PATCH 07/13] test --- .../exec/stream/LogOutputStreamTest.java | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java diff --git a/src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java b/src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java new file mode 100644 index 0000000..7e3fc2a --- /dev/null +++ b/src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java @@ -0,0 +1,42 @@ +package org.zeroturnaround.exec.stream; + +import org.junit.Test; + +import java.io.IOException; +import java.io.OutputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class LogOutputStreamTest { + private void writeDataTo(OutputStream out) throws IOException { + out.write("Hello,\nworld!".getBytes()); + out.close(); + } + + @Test + public void anonymous() throws IOException { + final List lines = new ArrayList(); + writeDataTo(new LogOutputStream() { + @Override + protected void processLine(String line) { + lines.add(line); + } + }); + assertEquals(Arrays.asList("Hello,", "world!"), lines); + } + + @Test + public void lambda() throws IOException { + final List lines = new ArrayList(); + writeDataTo(LogOutputStream.create(new LogOutputStream.LineConsumer() { + @Override + public void accept(String line) { + lines.add(line); + } + })); + assertEquals(Arrays.asList("Hello,", "world!"), lines); + } +} From d331738f10ea769a67c4b18d0a14c49954ea4a4b Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 11:19:06 +0400 Subject: [PATCH 08/13] move into existing test --- .../exec/stream/LogOutputStreamTest.java | 42 ------------------- .../exec/test/LogOutputStreamTest.java | 15 +++++++ 2 files changed, 15 insertions(+), 42 deletions(-) delete mode 100644 src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java diff --git a/src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java b/src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java deleted file mode 100644 index 7e3fc2a..0000000 --- a/src/test/java/org/zeroturnaround/exec/stream/LogOutputStreamTest.java +++ /dev/null @@ -1,42 +0,0 @@ -package org.zeroturnaround.exec.stream; - -import org.junit.Test; - -import java.io.IOException; -import java.io.OutputStream; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.junit.Assert.assertEquals; - -public class LogOutputStreamTest { - private void writeDataTo(OutputStream out) throws IOException { - out.write("Hello,\nworld!".getBytes()); - out.close(); - } - - @Test - public void anonymous() throws IOException { - final List lines = new ArrayList(); - writeDataTo(new LogOutputStream() { - @Override - protected void processLine(String line) { - lines.add(line); - } - }); - assertEquals(Arrays.asList("Hello,", "world!"), lines); - } - - @Test - public void lambda() throws IOException { - final List lines = new ArrayList(); - writeDataTo(LogOutputStream.create(new LogOutputStream.LineConsumer() { - @Override - public void accept(String line) { - lines.add(line); - } - })); - assertEquals(Arrays.asList("Hello,", "world!"), lines); - } -} diff --git a/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java b/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java index babe347..dc84b1b 100644 --- a/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java +++ b/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java @@ -4,6 +4,7 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import org.junit.Assert; @@ -74,4 +75,18 @@ public void testNewLineAtTheEnd() throws UnsupportedEncodingException, IOExcepti testLogOutputStream("foo\n", "foo"); } + @Test + public void lambda() throws IOException { + final List lines = new ArrayList(); + LogOutputStream out = LogOutputStream.create(new LogOutputStream.LineConsumer() { + @Override + public void accept(String line) { + lines.add(line); + } + }); + out.write("foo\nbar".getBytes()); + Assert.assertEquals(Collections.singletonList("foo"), lines); + out.flush(); + Assert.assertEquals(Arrays.asList("foo", "bar"), lines); + } } From 6ba3a514d4f8756bb0e7c3c6dd5e54e65263c8f5 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Sat, 4 Mar 2023 11:33:44 +0400 Subject: [PATCH 09/13] simplify test --- .../org/zeroturnaround/exec/test/LogOutputStreamTest.java | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java b/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java index dc84b1b..82f44f2 100644 --- a/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java +++ b/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java @@ -4,7 +4,6 @@ import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Arrays; -import java.util.Collections; import java.util.List; import org.junit.Assert; @@ -84,9 +83,7 @@ public void accept(String line) { lines.add(line); } }); - out.write("foo\nbar".getBytes()); - Assert.assertEquals(Collections.singletonList("foo"), lines); - out.flush(); + out.write("foo\nbar\n".getBytes()); Assert.assertEquals(Arrays.asList("foo", "bar"), lines); } } From f15be1fbac912d3c3cc6618a96c728a38ee53cf5 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Mon, 12 Jun 2023 18:34:25 +0200 Subject: [PATCH 10/13] redirectOutput(LineConsumer consumer) --- .../zeroturnaround/exec/ProcessExecutor.java | 26 +++++++++++++++++++ .../exec/stream/LineConsumer.java | 9 +++++++ .../exec/stream/LogOutputStream.java | 8 ------ .../exec/test/LogOutputStreamTest.java | 3 ++- 4 files changed, 37 insertions(+), 9 deletions(-) create mode 100644 src/main/java/org/zeroturnaround/exec/stream/LineConsumer.java diff --git a/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java b/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java index d27e8db..0c1bde0 100644 --- a/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java +++ b/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java @@ -471,6 +471,19 @@ public ProcessExecutor redirectOutput(OutputStream output) { return streams(new PumpStreamHandler(output, pumps == null ? null : pumps.getErr(), pumps == null ? null : pumps.getInput())); } + /** + * Redirects the process' output stream to given line consumer. + * If this method is invoked multiple times each call overwrites the previous. + * Use {@link #redirectOutputAlsoTo(OutputStream)} if you want to redirect the output to multiple streams. + * + * @param consumer consumer where the process output is redirected to. + * @return This process executor. + * @see #redirectOutput(OutputStream) + */ + public ProcessExecutor redirectOutput(LineConsumer consumer) { + return redirectOutput(LogOutputStream.create(consumer)); + } + /** * Redirects the process' error stream to given output stream. * If this method is invoked multiple times each call overwrites the previous. @@ -492,6 +505,19 @@ public ProcessExecutor redirectError(OutputStream output) { return this; } + /** + * Redirects the process' error stream to given line consumer. + * If this method is invoked multiple times each call overwrites the previous. + * Use {@link #redirectErrorAlsoTo(OutputStream)} if you want to redirect the output to multiple streams. + * + * @param consumer consumer where the process error is redirected to. + * @return This process executor. + * @see #redirectError(OutputStream) + */ + public ProcessExecutor redirectError(LineConsumer consumer) { + return redirectError(LogOutputStream.create(consumer)); + } + /** * Redirects the process' output stream also to a given output stream. * This method can be used to redirect output to multiple streams. diff --git a/src/main/java/org/zeroturnaround/exec/stream/LineConsumer.java b/src/main/java/org/zeroturnaround/exec/stream/LineConsumer.java new file mode 100644 index 0000000..b0be384 --- /dev/null +++ b/src/main/java/org/zeroturnaround/exec/stream/LineConsumer.java @@ -0,0 +1,9 @@ +package org.zeroturnaround.exec.stream; + +/** + * This is equivalent to {@code java.util.function.Consumer} while staying compatible with + * Java versions earlier than 8. + */ +public interface LineConsumer { + void accept(String line); +} diff --git a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java index ee7797d..3105bba 100644 --- a/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java +++ b/src/main/java/org/zeroturnaround/exec/stream/LogOutputStream.java @@ -158,14 +158,6 @@ protected void processBuffer() { */ protected abstract void processLine(String line); - /** - * This is equivalent to {@code java.util.function.Consumer} while staying compatible with - * Java versions earlier than 8. - */ - public interface LineConsumer { - void accept(String line); - } - /** * Factory method to create a LogOutputStream that passes each line to the specified consumer. *

Mostly useful with Java 8+, so the consumer can be passed as a lambda expression.

diff --git a/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java b/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java index 82f44f2..6aaa47f 100644 --- a/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java +++ b/src/test/java/org/zeroturnaround/exec/test/LogOutputStreamTest.java @@ -8,6 +8,7 @@ import org.junit.Assert; import org.junit.Test; +import org.zeroturnaround.exec.stream.LineConsumer; import org.zeroturnaround.exec.stream.LogOutputStream; public class LogOutputStreamTest { @@ -77,7 +78,7 @@ public void testNewLineAtTheEnd() throws UnsupportedEncodingException, IOExcepti @Test public void lambda() throws IOException { final List lines = new ArrayList(); - LogOutputStream out = LogOutputStream.create(new LogOutputStream.LineConsumer() { + LogOutputStream out = LogOutputStream.create(new LineConsumer() { @Override public void accept(String line) { lines.add(line); From d0c77b3c1251f74dadff9299d4099864b3f95f50 Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Mon, 12 Jun 2023 18:54:46 +0200 Subject: [PATCH 11/13] fix build --- src/main/java/org/zeroturnaround/exec/ProcessExecutor.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java b/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java index 0c1bde0..4248490 100644 --- a/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java +++ b/src/main/java/org/zeroturnaround/exec/ProcessExecutor.java @@ -136,8 +136,8 @@ public class ProcessExecutor { // Run in case of any constructor exitValues(DEFAULT_EXIT_VALUES); stopper(DestroyProcessStopper.INSTANCE); - redirectOutput(null); - redirectError(null); + redirectOutput(NullOutputStream.NULL_OUTPUT_STREAM); + redirectError(NullOutputStream.NULL_OUTPUT_STREAM); destroyer(null); redirectErrorStream(DEFAULT_REDIRECT_ERROR_STREAM); } From 00f10eb22d6941587b60551695134442a358e7fc Mon Sep 17 00:00:00 2001 From: Alex Panchenko Date: Mon, 12 Jun 2023 18:57:52 +0200 Subject: [PATCH 12/13] use lambda in readme --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index f935a08..4e55de4 100644 --- a/README.md +++ b/README.md @@ -164,7 +164,7 @@ new ProcessExecutor().command("java", "-version") ```java new ProcessExecutor().command("java", "-version") - .redirectOutput(LogOutputStream.create(line -> ...)) + .redirectOutput(line -> ...) .execute(); ``` From cf26de6525b5fc81c0ee295199c96e91491f5813 Mon Sep 17 00:00:00 2001 From: Neeme Praks Date: Fri, 15 Mar 2024 22:25:24 +0200 Subject: [PATCH 13/13] Improve README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 4e55de4..a7ea1f1 100644 --- a/README.md +++ b/README.md @@ -160,7 +160,7 @@ new ProcessExecutor().command("java", "-version")
-* Handling output line-by-line while process is running (java 8+) +* Handling output line-by-line while process is running (Java 8+) ```java new ProcessExecutor().command("java", "-version") @@ -170,7 +170,7 @@ new ProcessExecutor().command("java", "-version")
-* Handling output line-by-line while process is running (prior to java 8) +* Handling output line-by-line while process is running (prior to Java 8) ```java new ProcessExecutor().command("java", "-version")