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