1 package SnowMailClient.utils.storage; 2 3 import SnowMailClient.SnowMailClientApp; 4 import snow.utils.gui.*; 5 import snow.Language.Language; 6 import snow.utils.storage.*; 7 import java.util.*; 8 import java.util.zip.*; 9 import java.io.*; 10 import javax.swing.*; 11 import java.text.*; 12 13 16 public final class Backup implements Vectorizable 17 { 18 long lastBackup = 0; 19 long minTimeBetweenTwoBackups = 1000*60*5; private String destinationBackupFolder = ""; 21 boolean isAutomaticBackupEnabled = true; 22 23 public Backup() 24 { 25 if(System.getProperty("os.name", "Windows").indexOf("Windows")>0) 26 { 27 destinationBackupFolder = "c:/SnowMailBackup/"; 28 } 29 else 30 { 31 destinationBackupFolder = System.getProperty("user.home",".") 33 + File.pathSeparator + "SnowMailBackup" + File.pathSeparator; 34 } 35 } 37 public String getBackupDestinationDirectory() 38 { 39 return destinationBackupFolder; 40 } 41 42 public void setBackupDestination(String destinationBackupFolder) 43 { 44 this.destinationBackupFolder = destinationBackupFolder; 45 } 46 47 public boolean isAutomaticBackupEnabled() 48 { 49 return isAutomaticBackupEnabled; 50 } 51 52 public void setIsAutomaticBackupEnabled(boolean is) 53 { 54 isAutomaticBackupEnabled = is; 55 } 56 57 public synchronized void checkDoBackup() 58 { 59 long now = new Date().getTime(); 60 if(isAutomaticBackupEnabled && (now-lastBackup > minTimeBetweenTwoBackups)) 61 { 62 doBackupNow(); 63 } 64 else 65 { 66 System.out.println("No backup to do, last was made = "+new Date(lastBackup)); 67 } 68 } 69 70 71 72 public synchronized void doBackupNow() 73 { 74 if( SwingUtilities.isEventDispatchThread() ) 75 { 76 throw new RuntimeException ("Must be called from another thread than EDT"); 77 } 78 79 File destFolder = new File(destinationBackupFolder); 80 if(!destFolder.exists()) 81 { 82 destFolder.mkdirs(); 83 } 84 85 File backupFile = new File(destinationBackupFolder, getActualBackupName()+"SnowMailBackup.zip"); 86 final ProgressModalDialog progress = new ProgressModalDialog(SnowMailClientApp.getInstance(), "Backup", false, false); 87 progress.setCommentLabel(Language.translate("Saving opened folders")+"..."); 88 progress.start(); 89 90 91 SnowMailClientApp.getInstance().saveAllMails(false); 92 93 progress.setCommentLabel(backupFile.getAbsolutePath()); 94 95 96 synchronized( FileUtils.getLockForFileAccess() ) 97 { 98 FileOutputStream fos = null; 99 ZipOutputStream zos = null; 100 try 101 { 102 fos = new FileOutputStream(backupFile); 103 zos = new ZipOutputStream(fos); 104 List<File> allFiles = new Vector<File>(); 105 File rootFile = SnowMailClientApp.getInstance().getSnowMailRoot(); 106 FileUtils.getAllFilesRecurse(rootFile, allFiles); 107 progress.setProgressBounds(allFiles.size()); 108 109 for(int i=0; i<allFiles.size(); i++) 110 { 111 if(progress.wasCancelled()) 112 { 113 break; 114 } 115 116 File file = allFiles.get(i); 117 progress.setProgressValue(i, ""+file.getName()); 118 String relativeName = file.getAbsolutePath(); 119 relativeName = relativeName.substring( 120 rootFile.getParentFile().getAbsolutePath().length()+1, 121 relativeName.length()); 122 123 FileUtils.addToZip(zos, file, relativeName); 124 } 125 126 } 127 catch(Exception e) 128 { 129 e.printStackTrace(); 130 } 131 finally 132 { 133 FileUtils.closeIgnoringExceptions(zos); 134 FileUtils.closeIgnoringExceptions(fos); 135 136 progress.closeDialog(); 137 138 if(progress.wasCancelled()) 139 { 140 backupFile .delete (); 141 return; 142 } 143 } 144 } 145 146 lastBackup = new Date().getTime(); 147 148 organizeBackupArchive(new File(destinationBackupFolder)); 149 } 150 151 152 private void organizeBackupArchive(File base) 153 { 154 Vector<File> allBackups = new Vector<File>(); 156 getAllBackups(base, allBackups); 157 159 if(allBackups.size()<3) 160 { 161 return; 162 } 163 164 165 Collections.sort(allBackups, new Comparator<File>() 167 { 168 public int compare(File file1, File file2) 169 { 170 if(file1.lastModified() == file2.lastModified()) return 0; 171 if(file1.lastModified() > file2.lastModified()) return -1; 172 return 1; 173 } 174 }); 175 176 long lastBackupTime = allBackups.firstElement().lastModified(); 177 long oldestBackupTime = allBackups.lastElement().lastModified(); 178 181 Vector<File> youngerThanHour = new Vector<File>(); Vector<File> youngerThanDay = new Vector<File>(); Vector<File> youngerThanWeek = new Vector<File>(); Vector<File> youngerThanMonth = new Vector<File>(); Vector<File> olderThanMonth = new Vector<File>(); 189 for(int i=0; i<allBackups.size()-1; i++) 190 { 191 File file = allBackups.elementAt(i); 192 long time = file.lastModified(); 193 194 long ageFromNowSec = (lastBackupTime-time)/1000; 196 198 199 if(ageFromNowSec<3600) 200 { 201 youngerThanHour.add(file); 202 } 203 else if(ageFromNowSec<24*3600) 204 { 205 youngerThanDay.add(file); 206 } 207 else if(ageFromNowSec<7*24*3600) 208 { 209 youngerThanWeek.add(file); 210 } 211 else if(ageFromNowSec<30*24*3600) 212 { 213 youngerThanMonth.add(file); 214 } 215 else 216 { 217 olderThanMonth.add(file); 218 } 219 } 220 221 if(false) 222 { 223 System.out.println("Backup structure before reordering\n<begin>"); 224 System.out.println(" younger than 1 hour : "+youngerThanHour.size()); 225 System.out.println(" younger than 1 day : "+youngerThanDay.size()); 226 System.out.println(" younger than 1 week : "+youngerThanWeek.size()); 227 System.out.println(" younger than 1 month : "+youngerThanMonth.size()); 228 System.out.println(" older than 1 month : "+olderThanMonth.size()); 229 System.out.println("<end>"); 230 } 231 232 purge(youngerThanDay, 3600* 3); 233 purge(youngerThanWeek, 3600*24); 234 purge(youngerThanMonth, 3600*24* 7); 235 purge(olderThanMonth, 3600*24*30); 236 237 } 238 239 241 private void purge(Vector<File> files, long minDistanceSec) 242 { 243 if(files.size()<3) return; 245 long t0 = files.lastElement().lastModified(); 247 for(int i=files.size()-2; i>=1; i--) { 249 File file = files.elementAt(i); 250 252 long ti = file.lastModified(); 253 long distSec = (ti-t0)/1000; 254 if(distSec < minDistanceSec) 255 { 256 if(!file.delete()) {file.deleteOnExit();} 258 } 259 else 260 { 261 t0 = ti; 263 } 264 } 265 } 266 267 268 private void getAllBackups(File folder, Vector<File> files) 269 { 270 File[] backupFiles = folder.listFiles(new FilenameFilter() 271 { 272 public boolean accept(File dir, String name) 273 { 274 return name.toUpperCase().endsWith("SNOWMAILBACKUP.ZIP"); 275 } 276 }); 277 278 files.addAll(Arrays.asList(backupFiles)); 279 } 280 281 282 283 public String getActualBackupName() 284 { 285 SimpleDateFormat sdf = new SimpleDateFormat("yyyy MM dd HH'h'mm", Locale.ENGLISH); 286 String userName = System.getProperty("user.name", "home"); 287 return sdf.format(new Date()) + " ("+userName+")"; 288 } 289 290 293 public Vector<Object > getVectorRepresentation() throws VectorizeException 294 { 295 Vector<Object > v = new Vector<Object >(); 296 v.addElement(2); v.addElement(destinationBackupFolder); 298 v.addElement(minTimeBetweenTwoBackups); 299 v.addElement(lastBackup); 300 v.addElement(isAutomaticBackupEnabled); 301 return v; 302 } 303 304 public void createFromVectorRepresentation(Vector<Object > v) throws VectorizeException 305 { 306 int version = (Integer ) v.get(0); 307 if(version==1) 308 { 309 destinationBackupFolder = (String ) v.get(1); 310 minTimeBetweenTwoBackups = (Long ) v.get(2); 311 lastBackup = (Long ) v.elementAt(3); 312 } 313 else if(version==2) 314 { 315 destinationBackupFolder = (String ) v.get(1); 316 minTimeBetweenTwoBackups = (Long ) v.get(2); 317 lastBackup = (Long ) v.get(3); 318 isAutomaticBackupEnabled = (Boolean ) v.get(4); 319 } 320 else 321 { 322 throw new VectorizeException("Bad version "+version); 323 } 324 } 325 326 327 328 } | Popular Tags |