001
014
015 package com.liferay.portal.kernel.io;
016
017 import com.liferay.portal.kernel.nio.charset.CharsetDecoderUtil;
018 import com.liferay.portal.kernel.util.StringPool;
019
020 import java.io.IOException;
021 import java.io.OutputStream;
022 import java.io.Writer;
023
024 import java.nio.ByteBuffer;
025 import java.nio.CharBuffer;
026 import java.nio.charset.CharsetDecoder;
027 import java.nio.charset.CoderResult;
028
029
032 public class WriterOutputStream extends OutputStream {
033
034 public WriterOutputStream(Writer writer) {
035 this(
036 writer, StringPool.UTF8, _DEFAULT_INTPUT_BUFFER_SIZE,
037 _DEFAULT_OUTPUT_BUFFER_SIZE, false);
038 }
039
040 public WriterOutputStream(Writer writer, String charsetName) {
041 this(
042 writer, charsetName, _DEFAULT_INTPUT_BUFFER_SIZE,
043 _DEFAULT_OUTPUT_BUFFER_SIZE, false);
044 }
045
046 public WriterOutputStream(
047 Writer writer, String charsetName, boolean autoFlush) {
048
049 this(
050 writer, charsetName, _DEFAULT_INTPUT_BUFFER_SIZE,
051 _DEFAULT_OUTPUT_BUFFER_SIZE, autoFlush);
052 }
053
054 public WriterOutputStream(
055 Writer writer, String charsetName, int inputBufferSize,
056 int outputBufferSize) {
057
058 this(writer, charsetName, inputBufferSize, outputBufferSize, false);
059 }
060
061 public WriterOutputStream(
062 Writer writer, String charsetName, int inputBufferSize,
063 int outputBufferSize, boolean autoFlush) {
064
065 if (inputBufferSize < 4) {
066 throw new IllegalArgumentException(
067 "Input buffer size " + inputBufferSize + " is less than 4");
068 }
069
070 if (outputBufferSize <= 0) {
071 throw new IllegalArgumentException(
072 "Output buffer size " + outputBufferSize +
073 " must be a positive number");
074 }
075
076 _writer = writer;
077 _charsetName = charsetName;
078 _charsetDecoder = CharsetDecoderUtil.getCharsetDecoder(charsetName);
079 _inputBuffer = ByteBuffer.allocate(inputBufferSize);
080 _outputBuffer = CharBuffer.allocate(outputBufferSize);
081 _autoFlush = autoFlush;
082 }
083
084 public void close() throws IOException {
085 _doDecode(true);
086 _doFlush();
087
088 _writer.close();
089 }
090
091 public void flush() throws IOException {
092 _doFlush();
093
094 _writer.flush();
095 }
096
097 public String getEncoding() {
098 return _charsetName;
099 }
100
101 public void write(byte[] byteArray) throws IOException {
102 write(byteArray, 0, byteArray.length);
103 }
104
105 public void write(byte[] byteArray, int offset, int length)
106 throws IOException {
107
108 while (length > 0) {
109 int blockSize = Math.min(length, _inputBuffer.remaining());
110
111 _inputBuffer.put(byteArray, offset, blockSize);
112
113 _doDecode(false);
114
115 length -= blockSize;
116 offset += blockSize;
117 }
118
119 if (_autoFlush) {
120 _doFlush();
121 }
122 }
123
124 public void write(int b) throws IOException {
125 write(new byte[] {(byte)b}, 0, 1);
126 }
127
128 private void _doDecode(boolean endOfInput) throws IOException {
129 _inputBuffer.flip();
130
131 while (true) {
132 CoderResult coderResult = _charsetDecoder.decode(
133 _inputBuffer, _outputBuffer, endOfInput);
134
135 if (coderResult.isOverflow()) {
136 _doFlush();
137 }
138 else if (coderResult.isUnderflow()) {
139 break;
140 }
141 else {
142 throw new IOException("Unexcepted coder result " + coderResult);
143 }
144 }
145
146 _inputBuffer.compact();
147 }
148
149 private void _doFlush() throws IOException {
150 if (_outputBuffer.position() > 0) {
151 _writer.write(_outputBuffer.array(), 0, _outputBuffer.position());
152
153 _outputBuffer.rewind();
154 }
155 }
156
157 private static final int _DEFAULT_INTPUT_BUFFER_SIZE = 128;
158
159 private static final int _DEFAULT_OUTPUT_BUFFER_SIZE = 1024;
160
161 private boolean _autoFlush;
162 private CharsetDecoder _charsetDecoder;
163 private String _charsetName;
164 private ByteBuffer _inputBuffer;
165 private CharBuffer _outputBuffer;
166 private Writer _writer;
167
168 }