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     for (int m = 0; m < max; m++)
156     {
157       int n = reverseOrder ? max - m : m + 1;
158       numString = String.format("%0" + digits + "d", n);
159       String backupSuffix = suffix.replaceAll("%n", numString);
160       String backupfilename = dir + File.separatorChar + basename
161               + backupSuffix + extension;
162       File backupfile_n = new File(backupfilename);
163
164       if (!backupfile_n.exists())
165       {
166         lastfile = backupfile_n;
167         continue;
168       }
169
170       if (m == 0)
171       { // Move the max backup to /tmp instead of deleting (Just In
172         // Case)
173         String tmpfile = "tmp-" + backupfile_n.getName();
174         try
175         {
176           File tmpFile = File.createTempFile(tmpfile, ".tmp");
177           ret = ret && backupfile_n.renameTo(tmpFile);
178         } catch (IOException e)
179         {
180           System.out.println(
181                   "Could not create temp file '" + tmpfile + ".tmp'");
182         }
183       }
184       else
185       {
186         // Just In Case
187         if (lastfile != null)
188         {
189           ret = ret && backupfile_n.renameTo(lastfile);
190         }
191       }
192
193       lastfile = backupfile_n;
194     }
195
196     // now actually backup the important file!
197     ret = ret && file.renameTo(lastfile);
198
199     return ret;
200   }
201
202 }