You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2022/01/11 14:22:33 UTC

[commons-io] 04/04: WriterOutputStream maps null Charset, Charset name, and CharsetEncoder name to the platform default instead of throwing a NullPointerException.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git

commit f3823cb310c3409c87d6f4979f616c8650381766
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Tue Jan 11 09:22:27 2022 -0500

    WriterOutputStream maps null Charset, Charset name, and CharsetEncoder
    name to the platform default instead of throwing a NullPointerException.
---
 src/changes/changes.xml                            |  5 +-
 .../commons/io/output/WriterOutputStream.java      | 19 ++++----
 .../commons/io/output/WriterOutputStreamTest.java  | 53 +++++++++++++++++++++-
 3 files changed, 67 insertions(+), 10 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 151b755..0720199 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -127,11 +127,14 @@ The <action> type attribute can be add,update,fix,remove.
         When deleting symlinks, File/PathUtils.deleteDirectory() changes file permissions of the target.
       </action>
       <action dev="ggregory" type="fix" due-to="Gary Gregory">
-        ReaderInputStream maps null Charset, Charset name, and CharsetEmcoder to the platform default instead of throwing a NullPointerException.
+        ReaderInputStream maps null Charset, Charset name, and CharsetEncoder to the platform default instead of throwing a NullPointerException.
       </action>
       <action dev="ggregory" type="fix" due-to="Gary Gregory">
         CharSequenceInputStream maps null Charset and Charset name to the platform default instead of throwing a NullPointerException.
       </action>
+      <action dev="ggregory" type="fix" due-to="Gary Gregory">
+        WriterOutputStream maps null Charset, Charset name, and CharsetEncoder name to the platform default instead of throwing a NullPointerException.
+      </action>
       <!-- ADD -->
       <action issue="IO-726" dev="ggregory" type="fix" due-to="shollander, Gary Gregory">
         Add MemoryMappedFileInputStream #215.
diff --git a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
index ae6d1a5..b5d6f46 100644
--- a/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
+++ b/src/main/java/org/apache/commons/io/output/WriterOutputStream.java
@@ -26,6 +26,9 @@ import java.nio.charset.CharsetDecoder;
 import java.nio.charset.CoderResult;
 import java.nio.charset.CodingErrorAction;
 
+import org.apache.commons.io.Charsets;
+import org.apache.commons.io.charset.CharsetDecoders;
+
 /**
  * {@link OutputStream} implementation that transforms a byte stream to a
  * character stream using a specified charset encoding and writes the resulting
@@ -164,15 +167,16 @@ public class WriterOutputStream extends OutputStream {
      *                         output buffer will only be flushed when it overflows or when
      *                         {@link #flush()} or {@link #close()} is called.
      */
-    public WriterOutputStream(final Writer writer, final Charset charset, final int bufferSize,
-                              final boolean writeImmediately) {
+    public WriterOutputStream(final Writer writer, final Charset charset, final int bufferSize, final boolean writeImmediately) {
+        // @formatter:off
         this(writer,
-             charset.newDecoder()
+            Charsets.toCharset(charset).newDecoder()
                     .onMalformedInput(CodingErrorAction.REPLACE)
                     .onUnmappableCharacter(CodingErrorAction.REPLACE)
                     .replaceWith("?"),
              bufferSize,
              writeImmediately);
+        // @formatter:on
     }
 
     /**
@@ -201,11 +205,10 @@ public class WriterOutputStream extends OutputStream {
      *                         {@link #flush()} or {@link #close()} is called.
      * @since 2.1
      */
-    public WriterOutputStream(final Writer writer, final CharsetDecoder decoder, final int bufferSize,
-                              final boolean writeImmediately) {
-        checkIbmJdkWithBrokenUTF16( decoder.charset());
+    public WriterOutputStream(final Writer writer, final CharsetDecoder decoder, final int bufferSize, final boolean writeImmediately) {
+        checkIbmJdkWithBrokenUTF16(CharsetDecoders.toCharsetDecoder(decoder).charset());
         this.writer = writer;
-        this.decoder = decoder;
+        this.decoder = CharsetDecoders.toCharsetDecoder(decoder);
         this.writeImmediately = writeImmediately;
         decoderOut = CharBuffer.allocate(bufferSize);
     }
@@ -236,7 +239,7 @@ public class WriterOutputStream extends OutputStream {
      */
     public WriterOutputStream(final Writer writer, final String charsetName, final int bufferSize,
                               final boolean writeImmediately) {
-        this(writer, Charset.forName(charsetName), bufferSize, writeImmediately);
+        this(writer, Charsets.toCharset(charsetName), bufferSize, writeImmediately);
     }
 
     /**
diff --git a/src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java b/src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java
index 61da71c..50c840d 100644
--- a/src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java
+++ b/src/test/java/org/apache/commons/io/output/WriterOutputStreamTest.java
@@ -21,9 +21,13 @@ import static org.junit.jupiter.api.Assertions.fail;
 
 import java.io.IOException;
 import java.io.StringWriter;
+import java.nio.charset.Charset;
+import java.nio.charset.CharsetDecoder;
 import java.nio.charset.StandardCharsets;
 import java.util.Random;
 
+import org.apache.commons.io.Charsets;
+import org.apache.commons.io.charset.CharsetDecoders;
 import org.junit.jupiter.api.Test;
 
 public class WriterOutputStreamTest {
@@ -52,6 +56,16 @@ public class WriterOutputStreamTest {
     }
 
     @Test
+    public void testLargeUTF8CharsetWithBufferedWrite() throws IOException {
+        testWithBufferedWrite(LARGE_TEST_STRING, "UTF-8");
+    }
+
+    @Test
+    public void testLargeUTF8CharsetWithSingleByteWrite() throws IOException {
+        testWithSingleByteWrite(LARGE_TEST_STRING, StandardCharsets.UTF_8);
+    }
+
+    @Test
     public void testLargeUTF8WithBufferedWrite() throws IOException {
         testWithBufferedWrite(LARGE_TEST_STRING, "UTF-8");
     }
@@ -62,6 +76,21 @@ public class WriterOutputStreamTest {
     }
 
     @Test
+    public void testNullCharsetNameWithSingleByteWrite() throws IOException {
+        testWithSingleByteWrite(TEST_STRING, (String) null);
+    }
+
+    @Test
+    public void testNullCharsetWithSingleByteWrite() throws IOException {
+        testWithSingleByteWrite(TEST_STRING, (Charset) null);
+    }
+
+    @Test
+    public void testNullCharsetDecoderWithSingleByteWrite() throws IOException {
+        testWithSingleByteWrite(TEST_STRING, (CharsetDecoder) null);
+    }
+
+    @Test
     public void testUTF16BEWithBufferedWrite() throws IOException {
         testWithBufferedWrite(TEST_STRING, "UTF-16BE");
     }
@@ -128,8 +157,30 @@ public class WriterOutputStreamTest {
     }
 
 
+    private void testWithSingleByteWrite(final String testString, final Charset charset) throws IOException {
+        final byte[] bytes = testString.getBytes(Charsets.toCharset(charset));
+        final StringWriter writer = new StringWriter();
+        try (final WriterOutputStream out = new WriterOutputStream(writer, charset)) {
+            for (final byte b : bytes) {
+                out.write(b);
+            }
+        }
+        assertEquals(testString, writer.toString());
+    }
+
+    private void testWithSingleByteWrite(final String testString, final CharsetDecoder charsetDecoder) throws IOException {
+        final byte[] bytes = testString.getBytes(CharsetDecoders.toCharsetDecoder(charsetDecoder).charset());
+        final StringWriter writer = new StringWriter();
+        try (final WriterOutputStream out = new WriterOutputStream(writer, charsetDecoder)) {
+            for (final byte b : bytes) {
+                out.write(b);
+            }
+        }
+        assertEquals(testString, writer.toString());
+    }
+
     private void testWithSingleByteWrite(final String testString, final String charsetName) throws IOException {
-        final byte[] bytes = testString.getBytes(charsetName);
+        final byte[] bytes = testString.getBytes(Charsets.toCharset(charsetName));
         final StringWriter writer = new StringWriter();
         try (final WriterOutputStream out = new WriterOutputStream(writer, charsetName)) {
             for (final byte b : bytes) {