diff --git a/src/main/java/org/codehaus/mojo/exec/LineRedirectOutputStream.java b/src/main/java/org/codehaus/mojo/exec/LineRedirectOutputStream.java index d9a78fb8..f3cbb4e6 100644 --- a/src/main/java/org/codehaus/mojo/exec/LineRedirectOutputStream.java +++ b/src/main/java/org/codehaus/mojo/exec/LineRedirectOutputStream.java @@ -22,6 +22,7 @@ import java.io.ByteArrayOutputStream; import java.io.OutputStream; import java.nio.charset.Charset; +import java.util.Objects; import java.util.function.Consumer; /** @@ -35,10 +36,16 @@ class LineRedirectOutputStream extends OutputStream { private final Consumer linePrinter; + private final Charset charset; private ByteArrayOutputStream buffer = new ByteArrayOutputStream(); public LineRedirectOutputStream(Consumer linePrinter) { - this.linePrinter = linePrinter; + this(linePrinter, Charset.defaultCharset()); + } + + public LineRedirectOutputStream(Consumer linePrinter, Charset charset) { + this.linePrinter = Objects.requireNonNull(linePrinter); + this.charset = Objects.requireNonNull(charset); } @Override @@ -63,7 +70,7 @@ public void close() { } private void printAndReset() { - linePrinter.accept(new String(buffer.toByteArray(), Charset.defaultCharset())); + linePrinter.accept(new String(buffer.toByteArray(), charset)); buffer = new ByteArrayOutputStream(); } } diff --git a/src/test/java/org/codehaus/mojo/exec/LineRedirectOutputStreamTest.java b/src/test/java/org/codehaus/mojo/exec/LineRedirectOutputStreamTest.java index 0dbd5a24..d1da8d65 100644 --- a/src/test/java/org/codehaus/mojo/exec/LineRedirectOutputStreamTest.java +++ b/src/test/java/org/codehaus/mojo/exec/LineRedirectOutputStreamTest.java @@ -1,23 +1,74 @@ package org.codehaus.mojo.exec; import org.junit.Assert; +import org.junit.Assume; import org.junit.Test; import java.io.IOException; import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.function.Function; public class LineRedirectOutputStreamTest { @Test - public void givenUtf8Output_whenRedirecting_thenShouldDecodeProperly() throws IOException { + public void givenExtendedUnicodeCharacterOutput_whenRedirectingWithUtf8Charset_thenShouldDecodeProperly() + throws IOException { + internalTestForCharset(StandardCharsets.UTF_8); + } + + @Test + public void givenExtendedUnicodeCharacterOutput_whenRedirectingWithIso8859Charset_thenShouldDecodeProperly() + throws IOException { + internalTestForCharset(StandardCharsets.ISO_8859_1); + } + + @Test + public void givenExtendedUnicodeCharacterOutput_whenRedirectingWithCp1252_thenShouldDecodeProperly() + throws IOException { + Assume.assumeTrue("The JVM does not contain the cp-1252 charset", Charset.availableCharsets().containsKey("windows-1252")); + internalTestForCharset(Charset.forName("windows-1252")); + } + + @Test + public void givenExtendedUnicodeCharacterOutput_whenRedirectingWithDefaultCharset_thenShouldDecodeProperly() + throws IOException { + internalTestForCharset(Charset.defaultCharset()); + } + + @Test + public void givenExtendedUnicodeCharacterOutput_whenRedirectingWithCharsetUnspecified_thenShouldDecodeProperly() + throws IOException { + internalTestForCharset(sb -> new LineRedirectOutputStream(sb::append), Charset.defaultCharset()); + } + + @Test(expected = NullPointerException.class) + public void givenNullCharset_whenInstantiating_thenShouldThrow() { + new LineRedirectOutputStream(new StringBuilder()::append, null); + } + + @Test(expected = NullPointerException.class) + public void givenNullStringConsumer_whenInstantiating_thenShouldThrow() { + new LineRedirectOutputStream(null, Charset.defaultCharset()); + } + + private void internalTestForCharset(Charset charset) throws IOException { + internalTestForCharset(sb -> new LineRedirectOutputStream(sb::append, charset), charset); + } + + private void internalTestForCharset(Function lineRedirectOutputStream, + Charset charset) throws IOException { StringBuilder sb = new StringBuilder(); - String firstLine = "Hello 😃 😄"; - String secondLine = "foo bar éà"; + String firstLine = "Hello, 你好, नमस्ते, مرحبا, γεια σας, שלום, こんにちは, 안녕하세요!"; + String secondLine = "🌍 Welcome to the world! 🌟✨🎉🔥"; + String expectedString = firstLine + secondLine; - try (LineRedirectOutputStream os = new LineRedirectOutputStream(sb::append)) { - os.write(String.join("\n", firstLine, secondLine).getBytes(Charset.defaultCharset())); + try (LineRedirectOutputStream os = lineRedirectOutputStream.apply(sb)) { + os.write(String.join("\n", firstLine, secondLine).getBytes(charset)); } - Assert.assertEquals(firstLine + secondLine, sb.toString()); + // The String to bytes to String is required here because StringCoding uses the Charset.defaultCharset() + // internally so it would make the test fail when testing for different charsets. + Assert.assertEquals(new String(expectedString.getBytes(charset), charset), sb.toString()); } } \ No newline at end of file