Guard Mapper.write against null writer (#123)

* Expose anonymous classes to DelegatingX classes

Applies the suggestions by @jungm and @rmannibucau

* Modify code style
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingInputStream.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingInputStream.java
new file mode 100644
index 0000000..f083ba3
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingInputStream.java
@@ -0,0 +1,75 @@
+/*
+ *     Licensed to the Apache Software Foundation (ASF) under one or more
+ *     contributor license agreements.  See the NOTICE file distributed with
+ *     this work for additional information regarding copyright ownership.
+ *     The ASF licenses this file to You under the Apache License, Version 2.0
+ *     (the "License"); you may not use this file except in compliance with
+ *     the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *     Unless required by applicable law or agreed to in writing, software
+ *     distributed under the License is distributed on an "AS IS" BASIS,
+ *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *     See the License for the specific language governing permissions and
+ *     limitations under the License.
+ */
+package org.apache.johnzon.mapper.internal;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Objects;
+
+public class DelegatingInputStream extends InputStream {
+
+    private final InputStream inputStream;
+
+    public DelegatingInputStream(InputStream inputStream) {
+        this.inputStream = Objects.requireNonNull(inputStream, "delegate inputStream must not be null");
+    }
+
+    @Override
+    public void close() throws IOException {
+        inputStream.close();
+    }
+
+    @Override
+    public int read(final byte[] b) throws IOException {
+        return inputStream.read(b);
+    }
+
+    @Override
+    public int read(final byte[] b, final int off, final int len) throws IOException {
+        return inputStream.read(b, off, len);
+    }
+
+    @Override
+    public long skip(final long n) throws IOException {
+        return inputStream.skip(n);
+    }
+
+    @Override
+    public int available() throws IOException {
+        return inputStream.available();
+    }
+
+    @Override
+    public void mark(final int readlimit) {
+        inputStream.mark(readlimit);
+    }
+
+    @Override
+    public void reset() throws IOException {
+        inputStream.reset();
+    }
+
+    @Override
+    public boolean markSupported() {
+        return inputStream.markSupported();
+    }
+
+    @Override
+    public int read() throws IOException {
+        return inputStream.read();
+    }
+}
\ No newline at end of file
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingOutputStream.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingOutputStream.java
new file mode 100644
index 0000000..cf5c168
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingOutputStream.java
@@ -0,0 +1,55 @@
+/*
+ *     Licensed to the Apache Software Foundation (ASF) under one or more
+ *     contributor license agreements.  See the NOTICE file distributed with
+ *     this work for additional information regarding copyright ownership.
+ *     The ASF licenses this file to You under the Apache License, Version 2.0
+ *     (the "License"); you may not use this file except in compliance with
+ *     the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *     Unless required by applicable law or agreed to in writing, software
+ *     distributed under the License is distributed on an "AS IS" BASIS,
+ *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *     See the License for the specific language governing permissions and
+ *     limitations under the License.
+ */
+package org.apache.johnzon.mapper.internal;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Objects;
+
+public class DelegatingOutputStream extends OutputStream {
+
+    private final OutputStream outputStream;
+
+    public DelegatingOutputStream(OutputStream outputStream) {
+        this.outputStream = Objects.requireNonNull(outputStream, "delegate outputStream must not be null");
+    }
+
+    @Override
+    public void close() throws IOException {
+        outputStream.close();
+    }
+
+    @Override
+    public void write(final int b) throws IOException {
+        outputStream.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b) throws IOException {
+        outputStream.write(b);
+    }
+
+    @Override
+    public void write(final byte[] b, final int off, final int len) throws IOException {
+        outputStream.write(b, off, len);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        outputStream.flush();
+    }
+}
\ No newline at end of file
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingReader.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingReader.java
new file mode 100644
index 0000000..617e525
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingReader.java
@@ -0,0 +1,81 @@
+/*
+ *     Licensed to the Apache Software Foundation (ASF) under one or more
+ *     contributor license agreements.  See the NOTICE file distributed with
+ *     this work for additional information regarding copyright ownership.
+ *     The ASF licenses this file to You under the Apache License, Version 2.0
+ *     (the "License"); you may not use this file except in compliance with
+ *     the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *     Unless required by applicable law or agreed to in writing, software
+ *     distributed under the License is distributed on an "AS IS" BASIS,
+ *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *     See the License for the specific language governing permissions and
+ *     limitations under the License.
+ */
+package org.apache.johnzon.mapper.internal;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.nio.CharBuffer;
+import java.util.Objects;
+
+public class DelegatingReader extends Reader {
+
+    private final Reader reader;
+
+    public DelegatingReader(Reader reader) {
+        this.reader = Objects.requireNonNull(reader, "delegate reader must not be null");
+    }
+
+    @Override
+    public void close() throws IOException {
+        reader.close();
+    }
+
+    @Override
+    public int read(final CharBuffer target) throws IOException {
+        return reader.read(target);
+    }
+
+    @Override
+    public int read() throws IOException {
+        return reader.read();
+    }
+
+    @Override
+    public int read(final char[] cbuf) throws IOException {
+        return reader.read(cbuf);
+    }
+
+    @Override
+    public int read(final char[] cbuf, final int off, final int len) throws IOException {
+        return reader.read(cbuf, off, len);
+    }
+
+    @Override
+    public long skip(final long n) throws IOException {
+        return reader.skip(n);
+    }
+
+    @Override
+    public boolean ready() throws IOException {
+        return reader.ready();
+    }
+
+    @Override
+    public boolean markSupported() {
+        return reader.markSupported();
+    }
+
+    @Override
+    public void mark(final int readAheadLimit) throws IOException {
+        reader.mark(readAheadLimit);
+    }
+
+    @Override
+    public void reset() throws IOException {
+        reader.reset();
+    }
+}
\ No newline at end of file
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingWriter.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingWriter.java
new file mode 100644
index 0000000..0de1fc2
--- /dev/null
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/DelegatingWriter.java
@@ -0,0 +1,79 @@
+/*
+ *     Licensed to the Apache Software Foundation (ASF) under one or more
+ *     contributor license agreements.  See the NOTICE file distributed with
+ *     this work for additional information regarding copyright ownership.
+ *     The ASF licenses this file to You under the Apache License, Version 2.0
+ *     (the "License"); you may not use this file except in compliance with
+ *     the License.  You may obtain a copy of the License at
+ *
+ *        http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *     Unless required by applicable law or agreed to in writing, software
+ *     distributed under the License is distributed on an "AS IS" BASIS,
+ *     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *     See the License for the specific language governing permissions and
+ *     limitations under the License.
+ */
+package org.apache.johnzon.mapper.internal;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.util.Objects;
+
+public class DelegatingWriter extends Writer {
+    private final Writer writer;
+
+    public DelegatingWriter(Writer writer) {
+        this.writer = Objects.requireNonNull(writer, "delegate writer must not be null");
+    }
+
+    @Override
+    public void write(final int c) throws IOException {
+        writer.write(c);
+    }
+
+    @Override
+    public void write(final char[] cbuf) throws IOException {
+        writer.write(cbuf);
+    }
+
+    @Override
+    public void write(final char[] cbuf, final int off, final int len) throws IOException {
+        writer.write(cbuf, off, len);
+    }
+
+    @Override
+    public void write(final String str) throws IOException {
+        writer.write(str);
+    }
+
+    @Override
+    public void write(final String str, final int off, final int len) throws IOException {
+        writer.write(str, off, len);
+    }
+
+    @Override
+    public Writer append(final CharSequence csq) throws IOException {
+        return writer.append(csq);
+    }
+
+    @Override
+    public Writer append(final CharSequence csq, final int start, final int end) throws IOException {
+        return writer.append(csq, start, end);
+    }
+
+    @Override
+    public Writer append(final char c) throws IOException {
+        return writer.append(c);
+    }
+
+    @Override
+    public void flush() throws IOException {
+        writer.flush();
+    }
+
+    @Override
+    public void close() throws IOException {
+        writer.close();
+    }
+}
\ No newline at end of file
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/Streams.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/Streams.java
index 8fb273c..e4bc8d5 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/Streams.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/internal/Streams.java
@@ -21,195 +21,44 @@
 import java.io.OutputStream;
 import java.io.Reader;
 import java.io.Writer;
-import java.nio.CharBuffer;
 
 public final class Streams {
     private Streams() {
         // no-op
     }
 
-    public static Writer noClose(final Writer from) {
-        return new Writer() {
-            @Override
-            public void write(final int c) throws IOException {
-                from.write(c);
-            }
-
-            @Override
-            public void write(final char[] cbuf) throws IOException {
-                from.write(cbuf);
-            }
-
-            @Override
-            public void write(final char[] cbuf, final int off, final int len) throws IOException {
-                from.write(cbuf, off, len);
-            }
-
-            @Override
-            public void write(final String str) throws IOException {
-                from.write(str);
-            }
-
-            @Override
-            public void write(final String str, final int off, final int len) throws IOException {
-                from.write(str, off, len);
-            }
-
-            @Override
-            public Writer append(final CharSequence csq) throws IOException {
-                return from.append(csq);
-            }
-
-            @Override
-            public Writer append(final CharSequence csq, final int start, final int end) throws IOException {
-                return from.append(csq, start, end);
-            }
-
-            @Override
-            public Writer append(final char c) throws IOException {
-                return from.append(c);
-            }
-
-            @Override
-            public void flush() throws IOException {
-                from.flush();
-            }
-
+    public static Writer noClose(final Writer writer) {
+        return new DelegatingWriter(writer) {
             @Override
             public void close() throws IOException {
-                from.flush();
+                flush();
             }
         };
     }
 
-    public static Reader noClose(final Reader from) {
-        return new Reader() {
+    public static Reader noClose(final Reader reader) {
+        return new DelegatingReader(reader) {
             @Override
             public void close() throws IOException {
                 // no-op
             }
-
-            @Override
-            public int read(final CharBuffer target) throws IOException {
-                return from.read(target);
-            }
-
-            @Override
-            public int read() throws IOException {
-                return from.read();
-            }
-
-            @Override
-            public int read(final char[] cbuf) throws IOException {
-                return from.read(cbuf);
-            }
-
-            @Override
-            public int read(final char[] cbuf, final int off, final int len) throws IOException {
-                return from.read(cbuf, off, len);
-            }
-
-            @Override
-            public long skip(final long n) throws IOException {
-                return from.skip(n);
-            }
-
-            @Override
-            public boolean ready() throws IOException {
-                return from.ready();
-            }
-
-            @Override
-            public boolean markSupported() {
-                return from.markSupported();
-            }
-
-            @Override
-            public void mark(final int readAheadLimit) throws IOException {
-                from.mark(readAheadLimit);
-            }
-
-            @Override
-            public void reset() throws IOException {
-                from.reset();
-            }
         };
     }
-    public static OutputStream noClose(final OutputStream from) {
-        return new OutputStream() {
+    public static OutputStream noClose(final OutputStream outputStream) {
+        return new DelegatingOutputStream(outputStream) {
             @Override
             public void close() throws IOException {
-                from.flush();
-            }
-
-            @Override
-            public void write(final int b) throws IOException {
-                from.write(b);
-            }
-
-            @Override
-            public void write(final byte[] b) throws IOException {
-                from.write(b);
-            }
-
-            @Override
-            public void write(final byte[] b, final int off, final int len) throws IOException {
-                from.write(b, off, len);
-            }
-
-            @Override
-            public void flush() throws IOException {
-                from.flush();
+                flush();
             }
         };
     }
 
-    public static InputStream noClose(final InputStream from) {
-        return new InputStream() {
+    public static InputStream noClose(final InputStream inputStream) {
+        return new DelegatingInputStream(inputStream) {
             @Override
             public void close() throws IOException {
                 // no-op
             }
-
-            @Override
-            public int read(final byte[] b) throws IOException {
-                return from.read(b);
-            }
-
-            @Override
-            public int read(final byte[] b, final int off, final int len) throws IOException {
-                return from.read(b, off, len);
-            }
-
-            @Override
-            public long skip(final long n) throws IOException {
-                return from.skip(n);
-            }
-
-            @Override
-            public int available() throws IOException {
-                return from.available();
-            }
-
-            @Override
-            public void mark(final int readlimit) {
-                from.mark(readlimit);
-            }
-
-            @Override
-            public void reset() throws IOException {
-                from.reset();
-            }
-
-            @Override
-            public boolean markSupported() {
-                return from.markSupported();
-            }
-
-            @Override
-            public int read() throws IOException {
-                return from.read();
-            }
         };
     }
 }