001package ball.activation; 002/*- 003 * ########################################################################## 004 * Utilities 005 * $Id: ReaderWriterDataSource.java 5285 2020-02-05 04:23:21Z ball $ 006 * $HeadURL: svn+ssh://svn.hcf.dev/var/spool/scm/repository.svn/ball-util/trunk/src/main/java/ball/activation/ReaderWriterDataSource.java $ 007 * %% 008 * Copyright (C) 2008 - 2020 Allen D. Ball 009 * %% 010 * Licensed under the Apache License, Version 2.0 (the "License"); 011 * you may not use this file except in compliance with the License. 012 * You may obtain a copy of the License at 013 * 014 * http://www.apache.org/licenses/LICENSE-2.0 015 * 016 * Unless required by applicable law or agreed to in writing, software 017 * distributed under the License is distributed on an "AS IS" BASIS, 018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 019 * See the License for the specific language governing permissions and 020 * limitations under the License. 021 * ########################################################################## 022 */ 023import java.beans.ConstructorProperties; 024import java.io.BufferedReader; 025import java.io.IOException; 026import java.io.InputStreamReader; 027import java.io.OutputStreamWriter; 028import java.io.PrintStream; 029import java.io.PrintWriter; 030import java.io.Reader; 031import java.io.Writer; 032import java.nio.charset.Charset; 033 034import static java.nio.charset.StandardCharsets.UTF_8; 035import static java.util.stream.Collectors.joining; 036import static org.apache.commons.lang3.StringUtils.EMPTY; 037 038/** 039 * {@link javax.activation.DataSource} implementation that provides a 040 * {@link BufferedReader} wrapping the {@link javax.activation.DataSource} 041 * {@link java.io.InputStream} and a {@link PrintWriter} wrapping the 042 * {@link javax.activation.DataSource} {@link java.io.OutputStream}. 043 * 044 * @author {@link.uri mailto:ball@hcf.dev Allen D. Ball} 045 * @version $Revision: 5285 $ 046 */ 047public class ReaderWriterDataSource extends FilterDataSource { 048 protected static final Charset CHARSET = UTF_8; 049 050 private final Charset charset; 051 052 /** 053 * @param name Initial {@code "Name"} attribute value. 054 * @param type Initial {@code "ContentType"} attribute 055 * value. 056 */ 057 @ConstructorProperties({ "name", "contentType" }) 058 public ReaderWriterDataSource(String name, String type) { 059 this(name, type, null); 060 } 061 062 /** 063 * @param name Initial {@code "Name"} attribute value. 064 * @param type Initial {@code "ContentType"} attribute 065 * value. 066 * @param charset The {@link Charset} used to encode the 067 * {@link java.io.OutputStream}. 068 */ 069 @ConstructorProperties({ "name", "contentType", "charset" }) 070 public ReaderWriterDataSource(String name, String type, Charset charset) { 071 this(name, type, charset, null); 072 } 073 074 /** 075 * @param name Initial {@code "Name"} attribute value. 076 * @param type Initial {@code "ContentType"} attribute 077 * value. 078 * @param charset The {@link Charset} used to encode the 079 * {@link java.io.OutputStream}. 080 * @param content The initial content {@link String}. 081 */ 082 @ConstructorProperties({ "name", "contentType", "charset", EMPTY }) 083 public ReaderWriterDataSource(String name, String type, 084 Charset charset, String content) { 085 super(new ByteArrayDataSource(name, type)); 086 087 this.charset = (charset != null) ? charset : CHARSET; 088 089 if (content != null) { 090 try (Writer writer = getWriter()) { 091 writer.write(content); 092 } catch (IOException exception) { 093 throw new ExceptionInInitializerError(exception); 094 } 095 } 096 } 097 098 /** 099 * Private no-argument constructor (for JAXB annotated subclasses). 100 */ 101 private ReaderWriterDataSource() { this(null, null); } 102 103 /** 104 * Method to get the {@link Charset} used to create the 105 * {@link BufferedReader} and {@link PrintWriter}. 106 * 107 * @return The Charset. 108 */ 109 public Charset getCharset() { return charset; } 110 111 /** 112 * Method to return a new {@link Reader} to read the underlying 113 * {@link java.io.InputStream}. 114 * 115 * @see #getInputStream() 116 * 117 * @return A {@link Reader} wrapping the 118 * {@link javax.activation.DataSource} 119 * {@link java.io.InputStream}. 120 * 121 * @throws IOException If an I/O exception occurs. 122 */ 123 public Reader getReader() throws IOException { 124 return new InputStreamReader(getInputStream(), getCharset()); 125 } 126 127 /** 128 * Method to return a new {@link Writer} to write to the underlying 129 * {@link java.io.OutputStream}. 130 * 131 * @see #getOutputStream() 132 * 133 * @return A {@link Writer} wrapping the 134 * {@link javax.activation.DataSource} 135 * {@link java.io.OutputStream}. 136 * 137 * @throws IOException If an I/O exception occurs. 138 */ 139 public Writer getWriter() throws IOException { 140 return new OutputStreamWriter(getOutputStream(), getCharset()); 141 } 142 143 /** 144 * Method to return a new {@link BufferedReader} to read the underlying 145 * {@link java.io.InputStream}. 146 * 147 * @see #getInputStream() 148 * 149 * @return A {@link BufferedReader} wrapping the 150 * {@link javax.activation.DataSource} 151 * {@link java.io.InputStream}. 152 * 153 * @throws IOException If an I/O exception occurs. 154 */ 155 public BufferedReader getBufferedReader() throws IOException { 156 return new BufferedReader(getReader()); 157 } 158 159 /** 160 * Method to return a new {@link PrintWriter} to write to the underlying 161 * {@link java.io.OutputStream}. 162 * 163 * @see #getOutputStream() 164 * 165 * @return A {@link PrintWriter} wrapping the 166 * {@link javax.activation.DataSource} 167 * {@link java.io.OutputStream}. 168 * 169 * @throws IOException If an I/O exception occurs. 170 */ 171 public PrintWriter getPrintWriter() throws IOException { 172 return new PrintWriter(getWriter(), true); 173 } 174 175 /** 176 * Method to return a new {@link PrintStream} to write to the underlying 177 * {@link java.io.OutputStream}. 178 * 179 * @see #getOutputStream() 180 * 181 * @return A {@link PrintStream} wrapping the 182 * {@link javax.activation.DataSource} 183 * {@link java.io.OutputStream}. 184 * 185 * @throws IOException If an I/O exception occurs. 186 */ 187 public PrintStream getPrintStream() throws IOException { 188 return new PrintStream(getOutputStream(), true, getCharset().name()); 189 } 190 191 /** 192 * Method to write the contents of this 193 * {@link javax.activation.DataSource} to a {@link PrintWriter}. 194 * 195 * @see #getBufferedReader() 196 * 197 * @param writer The target {@link PrintWriter}. 198 * 199 * @throws IOException If a problem is encountered opening or 200 * reading the {@link BufferedReader} or 201 * writing to the {@link PrintWriter}. 202 */ 203 public void writeTo(PrintWriter writer) throws IOException { 204 getBufferedReader().lines().forEach(t -> writer.println(t)); 205 } 206 207 @Override 208 public String toString() { 209 String string = null; 210 211 try (BufferedReader reader = getBufferedReader()) { 212 string = reader.lines().collect(joining("\n")); 213 } catch (IOException exception) { 214 string = super.toString(); 215 } 216 217 return string; 218 } 219 220 /** 221 * Convenience method to get the name of a {@link Charset}. 222 * 223 * @param charset The {@link Charset}. 224 * 225 * @return The name of the {@link Charset} if non-{@code null}; 226 * {@code null} otherwise. 227 * 228 * @see Charset#name() 229 */ 230 protected static String nameOf(Charset charset) { 231 return (charset != null) ? charset.name() : null; 232 } 233}