001// Copyright (C) 2002 by Jason Hunter <jhunter_AT_acm_DOT_org>.
002// All rights reserved.  Use of this class is limited.
003// Please see the LICENSE for more information.
004
005package com.oreilly.servlet.multipart;
006
007import java.io.*;
008
009/**
010 * Implements a renaming policy that adds increasing integers to the body of
011 * any file that collides.  For example, if foo.gif is being uploaded and a
012 * file by the same name already exists, this logic will rename the upload
013 * foo1.gif.  A second upload by the same name would be foo2.gif.
014 * Note that for safety the rename() method creates a zero-length file with
015 * the chosen name to act as a marker that the name is taken even before the
016 * upload starts writing the bytes.
017 * 
018 * @author Jason Hunter
019 * @version 1.1, 2002/11/05, making thread safe with createNewFile()
020 * @version 1.0, 2002/04/30, initial revision, thanks to Yoonjung Lee
021 *                           for this idea
022 */
023public class DefaultFileRenamePolicy implements FileRenamePolicy {
024  
025  // This method does not need to be synchronized because createNewFile()
026  // is atomic and used here to mark when a file name is chosen
027  public File rename(File f) {
028    if (createNewFile(f)) {
029      return f;
030    }
031    String name = f.getName();
032    String body = null;
033    String ext = null;
034
035    int dot = name.lastIndexOf(".");
036    if (dot != -1) {
037      body = name.substring(0, dot);
038      ext = name.substring(dot);  // includes "."
039    }
040    else {
041      body = name;
042      ext = "";
043    }
044
045    // Increase the count until an empty spot is found.
046    // Max out at 9999 to avoid an infinite loop caused by a persistent
047    // IOException, like when the destination dir becomes non-writable.
048    // We don't pass the exception up because our job is just to rename,
049    // and the caller will hit any IOException in normal processing.
050    int count = 0;
051    while (!createNewFile(f) && count < 9999) {
052      count++;
053      String newName = body + count + ext;
054      f = new File(f.getParent(), newName);
055    }
056
057    return f;
058  }
059
060  private boolean createNewFile(File f) {
061    try {
062      return f.createNewFile();
063    }
064    catch (IOException ignored) {
065      return false;
066    }
067  }
068}