package esmska.persistence; import java.io.File; import java.io.IOException; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Date; import java.util.HashMap; import java.util.Locale; import java.util.logging.Level; import java.util.logging.Logger; import org.apache.commons.io.FileUtils; import org.apache.commons.lang.Validate; /** Manager for taking care of backups of user configuration files. * * @author ripper */ public class BackupManager { private static final Logger logger = Logger.getLogger(BackupManager.class.getName()); private final File backupRoot; private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.ENGLISH); /** Constructor. * * @param backupRoot Directory under which the backups will be created and managed. * Not null. */ public BackupManager(File backupRoot) { Validate.notNull(backupRoot); this.backupRoot = backupRoot; } /** Back up selected files to backup directory. A new subdirectory in a format * of yyyy-mm-dd will be created for them. * * @param files files to back up. Not null. Non-existent files are ignored. * @param overwrite if backup should overwrite already existing subdirectory * (i.e. backup from today) * @return true if files were backed up; false if they weren't (e.g. backup * already existed and wasn't overwritten) */ public boolean backupFiles(Collection<File> files, boolean overwrite) throws IOException { Validate.notNull(files); String today = dateFormat.format(new Date()); File backupDir = new File(backupRoot, today); if (backupDir.exists()) { if (!overwrite) { logger.fine("Backup already exists in '" + backupDir.getAbsolutePath() + "', skipping backup"); return false; } } else { FileUtils.forceMkdir(backupDir); } //copy files for (File file : files) { if (!file.exists()) { //ignore non-existent files continue; } FileUtils.copyFileToDirectory(file, backupDir); } logger.fine("Files backed up to '" + backupDir.getAbsolutePath() + "'"); return true; } /** Clean backup directory from old backup subdirs. * * @param backupsPreserved how many old backups should be preserved. All other * (older) backups will be deleted. Negative integer is converted to 0. */ public void removeOldBackups(int backupsPreserved) throws IOException { if (backupsPreserved < 0) { backupsPreserved = 0; } File[] subdirs = backupRoot.listFiles(); HashMap<Date, File> dateFiles = new HashMap<Date, File>(); for (File dir : subdirs) { if (!dir.isDirectory()) { continue; } try { Date date = dateFormat.parse(dir.getName()); dateFiles.put(date, dir); } catch (ParseException ex) { logger.log(Level.WARNING, "Unknown unparsable dir found in backups folder: '" + dir.getAbsolutePath() + "'", ex); //just skip it } } //sort directories by date ArrayList<Date> dates = new ArrayList<Date>(dateFiles.keySet()); Collections.sort(dates); Collections.reverse(dates); //delete old directories if (dates.size() > backupsPreserved) { Date[] datesArray = dates.toArray(new Date[]{}); Date[] toRemove = Arrays.copyOfRange(datesArray, backupsPreserved, datesArray.length); for (Date d : toRemove) { File dir = dateFiles.get(d); FileUtils.deleteDirectory(dir); } } } }