da5209bcf72464feb69a4110a5d7d6fe0bb46af3
[jalview.git] / src / jalview / io / BackupFiles.java
1 package jalview.io;
2
3 import jalview.bin.Cache;
4
5 import java.io.File;
6 import java.io.IOException;
7
8 public class BackupFiles
9 {
10
11   // labels for saved params in Cache and .jalview_properties
12   private static String NS = "BACKUPFILES";
13
14   public static String ENABLED = NS + "_ENABLED";
15
16   public static String SUFFIX = NS + "_SUFFIX";
17
18   public static String ROLL_MAX = NS + "_ROLL_MAX";
19
20   public static String SUFFIX_DIGITS = NS + "_SUFFIX_DIGITS";
21
22   protected static String NUM_PLACEHOLDER = "%n";
23
24   public static String REVERSE_ORDER = NS + "_REVERSE_ORDER";
25
26   private static String DEFAULT_TEMP_FILE = "jalview_temp_file_" + NS;
27
28   // file - File object to be backed up and then updated (written over)
29   private File file;
30
31   // enabled - default flag as to whether to do the backup file roll (if not
32   // defined in preferences)
33   private boolean enabled;
34
35   // defaultSuffix - default template to use to append to basename of file
36   private String suffix;
37
38   // defaultMax - default max number of backup files
39   private int max;
40
41   // defaultDigits - number of zero-led digits to use in the filename
42   private int digits;
43
44   // reverseOrder - set to true to make newest (latest) files lowest number
45   // (like rolled log files)
46   private boolean reverseOrder;
47
48   // temp saved file to become new saved file
49   private File tempFile;
50
51   public BackupFiles(String filename)
52   {
53     this(new File(filename));
54   }
55
56   // first time defaults for ENABLED, SUFFIX, ROLL_MAX, SUFFIX_DIGITS and
57   // REVERSE_ORDER
58   public BackupFiles(File file)
59   {
60     this(file, true, "-v" + NUM_PLACEHOLDER, 4, 3, false);
61   }
62
63   // set, get and rename temp file into place
64   public void setTempFile(File temp)
65   {
66     this.tempFile = temp;
67   }
68
69   public File getTempFile()
70   {
71     return tempFile;
72   }
73
74   public boolean renameTempFile()
75   {
76     return tempFile.renameTo(file);
77   }
78
79   public BackupFiles(File file, boolean defaultEnabled,
80           String defaultSuffix,
81           int defaultMax, int defaultDigits, boolean defaultReverseOrder)
82   {
83     this.file = file;
84     this.enabled = Cache.getDefault(ENABLED, defaultEnabled);
85     this.suffix = Cache.getDefault(SUFFIX, defaultSuffix);
86     this.max = Cache.getDefault(ROLL_MAX, defaultMax);
87     this.digits = Cache.getDefault(SUFFIX_DIGITS, defaultDigits);
88     this.reverseOrder = Cache.getDefault(REVERSE_ORDER,
89             defaultReverseOrder);
90     
91     // create a temp file to save new data in
92     File temp;
93     try
94     {
95       if (file != null)
96       {
97         String tempfilename = file.getName();
98         File tempdir = file.getParentFile();
99         temp = File.createTempFile(tempfilename, ".tmp", tempdir);
100       }
101       else
102       {
103         temp = File.createTempFile(DEFAULT_TEMP_FILE, ".tmp");
104         setTempFile(temp);
105       }
106     } catch (IOException e)
107     {
108       System.out.println(
109               "Could not create temp file to save into (IOException)");
110     } catch (Exception e)
111     {
112       System.out.println("Exception ctreating temp file for saving");
113     }
114
115   }
116
117   // roll the backupfiles
118   public boolean rollBackupFiles()
119   {
120
121     // file doesn't yet exist or backups are not enabled
122     if ((!file.exists()) || (!enabled) || (max < 1))
123     {
124       // nothing to do
125       return true;
126     }
127
128     // split filename up to insert suffix template in the right place. template
129     // and backupMax can be set in .jalview_properties
130     String dir = "";
131     File dirFile;
132     try
133     {
134       dirFile = file.getParentFile();
135       dir = dirFile.getCanonicalPath();
136     } catch (Exception e)
137     {
138       System.out.println(
139               "Could not get canonical path for file '" + file + "'");
140       return false;
141     }
142     String filename = file.getName();
143     String basename = filename;
144     String extension = "";
145     int dotcharpos = filename.lastIndexOf('.');
146     // don't split of filenames with the last '.' at the very beginning or
147     // very end of the filename
148     if ((dotcharpos > 0) && (dotcharpos < filename.length() - 1))
149     {
150       basename = filename.substring(0, dotcharpos);
151       extension = filename.substring(dotcharpos); // NOTE this includes the '.'
152     }
153
154     boolean ret = true;
155     // Create/move backups up one
156     String numString = null;
157     File lastfile = null;
158
159     if (reverseOrder)
160     {
161       // backup style numbering
162       for (int m = 0; m < max; m++)
163       {
164         int n = max - m;
165         numString = String.format("%0" + digits + "d", n);
166         String backupSuffix = suffix.replaceAll(NUM_PLACEHOLDER, numString);
167         String backupfilename = dir + File.separatorChar + basename
168                 + backupSuffix + extension;
169         File backupfile_n = new File(backupfilename);
170
171         if (!backupfile_n.exists())
172         {
173           lastfile = backupfile_n;
174           continue;
175         }
176
177         if (m == 0)
178         { // Move the max backup to /tmp instead of deleting (Just In
179           // Case)
180           String tmpfile = "tmp-" + backupfile_n.getName();
181           try
182           {
183             File tmpFile = File.createTempFile(tmpfile, ".tmp");
184             ret = ret && backupfile_n.renameTo(tmpFile);
185           } catch (IOException e)
186           {
187             System.out.println(
188                     "Could not create temp file '" + tmpfile + ".tmp'");
189           }
190         }
191         else
192         {
193           // Just In Case
194           if (lastfile != null)
195           {
196             ret = ret && backupfile_n.renameTo(lastfile);
197           }
198         }
199
200         lastfile = backupfile_n;
201       }
202
203       // now actually backup the important file!
204       ret = ret && file.renameTo(lastfile);
205     }
206     else
207     {
208       // version style numbering (with earliest file deletion if max files
209       // reached)
210
211       // find existing backup files
212       BackupFileFilter bff = new BackupFileFilter(basename, suffix, digits,
213               extension);
214       File[] backupFiles = dirFile.listFiles(bff);
215
216       
217     }
218
219     return ret;
220   }
221
222 }
223