001
014
015 package com.liferay.portal.kernel.io;
016
017 import com.liferay.portal.kernel.nio.charset.CharsetEncoderUtil;
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.CharsetEncoder;
027 import java.nio.charset.CoderResult;
028
029
032 public class OutputStreamWriter extends Writer {
033
034 public OutputStreamWriter(OutputStream outputStream) {
035 this(
036 outputStream, StringPool.DEFAULT_CHARSET_NAME,
037 _DEFAULT_OUTPUT_BUFFER_SIZE, false);
038 }
039
040 public OutputStreamWriter(OutputStream outputStream, String charsetName) {
041 this(outputStream, charsetName, _DEFAULT_OUTPUT_BUFFER_SIZE, false);
042 }
043
044 public OutputStreamWriter(
045 OutputStream outputStream, String charsetName, boolean autoFlush) {
046
047 this(outputStream, charsetName, _DEFAULT_OUTPUT_BUFFER_SIZE, autoFlush);
048 }
049
050 public OutputStreamWriter(
051 OutputStream outputStream, String charsetName, int outputBufferSize) {
052
053 this(outputStream, charsetName, outputBufferSize, false);
054 }
055
056 public OutputStreamWriter(
057 OutputStream outputStream, String charsetName, int outputBufferSize,
058 boolean autoFlush) {
059
060 if (outputBufferSize < 4) {
061 throw new IllegalArgumentException(
062 "Output buffer size " + outputBufferSize + " is less than 4");
063 }
064
065 if (charsetName == null) {
066 charsetName = StringPool.DEFAULT_CHARSET_NAME;
067 }
068
069 _outputStream = outputStream;
070 _charsetName = charsetName;
071 _charsetEncoder = CharsetEncoderUtil.getCharsetEncoder(charsetName);
072 _outputByteBuffer = ByteBuffer.allocate(outputBufferSize);
073 _autoFlush = autoFlush;
074 }
075
076 @Override
077 public void close() throws IOException {
078 _flushBuffer();
079
080 _outputStream.close();
081 }
082
083 @Override
084 public void flush() throws IOException {
085 _flushBuffer();
086
087 _outputStream.flush();
088 }
089
090 public String getEncoding() {
091 return _charsetName;
092 }
093
094 @Override
095 public void write(char[] chars) throws IOException {
096 _doWrite(CharBuffer.wrap(chars, 0, chars.length));
097 }
098
099 @Override
100 public void write(char[] chars, int offset, int length) throws IOException {
101 _doWrite(CharBuffer.wrap(chars, offset, length));
102 }
103
104 @Override
105 public void write(int c) throws IOException {
106 _inputArray[0] = (char)c;
107
108 _doWrite(_inputCharBuffer);
109
110 _inputCharBuffer.clear();
111 }
112
113 @Override
114 public void write(String string) throws IOException {
115 _doWrite(CharBuffer.wrap(string, 0, string.length()));
116 }
117
118 @Override
119 public void write(String string, int offset, int length)
120 throws IOException {
121
122 _doWrite(CharBuffer.wrap(string, offset, offset + length));
123 }
124
125 private void _doWrite(CharBuffer inputCharBuffer) throws IOException {
126 while (true) {
127 CoderResult coderResult = _charsetEncoder.encode(
128 inputCharBuffer, _outputByteBuffer, true);
129
130 if (coderResult.isOverflow()) {
131 _flushBuffer();
132 }
133 else if (coderResult.isUnderflow()) {
134 if (_autoFlush) {
135 _flushBuffer();
136 }
137
138 break;
139 }
140 else {
141 throw new IOException("Unexcepted coder result " + coderResult);
142 }
143 }
144 }
145
146 private void _flushBuffer() throws IOException {
147 if (_outputByteBuffer.position() > 0) {
148 _outputStream.write(
149 _outputByteBuffer.array(), 0, _outputByteBuffer.position());
150
151 _outputByteBuffer.rewind();
152 }
153 }
154
155 private static final int _DEFAULT_OUTPUT_BUFFER_SIZE = 8192;
156
157 private final boolean _autoFlush;
158 private final CharsetEncoder _charsetEncoder;
159 private final String _charsetName;
160 private final char[] _inputArray = new char[1];
161 private final CharBuffer _inputCharBuffer = CharBuffer.wrap(_inputArray);
162 private final ByteBuffer _outputByteBuffer;
163 private final OutputStream _outputStream;
164
165 }