View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2009, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.rolling.helper;
15  
16  
17  import java.io.File;
18  import java.io.FileInputStream;
19  import java.io.FileOutputStream;
20  import java.io.IOException;
21  
22  import ch.qos.logback.core.rolling.RolloverFailure;
23  import ch.qos.logback.core.spi.ContextAwareBase;
24  import ch.qos.logback.core.util.FileUtil;
25  
26  
27  /**
28   * Utility class to help solving problems encountered while renaming files.
29   *
30   * @author Ceki Gulcu
31   */
32  public class RenameUtil extends ContextAwareBase {
33  
34  
35    /**
36     * A robust file renaming method which in case of failure falls back to
37     * renaming by copying. In case, the file to be renamed is open by another
38     * process, renaming by copying will succeed whereas regular renaming will
39     * fail. However, renaming by copying is much slower.
40     *
41     * @param from
42     * @param to
43     * @throws RolloverFailure
44     */
45    public void rename(String from, String to) throws RolloverFailure {
46      if (from.equals(to)) {
47        addWarn("From and to file are the same [" + from + "]. Skipping.");
48        return;
49      }
50      File fromFile = new File(from);
51  
52      if (fromFile.exists()) {
53        File toFile = new File(to);
54        createMissingTargetDirsIfNecessary(toFile);
55  
56        addInfo("Renaming file [" + fromFile + "] to [" + toFile + "]");
57  
58        boolean result = fromFile.renameTo(toFile);
59  
60        if (!result) {
61          addWarn("Failed to rename file [" + fromFile + "] to [" + toFile + "].");
62          addWarn("Attempting to rename by copying.");
63          renameByCopying(from, to);
64        }
65      } else {
66        throw new RolloverFailure("File [" + from + "] does not exist.");
67      }
68    }
69  
70    static final int BUF_SIZE = 32 * 1024;
71  
72    public void renameByCopying(String from, String to)
73            throws RolloverFailure {
74      try {
75        FileInputStream fis = new FileInputStream(from);
76        FileOutputStream fos = new FileOutputStream(to);
77        byte[] inbuf = new byte[BUF_SIZE];
78        int n;
79  
80        while ((n = fis.read(inbuf)) != -1) {
81          fos.write(inbuf, 0, n);
82        }
83  
84        fis.close();
85        fos.close();
86  
87        File fromFile = new File(from);
88  
89        if (!fromFile.delete()) {
90          addWarn("Could not delete " + from);
91        }
92      } catch (IOException ioe) {
93        addError("Failed to rename file by copying", ioe);
94        throw new RolloverFailure("Failed to rename file by copying");
95      }
96    }
97  
98    void createMissingTargetDirsIfNecessary(File toFile) throws RolloverFailure {
99      if (FileUtil.isParentDirectoryCreationRequired(toFile)) {
100       boolean result = FileUtil.createMissingParentDirectories(toFile);
101       if (!result) {
102         throw new RolloverFailure("Failed to create parent directories for ["
103                 + toFile.getAbsolutePath() + "]");
104       }
105     }
106   }
107 
108   @Override
109   public String toString() {
110     return "c.q.l.co.rolling.helper.RenameUtil";
111   }
112 }