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