1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.jboss.netty.handler.codec.http2;
17
18 import java.io.File;
19 import java.io.FileInputStream;
20 import java.io.FileOutputStream;
21 import java.io.IOException;
22 import java.io.InputStream;
23 import java.nio.ByteBuffer;
24 import java.nio.channels.FileChannel;
25 import java.nio.charset.Charset;
26
27 import org.jboss.netty.buffer.ChannelBuffer;
28 import org.jboss.netty.buffer.ChannelBuffers;
29
30
31
32
33
34
35
36
37
38
39 public abstract class AbstractDiskHttpData extends AbstractHttpData implements HttpData {
40
41 protected File file = null;
42
43 private boolean isRenamed = false;
44
45 private FileChannel fileChannel = null;
46
47 public AbstractDiskHttpData(String name, Charset charset, long size)
48 throws NullPointerException, IllegalArgumentException {
49 super(name, charset, size);
50 }
51
52
53
54
55
56 protected abstract String getDiskFilename();
57
58
59
60
61 protected abstract String getPrefix();
62
63
64
65
66 protected abstract String getBaseDirectory();
67
68
69
70
71 protected abstract String getPostfix();
72
73
74
75
76 protected abstract boolean deleteOnExit();
77
78
79
80
81
82
83 private File tempFile() throws IOException {
84 String newpostfix = null;
85 String diskFilename = getDiskFilename();
86 if (diskFilename != null) {
87 newpostfix = "_" + diskFilename;
88 } else {
89 newpostfix = getPostfix();
90 }
91 File tmpFile;
92 if (getBaseDirectory() == null) {
93
94 tmpFile = File.createTempFile(getPrefix(), newpostfix);
95 } else {
96 tmpFile = File.createTempFile(getPrefix(), newpostfix, new File(
97 getBaseDirectory()));
98 }
99 if (deleteOnExit()) {
100 tmpFile.deleteOnExit();
101 }
102 return tmpFile;
103 }
104
105 public void setContent(ChannelBuffer buffer) throws IOException {
106 if (buffer == null) {
107 throw new NullPointerException("buffer");
108 }
109 size = buffer.readableBytes();
110 if (definedSize > 0 && definedSize < size) {
111 throw new IOException("Out of size: " + size + " > " + definedSize);
112 }
113 if (file == null) {
114 file = tempFile();
115 }
116 if (buffer.readableBytes() == 0) {
117
118 file.createNewFile();
119 return;
120 }
121 FileOutputStream outputStream = new FileOutputStream(file);
122 FileChannel localfileChannel = outputStream.getChannel();
123 ByteBuffer byteBuffer = buffer.toByteBuffer();
124 int written = 0;
125 while (written < size) {
126 written += localfileChannel.write(byteBuffer);
127 }
128 buffer.readerIndex(buffer.readerIndex() + written);
129 localfileChannel.force(false);
130 localfileChannel.close();
131 completed = true;
132 }
133
134 public void addContent(ChannelBuffer buffer, boolean last)
135 throws IOException {
136 if (buffer != null) {
137 int localsize = buffer.readableBytes();
138 if (definedSize > 0 && definedSize < size + localsize) {
139 throw new IOException("Out of size: " + (size + localsize) +
140 " > " + definedSize);
141 }
142 ByteBuffer byteBuffer = buffer.toByteBuffer();
143 int written = 0;
144 if (file == null) {
145 file = tempFile();
146 }
147 if (fileChannel == null) {
148 FileOutputStream outputStream = new FileOutputStream(file);
149 fileChannel = outputStream.getChannel();
150 }
151 while (written < localsize) {
152 written += fileChannel.write(byteBuffer);
153 }
154 size += localsize;
155 buffer.readerIndex(buffer.readerIndex() + written);
156 }
157 if (last) {
158 if (file == null) {
159 file = tempFile();
160 }
161 if (fileChannel == null) {
162 FileOutputStream outputStream = new FileOutputStream(file);
163 fileChannel = outputStream.getChannel();
164 }
165 fileChannel.force(false);
166 fileChannel.close();
167 fileChannel = null;
168 completed = true;
169 } else {
170 if (buffer == null) {
171 throw new NullPointerException("buffer");
172 }
173 }
174 }
175
176 public void setContent(File file) throws IOException {
177 if (this.file != null) {
178 delete();
179 }
180 this.file = file;
181 size = file.length();
182 isRenamed = true;
183 completed = true;
184 }
185
186 public void setContent(InputStream inputStream) throws IOException {
187 if (inputStream == null) {
188 throw new NullPointerException("inputStream");
189 }
190 if (this.file != null) {
191 delete();
192 }
193 file = tempFile();
194 FileOutputStream outputStream = new FileOutputStream(file);
195 FileChannel localfileChannel = outputStream.getChannel();
196 byte[] bytes = new byte[4096*4];
197 ByteBuffer byteBuffer = ByteBuffer.wrap(bytes);
198 int read = inputStream.read(bytes);
199 int written = 0;
200 while (read > 0) {
201 byteBuffer.position(read).flip();
202 written += localfileChannel.write(byteBuffer);
203 read = inputStream.read(bytes);
204 }
205 localfileChannel.force(false);
206 localfileChannel.close();
207 size = written;
208 if (definedSize > 0 && definedSize < size) {
209 file.delete();
210 file = null;
211 throw new IOException("Out of size: " + size + " > " + definedSize);
212 }
213 isRenamed = true;
214 completed = true;
215 }
216
217 public void delete() {
218 if (! isRenamed) {
219 if (file != null) {
220 file.delete();
221 }
222 }
223 }
224
225 public byte[] get() throws IOException {
226 if (file == null) {
227 return new byte[0];
228 }
229 return readFrom(file);
230 }
231
232 public ChannelBuffer getChannelBuffer() throws IOException {
233 if (file == null) {
234 return ChannelBuffers.EMPTY_BUFFER;
235 }
236 byte[] array = readFrom(file);
237 return ChannelBuffers.wrappedBuffer(array);
238 }
239
240 public ChannelBuffer getChunk(int length) throws IOException {
241 if (file == null || length == 0) {
242 return ChannelBuffers.EMPTY_BUFFER;
243 }
244 if (fileChannel == null) {
245 FileInputStream inputStream = new FileInputStream(file);
246 fileChannel = inputStream.getChannel();
247 }
248 int read = 0;
249 ByteBuffer byteBuffer = ByteBuffer.allocate(length);
250 while (read < length) {
251 int readnow = fileChannel.read(byteBuffer);
252 if (readnow == -1) {
253 fileChannel.close();
254 fileChannel = null;
255 break;
256 } else {
257 read += readnow;
258 }
259 }
260 if (read == 0) {
261 return ChannelBuffers.EMPTY_BUFFER;
262 }
263 byteBuffer.flip();
264 ChannelBuffer buffer = ChannelBuffers.wrappedBuffer(byteBuffer);
265 buffer.readerIndex(0);
266 buffer.writerIndex(read);
267 return buffer;
268 }
269
270 public String getString() throws IOException {
271 return getString(HttpCodecUtil.DEFAULT_CHARSET);
272 }
273
274 public String getString(Charset encoding) throws IOException {
275 if (file == null) {
276 return "";
277 }
278 if (encoding == null) {
279 byte[] array = readFrom(file);
280 return new String(array, HttpCodecUtil.DEFAULT_CHARSET);
281 }
282 byte[] array = readFrom(file);
283 return new String(array, encoding);
284 }
285
286 public boolean isInMemory() {
287 return false;
288 }
289
290 public boolean renameTo(File dest) throws IOException {
291 if (dest == null) {
292 throw new NullPointerException("dest");
293 }
294 if (!file.renameTo(dest)) {
295
296 FileInputStream inputStream = new FileInputStream(file);
297 FileOutputStream outputStream = new FileOutputStream(dest);
298 FileChannel in = inputStream.getChannel();
299 FileChannel out = outputStream.getChannel();
300 long destsize = in.transferTo(0, size, out);
301 in.close();
302 out.close();
303 if (destsize == size) {
304 file.delete();
305 file = dest;
306 isRenamed = true;
307 return true;
308 } else {
309 dest.delete();
310 return false;
311 }
312 }
313 file = dest;
314 isRenamed = true;
315 return true;
316 }
317
318
319
320
321
322
323
324 private byte[] readFrom(File src) throws IOException {
325 long srcsize = src.length();
326 if (srcsize > Integer.MAX_VALUE) {
327 throw new IllegalArgumentException(
328 "File too big to be loaded in memory");
329 }
330 FileInputStream inputStream = new FileInputStream(src);
331 FileChannel fileChannel = inputStream.getChannel();
332 byte[] array = new byte[(int) srcsize];
333 ByteBuffer byteBuffer = ByteBuffer.wrap(array);
334 int read = 0;
335 while (read < srcsize) {
336 read += fileChannel.read(byteBuffer);
337 }
338 fileChannel.close();
339 return array;
340 }
341
342 public File getFile() throws IOException {
343 return file;
344 }
345
346 }