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.io.BufferInfo;
37 import org.apache.http.nio.reactor.SessionOutputBuffer;
38 import org.apache.http.util.CharArrayBuffer;
39
40
41
42
43
44
45
46 @NotThreadSafe
47 public class ChunkEncoder extends AbstractContentEncoder {
48
49 private final CharArrayBuffer lineBuffer;
50
51 private final BufferInfo bufferinfo;
52
53 public ChunkEncoder(
54 final WritableByteChannel channel,
55 final SessionOutputBuffer buffer,
56 final HttpTransportMetricsImpl metrics) {
57 super(channel, buffer, metrics);
58 this.lineBuffer = new CharArrayBuffer(16);
59 if (buffer instanceof BufferInfo) {
60 this.bufferinfo = (BufferInfo) buffer;
61 } else {
62 this.bufferinfo = null;
63 }
64 }
65
66 public int write(final ByteBuffer src) throws IOException {
67 if (src == null) {
68 return 0;
69 }
70 assertNotCompleted();
71 int chunk = src.remaining();
72 if (chunk == 0) {
73 return 0;
74 }
75
76 long bytesWritten = this.buffer.flush(this.channel);
77 if (bytesWritten > 0) {
78 this.metrics.incrementBytesTransferred(bytesWritten);
79 }
80 int avail;
81 if (this.bufferinfo != null) {
82 avail = this.bufferinfo.available();
83 } else {
84 avail = 4096;
85 }
86
87
88
89
90 avail -= 12;
91 if (avail <= 0) {
92 return 0;
93 } else if (avail < chunk) {
94
95 chunk = avail;
96 this.lineBuffer.clear();
97 this.lineBuffer.append(Integer.toHexString(chunk));
98 this.buffer.writeLine(this.lineBuffer);
99 int oldlimit = src.limit();
100 src.limit(src.position() + chunk);
101 this.buffer.write(src);
102 src.limit(oldlimit);
103 } else {
104
105 this.lineBuffer.clear();
106 this.lineBuffer.append(Integer.toHexString(chunk));
107 this.buffer.writeLine(this.lineBuffer);
108 this.buffer.write(src);
109 }
110 this.lineBuffer.clear();
111 this.buffer.writeLine(this.lineBuffer);
112 return chunk;
113 }
114
115 @Override
116 public void complete() throws IOException {
117 assertNotCompleted();
118 this.lineBuffer.clear();
119 this.lineBuffer.append("0");
120 this.buffer.writeLine(this.lineBuffer);
121 this.lineBuffer.clear();
122 this.buffer.writeLine(this.lineBuffer);
123 this.completed = true;
124 }
125
126 @Override
127 public String toString() {
128 StringBuilder buffer = new StringBuilder();
129 buffer.append("[chunk-coded; completed: ");
130 buffer.append(this.completed);
131 buffer.append("]");
132 return buffer.toString();
133 }
134
135 }