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.codecs;
29
30 import java.io.IOException;
31 import java.nio.ByteBuffer;
32 import java.nio.channels.WritableByteChannel;
33
34 import org.apache.http.impl.io.HttpTransportMetricsImpl;
35 import org.apache.http.nio.ContentEncoder;
36 import org.apache.http.nio.reactor.SessionOutputBuffer;
37 import org.apache.http.util.Args;
38 import org.apache.http.util.Asserts;
39
40
41
42
43
44
45
46 public abstract class AbstractContentEncoder implements ContentEncoder {
47
48 protected final WritableByteChannel channel;
49 protected final SessionOutputBuffer buffer;
50 protected final HttpTransportMetricsImpl metrics;
51
52
53
54
55 protected boolean completed;
56
57
58
59
60
61
62
63
64
65 public AbstractContentEncoder(
66 final WritableByteChannel channel,
67 final SessionOutputBuffer buffer,
68 final HttpTransportMetricsImpl metrics) {
69 super();
70 Args.notNull(channel, "Channel");
71 Args.notNull(buffer, "Session input buffer");
72 Args.notNull(metrics, "Transport metrics");
73 this.buffer = buffer;
74 this.channel = channel;
75 this.metrics = metrics;
76 }
77
78 @Override
79 public boolean isCompleted() {
80 return this.completed;
81 }
82
83 @Override
84 public void complete() throws IOException {
85 this.completed = true;
86 }
87
88 protected void assertNotCompleted() {
89 Asserts.check(!this.completed, "Encoding process already completed");
90 }
91
92
93
94
95
96
97
98
99 protected int flushToChannel() throws IOException {
100 if (!this.buffer.hasData()) {
101 return 0;
102 }
103 final int bytesWritten = this.buffer.flush(this.channel);
104 if (bytesWritten > 0) {
105 this.metrics.incrementBytesTransferred(bytesWritten);
106 }
107 return bytesWritten;
108 }
109
110
111
112
113
114
115
116
117 protected int writeToChannel(final ByteBuffer src) throws IOException {
118 if (!src.hasRemaining()) {
119 return 0;
120 }
121 final int bytesWritten = this.channel.write(src);
122 if (bytesWritten > 0) {
123 this.metrics.incrementBytesTransferred(bytesWritten);
124 }
125 return bytesWritten;
126 }
127
128
129
130
131
132
133
134
135
136
137 protected int writeToChannel(final ByteBuffer src, final int limit) throws IOException {
138 return doWriteChunk(src, limit, true);
139 }
140
141
142
143
144
145
146
147
148
149
150 protected int writeToBuffer(final ByteBuffer src, final int limit) throws IOException {
151 return doWriteChunk(src, limit, false);
152 }
153
154 private int doWriteChunk(
155 final ByteBuffer src, final int chunk, final boolean direct) throws IOException {
156 final int bytesWritten;
157 if (src.remaining() > chunk) {
158 final int oldLimit = src.limit();
159 final int newLimit = oldLimit - (src.remaining() - chunk);
160 src.limit(newLimit);
161 bytesWritten = doWriteChunk(src, direct);
162 src.limit(oldLimit);
163 } else {
164 bytesWritten = doWriteChunk(src, direct);
165 }
166 return bytesWritten;
167 }
168
169 private int doWriteChunk(final ByteBuffer src, final boolean direct) throws IOException {
170 if (direct) {
171 final int bytesWritten = this.channel.write(src);
172 if (bytesWritten > 0) {
173 this.metrics.incrementBytesTransferred(bytesWritten);
174 }
175 return bytesWritten;
176 }
177 final int chunk = src.remaining();
178 this.buffer.write(src);
179 return chunk;
180 }
181
182 }