| Classes in this File | Line Coverage | Branch Coverage | Complexity | ||||
| DiskFileItem |
|
| 2.4615384615384617;2.462 |
| 1 | /* | |
| 2 | * Licensed to the Apache Software Foundation (ASF) under one or more | |
| 3 | * contributor license agreements. See the NOTICE file distributed with | |
| 4 | * this work for additional information regarding copyright ownership. | |
| 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 | |
| 6 | * (the "License"); you may not use this file except in compliance with | |
| 7 | * the License. You may obtain a copy of the License at | |
| 8 | * | |
| 9 | * http://www.apache.org/licenses/LICENSE-2.0 | |
| 10 | * | |
| 11 | * Unless required by applicable law or agreed to in writing, software | |
| 12 | * distributed under the License is distributed on an "AS IS" BASIS, | |
| 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 14 | * See the License for the specific language governing permissions and | |
| 15 | * limitations under the License. | |
| 16 | */ | |
| 17 | package org.apache.commons.fileupload.disk; | |
| 18 | ||
| 19 | import static java.lang.String.format; | |
| 20 | ||
| 21 | import java.io.ByteArrayInputStream; | |
| 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.io.OutputStream; | |
| 28 | import java.io.UnsupportedEncodingException; | |
| 29 | import java.util.Map; | |
| 30 | import java.util.UUID; | |
| 31 | import java.util.concurrent.atomic.AtomicInteger; | |
| 32 | ||
| 33 | import org.apache.commons.fileupload.FileItem; | |
| 34 | import org.apache.commons.fileupload.FileItemHeaders; | |
| 35 | import org.apache.commons.fileupload.FileUploadException; | |
| 36 | import org.apache.commons.fileupload.ParameterParser; | |
| 37 | import org.apache.commons.fileupload.util.Streams; | |
| 38 | import org.apache.commons.io.FileUtils; | |
| 39 | import org.apache.commons.io.IOUtils; | |
| 40 | import org.apache.commons.io.output.DeferredFileOutputStream; | |
| 41 | ||
| 42 | /** | |
| 43 | * <p> The default implementation of the | |
| 44 | * {@link org.apache.commons.fileupload.FileItem FileItem} interface. | |
| 45 | * | |
| 46 | * <p> After retrieving an instance of this class from a {@link | |
| 47 | * DiskFileItemFactory} instance (see | |
| 48 | * {@link org.apache.commons.fileupload.servlet.ServletFileUpload | |
| 49 | * #parseRequest(javax.servlet.http.HttpServletRequest)}), you may | |
| 50 | * either request all contents of file at once using {@link #get()} or | |
| 51 | * request an {@link java.io.InputStream InputStream} with | |
| 52 | * {@link #getInputStream()} and process the file without attempting to load | |
| 53 | * it into memory, which may come handy with large files. | |
| 54 | * | |
| 55 | * <p>Temporary files, which are created for file items, should be | |
| 56 | * deleted later on. The best way to do this is using a | |
| 57 | * {@link org.apache.commons.io.FileCleaningTracker}, which you can set on the | |
| 58 | * {@link DiskFileItemFactory}. However, if you do use such a tracker, | |
| 59 | * then you must consider the following: Temporary files are automatically | |
| 60 | * deleted as soon as they are no longer needed. (More precisely, when the | |
| 61 | * corresponding instance of {@link java.io.File} is garbage collected.) | |
| 62 | * This is done by the so-called reaper thread, which is started and stopped | |
| 63 | * automatically by the {@link org.apache.commons.io.FileCleaningTracker} when | |
| 64 | * there are files to be tracked. | |
| 65 | * It might make sense to terminate that thread, for example, if | |
| 66 | * your web application ends. See the section on "Resource cleanup" | |
| 67 | * in the users guide of commons-fileupload.</p> | |
| 68 | * | |
| 69 | * @since FileUpload 1.1 | |
| 70 | */ | |
| 71 | public class DiskFileItem | |
| 72 | implements FileItem { | |
| 73 | ||
| 74 | // ----------------------------------------------------- Manifest constants | |
| 75 | ||
| 76 | /** | |
| 77 | * Default content charset to be used when no explicit charset | |
| 78 | * parameter is provided by the sender. Media subtypes of the | |
| 79 | * "text" type are defined to have a default charset value of | |
| 80 | * "ISO-8859-1" when received via HTTP. | |
| 81 | */ | |
| 82 | public static final String DEFAULT_CHARSET = "ISO-8859-1"; | |
| 83 | ||
| 84 | // ----------------------------------------------------------- Data members | |
| 85 | ||
| 86 | /** | |
| 87 | * UID used in unique file name generation. | |
| 88 | */ | |
| 89 | private static final String UID = | |
| 90 | 1 | UUID.randomUUID().toString().replace('-', '_'); |
| 91 | ||
| 92 | /** | |
| 93 | * Counter used in unique identifier generation. | |
| 94 | */ | |
| 95 | 1 | private static final AtomicInteger COUNTER = new AtomicInteger(0); |
| 96 | ||
| 97 | /** | |
| 98 | * The name of the form field as provided by the browser. | |
| 99 | */ | |
| 100 | private String fieldName; | |
| 101 | ||
| 102 | /** | |
| 103 | * The content type passed by the browser, or <code>null</code> if | |
| 104 | * not defined. | |
| 105 | */ | |
| 106 | private final String contentType; | |
| 107 | ||
| 108 | /** | |
| 109 | * Whether or not this item is a simple form field. | |
| 110 | */ | |
| 111 | private boolean isFormField; | |
| 112 | ||
| 113 | /** | |
| 114 | * The original filename in the user's filesystem. | |
| 115 | */ | |
| 116 | private final String fileName; | |
| 117 | ||
| 118 | /** | |
| 119 | * The size of the item, in bytes. This is used to cache the size when a | |
| 120 | * file item is moved from its original location. | |
| 121 | */ | |
| 122 | 2174 | private long size = -1; |
| 123 | ||
| 124 | ||
| 125 | /** | |
| 126 | * The threshold above which uploads will be stored on disk. | |
| 127 | */ | |
| 128 | private final int sizeThreshold; | |
| 129 | ||
| 130 | /** | |
| 131 | * The directory in which uploaded files will be stored, if stored on disk. | |
| 132 | */ | |
| 133 | private final File repository; | |
| 134 | ||
| 135 | /** | |
| 136 | * Cached contents of the file. | |
| 137 | */ | |
| 138 | private byte[] cachedContent; | |
| 139 | ||
| 140 | /** | |
| 141 | * Output stream for this item. | |
| 142 | */ | |
| 143 | private transient DeferredFileOutputStream dfos; | |
| 144 | ||
| 145 | /** | |
| 146 | * The temporary file to use. | |
| 147 | */ | |
| 148 | private transient File tempFile; | |
| 149 | ||
| 150 | /** | |
| 151 | * The file items headers. | |
| 152 | */ | |
| 153 | private FileItemHeaders headers; | |
| 154 | ||
| 155 | /** | |
| 156 | * Default content charset to be used when no explicit charset | |
| 157 | * parameter is provided by the sender. | |
| 158 | */ | |
| 159 | 2174 | private String defaultCharset = DEFAULT_CHARSET; |
| 160 | ||
| 161 | // ----------------------------------------------------------- Constructors | |
| 162 | ||
| 163 | /** | |
| 164 | * Constructs a new <code>DiskFileItem</code> instance. | |
| 165 | * | |
| 166 | * @param fieldName The name of the form field. | |
| 167 | * @param contentType The content type passed by the browser or | |
| 168 | * <code>null</code> if not specified. | |
| 169 | * @param isFormField Whether or not this item is a plain form field, as | |
| 170 | * opposed to a file upload. | |
| 171 | * @param fileName The original filename in the user's filesystem, or | |
| 172 | * <code>null</code> if not specified. | |
| 173 | * @param sizeThreshold The threshold, in bytes, below which items will be | |
| 174 | * retained in memory and above which they will be | |
| 175 | * stored as a file. | |
| 176 | * @param repository The data repository, which is the directory in | |
| 177 | * which files will be created, should the item size | |
| 178 | * exceed the threshold. | |
| 179 | */ | |
| 180 | public DiskFileItem(String fieldName, | |
| 181 | String contentType, boolean isFormField, String fileName, | |
| 182 | 2174 | int sizeThreshold, File repository) { |
| 183 | 2174 | this.fieldName = fieldName; |
| 184 | 2174 | this.contentType = contentType; |
| 185 | 2174 | this.isFormField = isFormField; |
| 186 | 2174 | this.fileName = fileName; |
| 187 | 2174 | this.sizeThreshold = sizeThreshold; |
| 188 | 2174 | this.repository = repository; |
| 189 | 2174 | } |
| 190 | ||
| 191 | // ------------------------------- Methods from javax.activation.DataSource | |
| 192 | ||
| 193 | /** | |
| 194 | * Returns an {@link java.io.InputStream InputStream} that can be | |
| 195 | * used to retrieve the contents of the file. | |
| 196 | * | |
| 197 | * @return An {@link java.io.InputStream InputStream} that can be | |
| 198 | * used to retrieve the contents of the file. | |
| 199 | * | |
| 200 | * @throws IOException if an error occurs. | |
| 201 | */ | |
| 202 | @Override | |
| 203 | public InputStream getInputStream() | |
| 204 | throws IOException { | |
| 205 | 0 | if (!isInMemory()) { |
| 206 | 0 | return new FileInputStream(dfos.getFile()); |
| 207 | } | |
| 208 | ||
| 209 | 0 | if (cachedContent == null) { |
| 210 | 0 | cachedContent = dfos.getData(); |
| 211 | } | |
| 212 | 0 | return new ByteArrayInputStream(cachedContent); |
| 213 | } | |
| 214 | ||
| 215 | /** | |
| 216 | * Returns the content type passed by the agent or <code>null</code> if | |
| 217 | * not defined. | |
| 218 | * | |
| 219 | * @return The content type passed by the agent or <code>null</code> if | |
| 220 | * not defined. | |
| 221 | */ | |
| 222 | @Override | |
| 223 | public String getContentType() { | |
| 224 | 43 | return contentType; |
| 225 | } | |
| 226 | ||
| 227 | /** | |
| 228 | * Returns the content charset passed by the agent or <code>null</code> if | |
| 229 | * not defined. | |
| 230 | * | |
| 231 | * @return The content charset passed by the agent or <code>null</code> if | |
| 232 | * not defined. | |
| 233 | */ | |
| 234 | public String getCharSet() { | |
| 235 | 35 | ParameterParser parser = new ParameterParser(); |
| 236 | 35 | parser.setLowerCaseNames(true); |
| 237 | // Parameter parser can handle null input | |
| 238 | 35 | Map<String, String> params = parser.parse(getContentType(), ';'); |
| 239 | 35 | return params.get("charset"); |
| 240 | } | |
| 241 | ||
| 242 | /** | |
| 243 | * Returns the original filename in the client's filesystem. | |
| 244 | * | |
| 245 | * @return The original filename in the client's filesystem. | |
| 246 | * @throws org.apache.commons.fileupload.InvalidFileNameException The file name contains a NUL character, | |
| 247 | * which might be an indicator of a security attack. If you intend to | |
| 248 | * use the file name anyways, catch the exception and use | |
| 249 | * {@link org.apache.commons.fileupload.InvalidFileNameException#getName()}. | |
| 250 | */ | |
| 251 | @Override | |
| 252 | public String getName() { | |
| 253 | 19 | return Streams.checkFileName(fileName); |
| 254 | } | |
| 255 | ||
| 256 | // ------------------------------------------------------- FileItem methods | |
| 257 | ||
| 258 | /** | |
| 259 | * Provides a hint as to whether or not the file contents will be read | |
| 260 | * from memory. | |
| 261 | * | |
| 262 | * @return <code>true</code> if the file contents will be read | |
| 263 | * from memory; <code>false</code> otherwise. | |
| 264 | */ | |
| 265 | @Override | |
| 266 | public boolean isInMemory() { | |
| 267 | 2432 | if (cachedContent != null) { |
| 268 | 2 | return true; |
| 269 | } | |
| 270 | 2430 | return dfos.isInMemory(); |
| 271 | } | |
| 272 | ||
| 273 | /** | |
| 274 | * Returns the size of the file. | |
| 275 | * | |
| 276 | * @return The size of the file, in bytes. | |
| 277 | */ | |
| 278 | @Override | |
| 279 | public long getSize() { | |
| 280 | 536 | if (size >= 0) { |
| 281 | 0 | return size; |
| 282 | 536 | } else if (cachedContent != null) { |
| 283 | 0 | return cachedContent.length; |
| 284 | 536 | } else if (dfos.isInMemory()) { |
| 285 | 4 | return dfos.getData().length; |
| 286 | } else { | |
| 287 | 532 | return dfos.getFile().length(); |
| 288 | } | |
| 289 | } | |
| 290 | ||
| 291 | /** | |
| 292 | * Returns the contents of the file as an array of bytes. If the | |
| 293 | * contents of the file were not yet cached in memory, they will be | |
| 294 | * loaded from the disk storage and cached. | |
| 295 | * | |
| 296 | * @return The contents of the file as an array of bytes | |
| 297 | * or {@code null} if the data cannot be read | |
| 298 | */ | |
| 299 | @Override | |
| 300 | public byte[] get() { | |
| 301 | 1451 | if (isInMemory()) { |
| 302 | 922 | if (cachedContent == null && dfos != null) { |
| 303 | 920 | cachedContent = dfos.getData(); |
| 304 | } | |
| 305 | 922 | return cachedContent; |
| 306 | } | |
| 307 | ||
| 308 | 529 | byte[] fileData = new byte[(int) getSize()]; |
| 309 | 529 | InputStream fis = null; |
| 310 | ||
| 311 | try { | |
| 312 | 529 | fis = new FileInputStream(dfos.getFile()); |
| 313 | 529 | IOUtils.readFully(fis, fileData); |
| 314 | 0 | } catch (IOException e) { |
| 315 | 0 | fileData = null; |
| 316 | } finally { | |
| 317 | 529 | IOUtils.closeQuietly(fis); |
| 318 | 529 | } |
| 319 | ||
| 320 | 529 | return fileData; |
| 321 | } | |
| 322 | ||
| 323 | /** | |
| 324 | * Returns the contents of the file as a String, using the specified | |
| 325 | * encoding. This method uses {@link #get()} to retrieve the | |
| 326 | * contents of the file. | |
| 327 | * | |
| 328 | * @param charset The charset to use. | |
| 329 | * | |
| 330 | * @return The contents of the file, as a string. | |
| 331 | * | |
| 332 | * @throws UnsupportedEncodingException if the requested character | |
| 333 | * encoding is not available. | |
| 334 | */ | |
| 335 | @Override | |
| 336 | public String getString(final String charset) | |
| 337 | throws UnsupportedEncodingException { | |
| 338 | 0 | return new String(get(), charset); |
| 339 | } | |
| 340 | ||
| 341 | /** | |
| 342 | * Returns the contents of the file as a String, using the default | |
| 343 | * character encoding. This method uses {@link #get()} to retrieve the | |
| 344 | * contents of the file. | |
| 345 | * | |
| 346 | * <b>TODO</b> Consider making this method throw UnsupportedEncodingException. | |
| 347 | * | |
| 348 | * @return The contents of the file, as a string. | |
| 349 | */ | |
| 350 | @Override | |
| 351 | public String getString() { | |
| 352 | 35 | byte[] rawdata = get(); |
| 353 | 35 | String charset = getCharSet(); |
| 354 | 35 | if (charset == null) { |
| 355 | 35 | charset = defaultCharset; |
| 356 | } | |
| 357 | try { | |
| 358 | 35 | return new String(rawdata, charset); |
| 359 | 0 | } catch (UnsupportedEncodingException e) { |
| 360 | 0 | return new String(rawdata); |
| 361 | } | |
| 362 | } | |
| 363 | ||
| 364 | /** | |
| 365 | * A convenience method to write an uploaded item to disk. The client code | |
| 366 | * is not concerned with whether or not the item is stored in memory, or on | |
| 367 | * disk in a temporary location. They just want to write the uploaded item | |
| 368 | * to a file. | |
| 369 | * <p> | |
| 370 | * This implementation first attempts to rename the uploaded item to the | |
| 371 | * specified destination file, if the item was originally written to disk. | |
| 372 | * Otherwise, the data will be copied to the specified file. | |
| 373 | * <p> | |
| 374 | * This method is only guaranteed to work <em>once</em>, the first time it | |
| 375 | * is invoked for a particular item. This is because, in the event that the | |
| 376 | * method renames a temporary file, that file will no longer be available | |
| 377 | * to copy or rename again at a later time. | |
| 378 | * | |
| 379 | * @param file The <code>File</code> into which the uploaded item should | |
| 380 | * be stored. | |
| 381 | * | |
| 382 | * @throws Exception if an error occurs. | |
| 383 | */ | |
| 384 | @Override | |
| 385 | public void write(File file) throws Exception { | |
| 386 | 0 | if (isInMemory()) { |
| 387 | 0 | FileOutputStream fout = null; |
| 388 | try { | |
| 389 | 0 | fout = new FileOutputStream(file); |
| 390 | 0 | fout.write(get()); |
| 391 | 0 | fout.close(); |
| 392 | } finally { | |
| 393 | 0 | IOUtils.closeQuietly(fout); |
| 394 | 0 | } |
| 395 | 0 | } else { |
| 396 | 0 | File outputFile = getStoreLocation(); |
| 397 | 0 | if (outputFile != null) { |
| 398 | // Save the length of the file | |
| 399 | 0 | size = outputFile.length(); |
| 400 | /* | |
| 401 | * The uploaded file is being stored on disk | |
| 402 | * in a temporary location so move it to the | |
| 403 | * desired file. | |
| 404 | */ | |
| 405 | 0 | FileUtils.moveFile(outputFile, file); |
| 406 | } else { | |
| 407 | /* | |
| 408 | * For whatever reason we cannot write the | |
| 409 | * file to disk. | |
| 410 | */ | |
| 411 | 0 | throw new FileUploadException( |
| 412 | "Cannot write uploaded file to disk!"); | |
| 413 | } | |
| 414 | } | |
| 415 | 0 | } |
| 416 | ||
| 417 | /** | |
| 418 | * Deletes the underlying storage for a file item, including deleting any | |
| 419 | * associated temporary disk file. Although this storage will be deleted | |
| 420 | * automatically when the <code>FileItem</code> instance is garbage | |
| 421 | * collected, this method can be used to ensure that this is done at an | |
| 422 | * earlier time, thus preserving system resources. | |
| 423 | */ | |
| 424 | @Override | |
| 425 | public void delete() { | |
| 426 | 707 | cachedContent = null; |
| 427 | 707 | File outputFile = getStoreLocation(); |
| 428 | 707 | if (outputFile != null && !isInMemory() && outputFile.exists()) { |
| 429 | 265 | outputFile.delete(); |
| 430 | } | |
| 431 | 707 | } |
| 432 | ||
| 433 | /** | |
| 434 | * Returns the name of the field in the multipart form corresponding to | |
| 435 | * this file item. | |
| 436 | * | |
| 437 | * @return The name of the form field. | |
| 438 | * | |
| 439 | * @see #setFieldName(java.lang.String) | |
| 440 | * | |
| 441 | */ | |
| 442 | @Override | |
| 443 | public String getFieldName() { | |
| 444 | 1445 | return fieldName; |
| 445 | } | |
| 446 | ||
| 447 | /** | |
| 448 | * Sets the field name used to reference this file item. | |
| 449 | * | |
| 450 | * @param fieldName The name of the form field. | |
| 451 | * | |
| 452 | * @see #getFieldName() | |
| 453 | * | |
| 454 | */ | |
| 455 | @Override | |
| 456 | public void setFieldName(String fieldName) { | |
| 457 | 0 | this.fieldName = fieldName; |
| 458 | 0 | } |
| 459 | ||
| 460 | /** | |
| 461 | * Determines whether or not a <code>FileItem</code> instance represents | |
| 462 | * a simple form field. | |
| 463 | * | |
| 464 | * @return <code>true</code> if the instance represents a simple form | |
| 465 | * field; <code>false</code> if it represents an uploaded file. | |
| 466 | * | |
| 467 | * @see #setFormField(boolean) | |
| 468 | * | |
| 469 | */ | |
| 470 | @Override | |
| 471 | public boolean isFormField() { | |
| 472 | 32 | return isFormField; |
| 473 | } | |
| 474 | ||
| 475 | /** | |
| 476 | * Specifies whether or not a <code>FileItem</code> instance represents | |
| 477 | * a simple form field. | |
| 478 | * | |
| 479 | * @param state <code>true</code> if the instance represents a simple form | |
| 480 | * field; <code>false</code> if it represents an uploaded file. | |
| 481 | * | |
| 482 | * @see #isFormField() | |
| 483 | * | |
| 484 | */ | |
| 485 | @Override | |
| 486 | public void setFormField(boolean state) { | |
| 487 | 0 | isFormField = state; |
| 488 | 0 | } |
| 489 | ||
| 490 | /** | |
| 491 | * Returns an {@link java.io.OutputStream OutputStream} that can | |
| 492 | * be used for storing the contents of the file. | |
| 493 | * | |
| 494 | * @return An {@link java.io.OutputStream OutputStream} that can be used | |
| 495 | * for storing the contents of the file. | |
| 496 | * | |
| 497 | * @throws IOException if an error occurs. | |
| 498 | */ | |
| 499 | @Override | |
| 500 | public OutputStream getOutputStream() | |
| 501 | throws IOException { | |
| 502 | 2172 | if (dfos == null) { |
| 503 | 2172 | File outputFile = getTempFile(); |
| 504 | 2172 | dfos = new DeferredFileOutputStream(sizeThreshold, outputFile); |
| 505 | } | |
| 506 | 2172 | return dfos; |
| 507 | } | |
| 508 | ||
| 509 | // --------------------------------------------------------- Public methods | |
| 510 | ||
| 511 | /** | |
| 512 | * Returns the {@link java.io.File} object for the <code>FileItem</code>'s | |
| 513 | * data's temporary location on the disk. Note that for | |
| 514 | * <code>FileItem</code>s that have their data stored in memory, | |
| 515 | * this method will return <code>null</code>. When handling large | |
| 516 | * files, you can use {@link java.io.File#renameTo(java.io.File)} to | |
| 517 | * move the file to new location without copying the data, if the | |
| 518 | * source and destination locations reside within the same logical | |
| 519 | * volume. | |
| 520 | * | |
| 521 | * @return The data file, or <code>null</code> if the data is stored in | |
| 522 | * memory. | |
| 523 | */ | |
| 524 | public File getStoreLocation() { | |
| 525 | 709 | if (dfos == null) { |
| 526 | 0 | return null; |
| 527 | } | |
| 528 | 709 | if (isInMemory()) { |
| 529 | 442 | return null; |
| 530 | } | |
| 531 | 267 | return dfos.getFile(); |
| 532 | } | |
| 533 | ||
| 534 | // ------------------------------------------------------ Protected methods | |
| 535 | ||
| 536 | /** | |
| 537 | * Removes the file contents from the temporary storage. | |
| 538 | */ | |
| 539 | @Override | |
| 540 | protected void finalize() { | |
| 541 | 1417 | if (dfos == null || dfos.isInMemory()) { |
| 542 | 892 | return; |
| 543 | } | |
| 544 | 525 | File outputFile = dfos.getFile(); |
| 545 | ||
| 546 | 525 | if (outputFile != null && outputFile.exists()) { |
| 547 | 262 | outputFile.delete(); |
| 548 | } | |
| 549 | 525 | } |
| 550 | ||
| 551 | /** | |
| 552 | * Creates and returns a {@link java.io.File File} representing a uniquely | |
| 553 | * named temporary file in the configured repository path. The lifetime of | |
| 554 | * the file is tied to the lifetime of the <code>FileItem</code> instance; | |
| 555 | * the file will be deleted when the instance is garbage collected. | |
| 556 | * <p> | |
| 557 | * <b>Note: Subclasses that override this method must ensure that they return the | |
| 558 | * same File each time.</b> | |
| 559 | * | |
| 560 | * @return The {@link java.io.File File} to be used for temporary storage. | |
| 561 | */ | |
| 562 | protected File getTempFile() { | |
| 563 | 2172 | if (tempFile == null) { |
| 564 | 2172 | File tempDir = repository; |
| 565 | 2172 | if (tempDir == null) { |
| 566 | 2165 | tempDir = new File(System.getProperty("java.io.tmpdir")); |
| 567 | } | |
| 568 | ||
| 569 | 2172 | String tempFileName = format("upload_%s_%s.tmp", UID, getUniqueId()); |
| 570 | ||
| 571 | 2172 | tempFile = new File(tempDir, tempFileName); |
| 572 | } | |
| 573 | 2172 | return tempFile; |
| 574 | } | |
| 575 | ||
| 576 | // -------------------------------------------------------- Private methods | |
| 577 | ||
| 578 | /** | |
| 579 | * Returns an identifier that is unique within the class loader used to | |
| 580 | * load this class, but does not have random-like appearance. | |
| 581 | * | |
| 582 | * @return A String with the non-random looking instance identifier. | |
| 583 | */ | |
| 584 | private static String getUniqueId() { | |
| 585 | 2172 | final int limit = 100000000; |
| 586 | 2172 | int current = COUNTER.getAndIncrement(); |
| 587 | 2172 | String id = Integer.toString(current); |
| 588 | ||
| 589 | // If you manage to get more than 100 million of ids, you'll | |
| 590 | // start getting ids longer than 8 characters. | |
| 591 | 2172 | if (current < limit) { |
| 592 | 2172 | id = ("00000000" + id).substring(id.length()); |
| 593 | } | |
| 594 | 2172 | return id; |
| 595 | } | |
| 596 | ||
| 597 | /** | |
| 598 | * Returns a string representation of this object. | |
| 599 | * | |
| 600 | * @return a string representation of this object. | |
| 601 | */ | |
| 602 | @Override | |
| 603 | public String toString() { | |
| 604 | 0 | return format("name=%s, StoreLocation=%s, size=%s bytes, isFormField=%s, FieldName=%s", |
| 605 | 0 | getName(), getStoreLocation(), Long.valueOf(getSize()), |
| 606 | 0 | Boolean.valueOf(isFormField()), getFieldName()); |
| 607 | } | |
| 608 | ||
| 609 | /** | |
| 610 | * Returns the file item headers. | |
| 611 | * @return The file items headers. | |
| 612 | */ | |
| 613 | @Override | |
| 614 | public FileItemHeaders getHeaders() { | |
| 615 | 32 | return headers; |
| 616 | } | |
| 617 | ||
| 618 | /** | |
| 619 | * Sets the file item headers. | |
| 620 | * @param pHeaders The file items headers. | |
| 621 | */ | |
| 622 | @Override | |
| 623 | public void setHeaders(FileItemHeaders pHeaders) { | |
| 624 | 2160 | headers = pHeaders; |
| 625 | 2160 | } |
| 626 | ||
| 627 | /** | |
| 628 | * Returns the default charset for use when no explicit charset | |
| 629 | * parameter is provided by the sender. | |
| 630 | * @return the default charset | |
| 631 | */ | |
| 632 | public String getDefaultCharset() { | |
| 633 | 0 | return defaultCharset; |
| 634 | } | |
| 635 | ||
| 636 | /** | |
| 637 | * Sets the default charset for use when no explicit charset | |
| 638 | * parameter is provided by the sender. | |
| 639 | * @param charset the default charset | |
| 640 | */ | |
| 641 | public void setDefaultCharset(String charset) { | |
| 642 | 2169 | defaultCharset = charset; |
| 643 | 2169 | } |
| 644 | } |