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