1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.nio.reactor;
29
30 import java.io.IOException;
31 import java.nio.ByteBuffer;
32 import java.nio.CharBuffer;
33 import java.nio.channels.ReadableByteChannel;
34 import java.nio.channels.WritableByteChannel;
35 import java.nio.charset.CharacterCodingException;
36 import java.nio.charset.Charset;
37 import java.nio.charset.CharsetEncoder;
38 import java.nio.charset.CoderResult;
39
40 import org.apache.http.annotation.NotThreadSafe;
41 import org.apache.http.nio.reactor.SessionOutputBuffer;
42 import org.apache.http.nio.util.ByteBufferAllocator;
43 import org.apache.http.nio.util.ExpandableBuffer;
44 import org.apache.http.nio.util.HeapByteBufferAllocator;
45 import org.apache.http.params.HttpParams;
46 import org.apache.http.params.HttpProtocolParams;
47 import org.apache.http.protocol.HTTP;
48 import org.apache.http.util.CharArrayBuffer;
49
50
51
52
53
54
55
56
57
58
59
60
61
62 @NotThreadSafe
63 public class SessionOutputBufferImpl extends ExpandableBuffer implements SessionOutputBuffer {
64
65 private static final byte[] CRLF = new byte[] {HTTP.CR, HTTP.LF};
66
67 private CharBuffer charbuffer = null;
68 private Charset charset = null;
69 private CharsetEncoder charencoder = null;
70
71 public SessionOutputBufferImpl(
72 int buffersize,
73 int linebuffersize,
74 final ByteBufferAllocator allocator,
75 final HttpParams params) {
76 super(buffersize, allocator);
77 this.charbuffer = CharBuffer.allocate(linebuffersize);
78 this.charset = Charset.forName(HttpProtocolParams.getHttpElementCharset(params));
79 this.charencoder = this.charset.newEncoder();
80 this.charencoder.onMalformedInput(HttpProtocolParams.getMalformedInputAction(params));
81 this.charencoder.onUnmappableCharacter(HttpProtocolParams.getUnmappableInputAction(params));
82 }
83
84 public SessionOutputBufferImpl(
85 int buffersize,
86 int linebuffersize,
87 final HttpParams params) {
88 this(buffersize, linebuffersize, new HeapByteBufferAllocator(), params);
89 }
90
91 public void reset(final HttpParams params) {
92 clear();
93 }
94
95 public int flush(final WritableByteChannel channel) throws IOException {
96 if (channel == null) {
97 throw new IllegalArgumentException("Channel may not be null");
98 }
99 setOutputMode();
100 int noWritten = channel.write(this.buffer);
101 return noWritten;
102 }
103
104 public void write(final ByteBuffer src) {
105 if (src == null) {
106 return;
107 }
108 setInputMode();
109 int requiredCapacity = this.buffer.position() + src.remaining();
110 ensureCapacity(requiredCapacity);
111 this.buffer.put(src);
112 }
113
114 public void write(final ReadableByteChannel src) throws IOException {
115 if (src == null) {
116 return;
117 }
118 setInputMode();
119 src.read(this.buffer);
120 }
121
122 private void write(final byte[] b) {
123 if (b == null) {
124 return;
125 }
126 setInputMode();
127 int off = 0;
128 int len = b.length;
129 int requiredCapacity = this.buffer.position() + len;
130 ensureCapacity(requiredCapacity);
131 this.buffer.put(b, off, len);
132 }
133
134 private void writeCRLF() {
135 write(CRLF);
136 }
137
138 public void writeLine(final CharArrayBuffer linebuffer) throws CharacterCodingException {
139 if (linebuffer == null) {
140 return;
141 }
142
143 if (linebuffer.length() > 0 ) {
144 setInputMode();
145 this.charencoder.reset();
146
147 int remaining = linebuffer.length();
148 int offset = 0;
149 while (remaining > 0) {
150 int l = this.charbuffer.remaining();
151 boolean eol = false;
152 if (remaining <= l) {
153 l = remaining;
154
155 eol = true;
156 }
157 this.charbuffer.put(linebuffer.buffer(), offset, l);
158 this.charbuffer.flip();
159
160 boolean retry = true;
161 while (retry) {
162 CoderResult result = this.charencoder.encode(this.charbuffer, this.buffer, eol);
163 if (result.isError()) {
164 result.throwException();
165 }
166 if (result.isOverflow()) {
167 expand();
168 }
169 retry = !result.isUnderflow();
170 }
171 this.charbuffer.compact();
172 offset += l;
173 remaining -= l;
174 }
175
176 boolean retry = true;
177 while (retry) {
178 CoderResult result = this.charencoder.flush(this.buffer);
179 if (result.isError()) {
180 result.throwException();
181 }
182 if (result.isOverflow()) {
183 expand();
184 }
185 retry = !result.isUnderflow();
186 }
187 }
188 writeCRLF();
189 }
190
191 public void writeLine(final String s) throws IOException {
192 if (s == null) {
193 return;
194 }
195 if (s.length() > 0) {
196 CharArrayBuffer tmp = new CharArrayBuffer(s.length());
197 tmp.append(s);
198 writeLine(tmp);
199 } else {
200 write(CRLF);
201 }
202 }
203
204 }