import java.io.File;
import java.io.IOException;
-import java.util.Arrays;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
// flag set to see if file save to temp file was successful
private boolean tempFileWriteSuccess;
+ // array of files to be deleted, with extra information
+ private ArrayList<DeleteFile> deleteFiles = new ArrayList<>();
+
+ // next backup filename
+ private File nextBackupFile;
+
+ // date formatting for modification times
+ private static final SimpleDateFormat sdf = new SimpleDateFormat(
+ "yyyy-MM-dd HH:mm:ss");
+
public BackupFiles(String filename)
{
this(new File(filename));
// roll the backupfiles
public boolean rollBackupFiles()
{
+ return this.rollBackupFiles(true);
+ }
+ public boolean rollBackupFiles(boolean tidyUp)
+ {
// file doesn't yet exist or backups are not enabled or template is null or
// empty
if ((!file.exists()) || (!enabled) || max < 0 || suffix == null
boolean ret = true;
// Create/move backups up one
- File[] oldFilesToDelete = null;
+ deleteFiles.clear();
+ //File[] oldFilesToDelete = null;
+ //File[] newerOldFilesToDelete = null; // put files with newer modification
+ // timestamps in here to warn the user!
// find existing backup files
BackupFilenameFilter bff = new BackupFilenameFilter(basename, suffix,
digits);
File[] backupFiles = dirFile.listFiles(bff);
int nextIndexNum = 0;
- String confirmDeleteExtraInfo = null;
if (backupFiles.length == 0)
{
{
TreeMap<Integer, File> bfTreeMap = sortBackupFilesAsTreeMap(
backupFiles, basename);
+ // bfTreeMap now a sorted list of <Integer index>,<File backupfile>
+ // mappings
if (reverseOrder)
{
// backup style numbering
File lastfile = null;
+ File lastfiletobedeleted = null;
+ String lastfiletobedeletedoriginalname = null;
+
int tempMax = noMax ? -1 : max;
// noMax == true means no limits
// look for first "gap" in backupFiles
tempMax = i;
}
}
-
- // for (int m = 0; m < tempMax; m++)
+
for (int n = tempMax; n > 0; n--)
{
- // int n = tempMax - m;
String backupfilename = dir + File.separatorChar
+ BackupFilenameParts.getBackupFilename(n, basename,
suffix, digits);
if (!backupfile_n.exists())
{
+ // no "oldest" file to delete
lastfile = backupfile_n;
+ lastfiletobedeleted = null;
continue;
}
- // if (m == 0 && backupfile_n.exists())
- if ((!noMax) && n == tempMax && backupfile_n.exists())
+ // check the modification time of the previous file if it's going to
+ // be deleted
+ if (lastfiletobedeleted != null)
+ {
+ long oldLMT = lastfiletobedeleted.lastModified();
+ long newLMT = backupfile_n.lastModified();
+ if (oldLMT > newLMT)
+ {
+ String oldLMTString = sdf
+ .format(lastfiletobedeleted.lastModified());
+ String newLMTString = sdf.format(backupfile_n.lastModified());
+ System.out.println("WARNING! I am set to delete backupfile "
+ + lastfiletobedeleted.getName() + " (was '"
+ + lastfiletobedeletedoriginalname + "')"
+ + " has modification time "
+ + oldLMTString
+ + " which is newer than its replacement "
+ + backupfile_n.getName() + " with modification time "
+ + newLMTString);
+
+ addDeleteFile(lastfiletobedeleted, backupfile_n, true, true,
+ " (" + MessageManager.formatMessage(
+ "label.was_previous", new String[]
+ { backupfile_n.getName() }) + ")");
+ }
+
+ // reset
+ lastfiletobedeleted = null;
+ lastfiletobedeletedoriginalname = null;
+ }
+
+ if (!noMax && n == tempMax && backupfile_n.exists())
{
// move the largest (max) rolled file to a temp file and add to the
// delete list
dirFile);
backupfile_n.renameTo(temp);
- oldFilesToDelete = new File[] { temp };
- confirmDeleteExtraInfo = "(was " + backupfile_n.getName()
- + ")";
+ String message = "(" + MessageManager
+ .formatMessage("label.was_previous", new String[]
+ { backupfile_n.getName() }) + ")";
+ addDeleteFile(temp, backupfile_n, true, false, message);
+
+ lastfiletobedeleted = temp;
} catch (IOException e)
{
System.out.println(
// need to delete some files to keep number of backups to designated
// max
int numToDelete = bfTreeMap.size() - max + 1;
- oldFilesToDelete = Arrays.copyOfRange(backupFiles, 0,
- numToDelete);
+ for (int i = 0; i < numToDelete; i++)
+ {
+ addDeleteFile(backupFiles[i], null, true, false, null);
+ }
}
}
}
- deleteOldFiles(oldFilesToDelete, confirmDeleteExtraInfo);
-
// Let's make the new backup file!! yay, got there at last!
String latestBackupFilename = dir + File.separatorChar
+ BackupFilenameParts.getBackupFilename(nextIndexNum, basename,
suffix, digits);
- File latestBackupFile = new File(latestBackupFilename);
- ret = ret && file.renameTo(latestBackupFile);
+ nextBackupFile = new File(latestBackupFilename);
+ ret |= file.renameTo(nextBackupFile);
+
+ if (tidyUp)
+ {
+ tidyUpFiles();
+ }
return ret;
}
- private void deleteOldFiles(File[] oldFilesToDelete,
- String confirmDeleteExtraInfo)
+ private void tidyUpFiles()
+ {
+ deleteOldFiles();
+ }
+
+ private void deleteOldFiles()
{
- if (oldFilesToDelete != null && oldFilesToDelete.length > 0)
+ if (deleteFiles != null && !deleteFiles.isEmpty())
{
+ boolean confirm = confirmDelete;
// delete old backup/version files
- boolean delete = false;
- if (confirmDelete)
+ // check for newer files
+ boolean newerDelete = hasNewerDeleteFile();
+ StringBuilder newerDeleteSB = null;
+ if (newerDelete)
{
- StringBuilder confirmMessage = new StringBuilder();
- confirmMessage.append(MessageManager
+ newerDeleteSB = new StringBuilder();
+ for (int i = 0; i < deleteFiles.size(); i++)
+ {
+ DeleteFile df = deleteFiles.get(i);
+ if (df.newer && df.delete)
+ {
+ String oldName = df.oldFile.getName();
+ String oldLMT = sdf.format(df.oldFile.lastModified());
+ String newLMT = sdf.format(df.newFile.lastModified());
+ if (newerDeleteSB.length() > 0)
+ {
+ newerDeleteSB.append("\n");
+ }
+ newerDeleteSB.append(
+ MessageManager.formatMessage("label.newerdelete_line",
+ new String[]
+ { oldName, oldLMT, df.newFile.getName(),
+ newLMT })
+ );
+ if (df.info != null
+ && df.info.length() > 0)
+ {
+ newerDeleteSB.append(" ");
+ newerDeleteSB.append(df.info);
+ }
+ confirm = true;
+ }
+ }
+ }
+
+ boolean doDelete = false;
+ StringBuilder deleteSB = null;
+ if (confirmDelete && deleteFiles.size() > 0)
+ {
+ deleteSB = new StringBuilder();
+ deleteSB.append(MessageManager
.getString("label.backupfiles_confirm_delete_old_files"));
- for (File f : oldFilesToDelete)
+ for (int i = 0; i < deleteFiles.size(); i++)
+ {
+ DeleteFile df = deleteFiles.get(i);
+ if (!df.delete)
+ {
+ break;
+ }
+ deleteSB.append("\n");
+ deleteSB.append(df.oldFile.getName());
+ if (df.info != null
+ && df.info.length() > 0)
+ {
+ deleteSB.append("\n");
+ deleteSB.append(df.info);
+ }
+ }
+ confirm = true;
+ }
+
+ if (confirm)
+ {
+ StringBuilder messageSB = new StringBuilder();
+ if (deleteSB != null && deleteSB.length() > 0)
{
- confirmMessage.append("\n");
- confirmMessage.append(f.getName());
+ messageSB.append(deleteSB);
}
- if (confirmDeleteExtraInfo != null
- && confirmDeleteExtraInfo.length() > 0)
+ if (newerDeleteSB != null && newerDeleteSB.length() > 0)
{
- confirmMessage.append("\n");
- confirmMessage.append(confirmDeleteExtraInfo);
+ messageSB.append("\n");
+ messageSB.append(newerDeleteSB);
}
- int confirm = JvOptionPane.showConfirmDialog(Desktop.desktop,
- confirmMessage.toString(),
+
+ int confirmButton = JvOptionPane.showConfirmDialog(Desktop.desktop,
+ messageSB.toString(),
MessageManager
.getString("label.backupfiles_confirm_delete"),
JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE);
- delete = (confirm == JvOptionPane.YES_OPTION);
+ doDelete = (confirmButton == JvOptionPane.YES_OPTION);
}
else
{
- delete = true;
+ doDelete = true;
}
- if (delete)
+ if (doDelete)
{
- for (int i = 0; i < oldFilesToDelete.length; i++)
+ for (int i = 0; i < deleteFiles.size(); i++)
{
- File fileToDelete = oldFilesToDelete[i];
+ File fileToDelete = deleteFiles.get(i).oldFile;
fileToDelete.delete();
// System.out.println("DELETING '" + fileToDelete.getName() +
// "'");
}
}
+
+ deleteFiles.clear();
}
private TreeMap<Integer, File> sortBackupFilesAsTreeMap(
boolean write = this.getWriteSuccess();
boolean roll = false;
+ boolean rename = false;
if (write)
{
- roll = this.rollBackupFiles();
- }
- else
- {
- return false;
+ roll = this.rollBackupFiles(false);
+ rename = this.renameTempFile();
}
/*
* trying to roll the backup files, and most likely the filename needed will already
* be vacant so renaming the temp file is nearly always correct!
*/
- if (!roll)
+ boolean okay = roll && rename;
+ if (!okay)
{
- int confirm = JvOptionPane.showConfirmDialog(Desktop.desktop,
- MessageManager.getString(
- "label.backupfiles_confirm_save_file_backupfiles_roll_wrong"),
- MessageManager
- .getString("label.backupfiles_confirm_save_file"),
- JvOptionPane.YES_NO_OPTION, JvOptionPane.WARNING_MESSAGE);
-
- if (confirm == JvOptionPane.YES_OPTION)
+ StringBuilder messageSB = new StringBuilder();
+ messageSB.append(MessageManager.getString( "label.backupfiles_confirm_save_file_backupfiles_roll_wrong"));
+ if (rename)
{
- roll = true;
+ if (messageSB.length() > 0)
+ {
+ messageSB.append("\n");
+ }
+ messageSB.append(MessageManager.getString(
+ "label.backupfiles_confirm_save_new_saved_file_ok"));
+ }
+ else
+ {
+ if (messageSB.length() > 0)
+ {
+ messageSB.append("\n");
+ }
+ messageSB.append(MessageManager.getString(
+ "label.backupfiles_confirm_save_new_saved_file_not_ok"));
}
- }
- boolean rename = false;
- if (roll)
+ int confirmButton = JvOptionPane.showConfirmDialog(Desktop.desktop,
+ messageSB.toString(),
+ MessageManager
+ .getString("label.backupfiles_confirm_save_file"),
+ JvOptionPane.OK_OPTION, JvOptionPane.WARNING_MESSAGE);
+ okay = confirmButton == JvOptionPane.OK_OPTION;
+ }
+ if (okay)
{
- rename = this.renameTempFile();
+ tidyUpFiles();
}
return rename;
return bfTreeMap;
}
+ private boolean addDeleteFile(File oldFile, File newFile, boolean delete,
+ boolean newer, String info)
+ {
+ boolean ret = false;
+ int pos = deleteFiles.indexOf(oldFile);
+ if (pos > -1)
+ {
+ DeleteFile df = deleteFiles.get(pos);
+ if (newFile != null)
+ {
+ df.newFile = newFile;
+ }
+ df.delete |= delete;
+ df.newer |= newer;
+ df.info += ';' + info;
+ ret = true;
+ }
+ else
+ {
+ deleteFiles
+ .add(new DeleteFile(oldFile, newFile, delete, newer, info));
+ }
+ return ret;
+ }
+
+ private boolean hasNewerDeleteFile()
+ {
+ for (int i = 0; i < deleteFiles.size(); i++)
+ {
+ DeleteFile df = deleteFiles.get(i);
+ if (df.newer)
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+}
+
+class DeleteFile
+{
+ protected File oldFile;
+
+ protected File newFile;
+
+ protected boolean delete;
+
+ protected boolean newer;
+
+ protected String info;
+
+ protected DeleteFile(File oldFile, File newFile, boolean delete,
+ boolean newer, String info)
+ {
+ this.oldFile = oldFile;
+ this.newFile = newFile;
+ this.delete = delete;
+ this.newer = newer;
+ this.info = info;
+ }
+
+ public boolean equals(File file)
+ {
+ return this.oldFile.equals(file);
+ }
}
embbedBioJSON.setText(MessageManager.getString("label.embbed_biojson"));
embbedBioJSON.setBounds(new Rectangle(228, 200, 250, 23));
- TitledBorder backupFilesBorder = new TitledBorder(
- MessageManager.getString("label.backup_files"));
-
jPanel11.add(jLabel1);
jPanel11.add(blcjv);
jPanel11.add(clustaljv);
@Override
public void actionPerformed(ActionEvent e)
{
- boolean selected = enableBackupFiles.isSelected();
// enable other options only when the first is checked
backupsOptionsSetEnabled();
}
return backupsTab;
}
- private final int BACKUPFILESSCHEMECUSTOMISE = 0;
- private final IntKeyStringValueEntry[] backupfilesPresetEntries = {
+ protected static final int BACKUPFILESSCHEMECUSTOMISE = 0;
+
+ private static final IntKeyStringValueEntry[] backupfilesPresetEntries = {
new IntKeyStringValueEntry(1,
MessageManager.getString("label.default")),
new IntKeyStringValueEntry(2,
new IntKeyStringValueEntry(4,
MessageManager.getString("label.rolled_backups")),
// ...
- // new IntKeyStringValueEntry(255,
- // MessageManager.getString("label.previously_saved_scheme")),
// IMPORTANT, keep "Custom" entry with key 0 (even though it appears last)
new IntKeyStringValueEntry(BACKUPFILESSCHEMECUSTOMISE,
MessageManager.getString("label.customise")) };
- private final Map<Integer, BackupFilesPresetEntry> backupfilesPresetEntriesValues = new HashMap<Integer, BackupFilesPresetEntry>()
+ private static final Map<Integer, BackupFilesPresetEntry> backupfilesPresetEntriesValues = new HashMap<Integer, BackupFilesPresetEntry>()
{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 125L;
+
{
put(1, new BackupFilesPresetEntry(
".bak" + BackupFiles.NUM_PLACEHOLDER, 3, false, false, 3,
updateBackupFilesExampleLabel();
}
- protected int getComboIntStringKey(JComboBox c)
+ protected int getComboIntStringKey(JComboBox<IntKeyStringValueEntry> c)
{
IntKeyStringValueEntry e = (IntKeyStringValueEntry) c.getSelectedItem();
return e != null ? e.getKey() : 0;
for (int i = 0; i < c.getItemCount(); i++)
{
IntKeyStringValueEntry e = c.getItemAt(i);
- int k = e.getKey();
- String v = e.getValue();
if (e.getKey() == key)
{
c.setSelectedIndex(i);
@Override
public void actionPerformed(ActionEvent e)
{
- boolean selected = backupfilesKeepAll.isSelected();
keepRollMaxOptionsEnabled();
updateBackupFilesExampleLabel();
}
class BackupFilesPresetsComboBoxRenderer extends DefaultListCellRenderer
{
+ /**
+ *
+ */
+ private static final long serialVersionUID = 88L;
+
@Override
- public Component getListCellRendererComponent(JList list, Object value, int index, boolean isSelected, boolean cellHasFocus) {
+ public Component getListCellRendererComponent(JList list, Object value,
+ int index, boolean isSelected, boolean cellHasFocus)
+ {
super.getListCellRendererComponent(list, value, index, isSelected, cellHasFocus);
try {
IntKeyStringValueEntry e = (IntKeyStringValueEntry) value;
- if (e.getKey() == 255)
- {
- // "Previously saved scheme" item
- this.setFont(this.getFont().deriveFont(Font.ITALIC));
- }
- else if (e.getKey() == 0)
+ if (e.getKey() == GPreferences.BACKUPFILESSCHEMECUSTOMISE)
{
// "Customise" item
this.setFont(this.getFont().deriveFont(Font.BOLD));