1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package io.netty.handler.codec.http.multipart;
17
18 import io.netty.buffer.ByteBuf;
19 import io.netty.buffer.CompositeByteBuf;
20 import io.netty.handler.codec.http.HttpConstants;
21
22 import java.io.File;
23 import java.io.FileInputStream;
24 import java.io.FileOutputStream;
25 import java.io.IOException;
26 import java.io.InputStream;
27 import java.nio.ByteBuffer;
28 import java.nio.channels.FileChannel;
29 import java.nio.charset.Charset;
30
31 import static io.netty.buffer.Unpooled.EMPTY_BUFFER;
32 import static io.netty.buffer.Unpooled.buffer;
33 import static io.netty.buffer.Unpooled.compositeBuffer;
34 import static io.netty.buffer.Unpooled.wrappedBuffer;
35
36
37
38
39 public abstract class AbstractMemoryHttpData extends AbstractHttpData {
40
41 private ByteBuf byteBuf;
42 private int chunkPosition;
43
44 protected AbstractMemoryHttpData(String name, Charset charset, long size) {
45 super(name, charset, size);
46 }
47
48 @Override
49 public void setContent(ByteBuf buffer) throws IOException {
50 if (buffer == null) {
51 throw new NullPointerException("buffer");
52 }
53 long localsize = buffer.readableBytes();
54 checkSize(localsize);
55 if (definedSize > 0 && definedSize < localsize) {
56 throw new IOException("Out of size: " + localsize + " > " +
57 definedSize);
58 }
59 if (byteBuf != null) {
60 byteBuf.release();
61 }
62 byteBuf = buffer;
63 size = localsize;
64 setCompleted();
65 }
66
67 @Override
68 public void setContent(InputStream inputStream) throws IOException {
69 if (inputStream == null) {
70 throw new NullPointerException("inputStream");
71 }
72 ByteBuf buffer = buffer();
73 byte[] bytes = new byte[4096 * 4];
74 int read = inputStream.read(bytes);
75 int written = 0;
76 while (read > 0) {
77 buffer.writeBytes(bytes, 0, read);
78 written += read;
79 checkSize(written);
80 read = inputStream.read(bytes);
81 }
82 size = written;
83 if (definedSize > 0 && definedSize < size) {
84 throw new IOException("Out of size: " + size + " > " + definedSize);
85 }
86 if (byteBuf != null) {
87 byteBuf.release();
88 }
89 byteBuf = buffer;
90 setCompleted();
91 }
92
93 @Override
94 public void addContent(ByteBuf buffer, boolean last)
95 throws IOException {
96 if (buffer != null) {
97 long localsize = buffer.readableBytes();
98 checkSize(size + localsize);
99 if (definedSize > 0 && definedSize < size + localsize) {
100 throw new IOException("Out of size: " + (size + localsize) +
101 " > " + definedSize);
102 }
103 size += localsize;
104 if (byteBuf == null) {
105 byteBuf = buffer;
106 } else if (byteBuf instanceof CompositeByteBuf) {
107 CompositeByteBuf cbb = (CompositeByteBuf) byteBuf;
108 cbb.addComponent(true, buffer);
109 } else {
110 CompositeByteBuf cbb = compositeBuffer(Integer.MAX_VALUE);
111 cbb.addComponents(true, byteBuf, buffer);
112 byteBuf = cbb;
113 }
114 }
115 if (last) {
116 setCompleted();
117 } else {
118 if (buffer == null) {
119 throw new NullPointerException("buffer");
120 }
121 }
122 }
123
124 @Override
125 public void setContent(File file) throws IOException {
126 if (file == null) {
127 throw new NullPointerException("file");
128 }
129 long newsize = file.length();
130 if (newsize > Integer.MAX_VALUE) {
131 throw new IllegalArgumentException(
132 "File too big to be loaded in memory");
133 }
134 checkSize(newsize);
135 FileInputStream inputStream = new FileInputStream(file);
136 FileChannel fileChannel = inputStream.getChannel();
137 byte[] array = new byte[(int) newsize];
138 ByteBuffer byteBuffer = ByteBuffer.wrap(array);
139 int read = 0;
140 while (read < newsize) {
141 read += fileChannel.read(byteBuffer);
142 }
143 fileChannel.close();
144 inputStream.close();
145 byteBuffer.flip();
146 if (byteBuf != null) {
147 byteBuf.release();
148 }
149 byteBuf = wrappedBuffer(Integer.MAX_VALUE, byteBuffer);
150 size = newsize;
151 setCompleted();
152 }
153
154 @Override
155 public void delete() {
156 if (byteBuf != null) {
157 byteBuf.release();
158 byteBuf = null;
159 }
160 }
161
162 @Override
163 public byte[] get() {
164 if (byteBuf == null) {
165 return EMPTY_BUFFER.array();
166 }
167 byte[] array = new byte[byteBuf.readableBytes()];
168 byteBuf.getBytes(byteBuf.readerIndex(), array);
169 return array;
170 }
171
172 @Override
173 public String getString() {
174 return getString(HttpConstants.DEFAULT_CHARSET);
175 }
176
177 @Override
178 public String getString(Charset encoding) {
179 if (byteBuf == null) {
180 return "";
181 }
182 if (encoding == null) {
183 encoding = HttpConstants.DEFAULT_CHARSET;
184 }
185 return byteBuf.toString(encoding);
186 }
187
188
189
190
191
192
193 @Override
194 public ByteBuf getByteBuf() {
195 return byteBuf;
196 }
197
198 @Override
199 public ByteBuf getChunk(int length) throws IOException {
200 if (byteBuf == null || length == 0 || byteBuf.readableBytes() == 0) {
201 chunkPosition = 0;
202 return EMPTY_BUFFER;
203 }
204 int sizeLeft = byteBuf.readableBytes() - chunkPosition;
205 if (sizeLeft == 0) {
206 chunkPosition = 0;
207 return EMPTY_BUFFER;
208 }
209 int sliceLength = length;
210 if (sizeLeft < length) {
211 sliceLength = sizeLeft;
212 }
213 ByteBuf chunk = byteBuf.retainedSlice(chunkPosition, sliceLength);
214 chunkPosition += sliceLength;
215 return chunk;
216 }
217
218 @Override
219 public boolean isInMemory() {
220 return true;
221 }
222
223 @Override
224 public boolean renameTo(File dest) throws IOException {
225 if (dest == null) {
226 throw new NullPointerException("dest");
227 }
228 if (byteBuf == null) {
229
230 if (!dest.createNewFile()) {
231 throw new IOException("file exists already: " + dest);
232 }
233 return true;
234 }
235 int length = byteBuf.readableBytes();
236 FileOutputStream outputStream = new FileOutputStream(dest);
237 FileChannel fileChannel = outputStream.getChannel();
238 int written = 0;
239 if (byteBuf.nioBufferCount() == 1) {
240 ByteBuffer byteBuffer = byteBuf.nioBuffer();
241 while (written < length) {
242 written += fileChannel.write(byteBuffer);
243 }
244 } else {
245 ByteBuffer[] byteBuffers = byteBuf.nioBuffers();
246 while (written < length) {
247 written += fileChannel.write(byteBuffers);
248 }
249 }
250
251 fileChannel.force(false);
252 fileChannel.close();
253 outputStream.close();
254 return written == length;
255 }
256
257 @Override
258 public File getFile() throws IOException {
259 throw new IOException("Not represented by a file");
260 }
261
262 @Override
263 public HttpData touch() {
264 return touch(null);
265 }
266
267 @Override
268 public HttpData touch(Object hint) {
269 if (byteBuf != null) {
270 byteBuf.touch(hint);
271 }
272 return this;
273 }
274 }