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