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