+/*
+ * Jalview - A Sequence Alignment Editor and Viewer ($$Version-Rel$$)
+ * Copyright (C) $$Year-Rel$$ The Jalview Authors
+ *
+ * This file is part of Jalview.
+ *
+ * Jalview is free software: you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation, either version 3
+ * of the License, or (at your option) any later version.
+ *
+ * Jalview is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR
+ * PURPOSE. See the GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Jalview. If not, see <http://www.gnu.org/licenses/>.
+ * The Jalview Authors are detailed in the 'AUTHORS' file.
+ */
package jalview.io;
-import jalview.bin.Cache;
-import jalview.gui.Desktop;
-import jalview.gui.JvOptionPane;
-import jalview.util.MessageManager;
-
import java.io.File;
import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
+import jalview.bin.Cache;
+import jalview.gui.Desktop;
+import jalview.gui.JvOptionPane;
+import jalview.util.MessageManager;
+
/*
* BackupFiles used for manipulating (naming rolling/deleting) backup/version files when an alignment or project file is saved.
* User configurable options are:
* BACKUPFILES_ENABLED - boolean flag as to whether to use this mechanism or act as before, including overwriting files as saved.
- * BACKUPFILES_SUFFIX - a template to insert after the file extension. Use '%n' to be replaced by a 0-led SUFFIX_DIGITS long integer.
- * BACKUPFILES_NO_MAX - flag to turn off setting a maximum number of backup files to keep.
- * BACKUPFILES_ROLL_MAX - the maximum number of backupfiles to keep for any one alignment or project file.
- * BACKUPFILES_SUFFIX_DIGITS - the number of digits to insert replace %n with (e.g. BACKUPFILES_SUFFIX_DIGITS = 3 would make "001", "002", etc)
- * BACKUPFILES_REVERSE_ORDER - if true then "logfile" style numbering and file rolling will occur. If false then ever-increasing version numbering will occur, but old files will still be deleted if there are more than ROLL_MAX backup files.
- * BACKUPFILES_CONFIRM_DELETE_OLD - if true then prompt/confirm with the user when deleting older backup/version files.
+ * The rest of the options are now saved as BACKUPFILES_PRESET, BACKUPFILES_SAVED and BACKUPFILES_CUSTOM
+ * (see BackupFilesPresetEntry)
*/
public class BackupFiles
public static final String ENABLED = NS + "_ENABLED";
- public static final String SUFFIX = NS + "_SUFFIX";
-
- public static final String NO_MAX = NS + "_NO_MAX";
-
- public static final String ROLL_MAX = NS + "_ROLL_MAX";
-
- public static final String SUFFIX_DIGITS = NS + "_SUFFIX_DIGITS";
-
public static final String NUM_PLACEHOLDER = "%n";
- public static final String REVERSE_ORDER = NS + "_REVERSE_ORDER";
-
- public static final String CONFIRM_DELETE_OLD = NS
- + "_CONFIRM_DELETE_OLD";
-
private static final String DEFAULT_TEMP_FILE = "jalview_temp_file_" + NS;
private static final String TEMP_FILE_EXT = ".tmp";
private static final SimpleDateFormat sdf = new SimpleDateFormat(
"yyyy-MM-dd HH:mm:ss");
+ private static final String newTempFileSuffix = "_newfile";
+
+ private static final String oldTempFileSuffix = "_oldfile_tobedeleted";
+
public BackupFiles(String filename)
{
this(new File(filename));
// REVERSE_ORDER
public BackupFiles(File file)
{
- this(file, ".bak" + NUM_PLACEHOLDER, false, 3, 3, false);
- }
-
- public BackupFiles(File file, String defaultSuffix, boolean defaultNoMax,
- int defaultMax, int defaultDigits, boolean defaultReverseOrder)
- {
classInit();
this.file = file;
- this.suffix = Cache.getDefault(SUFFIX, defaultSuffix);
- this.noMax = Cache.getDefault(NO_MAX, defaultNoMax);
- this.max = Cache.getDefault(ROLL_MAX, defaultMax);
- this.digits = Cache.getDefault(SUFFIX_DIGITS, defaultDigits);
- this.reverseOrder = Cache.getDefault(REVERSE_ORDER,
- defaultReverseOrder);
+ BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
+ .getSavedBackupEntry();
+ this.suffix = bfpe.suffix;
+ this.noMax = bfpe.keepAll;
+ this.max = bfpe.rollMax;
+ this.digits = bfpe.digits;
+ this.reverseOrder = bfpe.reverse;
// create a temp file to save new data in
File temp = null;
{
String tempfilename = file.getName();
File tempdir = file.getParentFile();
- temp = File.createTempFile(tempfilename, TEMP_FILE_EXT + "_newfile",
- tempdir);
+ temp = File.createTempFile(tempfilename,
+ TEMP_FILE_EXT + newTempFileSuffix, tempdir);
}
else
{
public static void classInit()
{
setEnabled(Cache.getDefault(ENABLED, true));
- setConfirmDelete(Cache.getDefault(CONFIRM_DELETE_OLD, true));
+ BackupFilesPresetEntry bfpe = BackupFilesPresetEntry
+ .getSavedBackupEntry();
+ setConfirmDelete(bfpe.confirmDelete);
}
public static void setEnabled(boolean flag)
public boolean renameTempFile()
{
- return tempFile.renameTo(file);
+ return moveFileToFile(tempFile, file);
}
// roll the backupfiles
{
// backup style numbering
-
int tempMax = noMax ? -1 : max;
// noMax == true means no limits
// look for first "gap" in backupFiles
tempMax = i;
}
}
-
+
File previousFile = null;
File fileToBeDeleted = null;
for (int n = tempMax; n > 0; n--)
{
File oldestTempFile = nextTempFile(fileToBeDeleted.getName(),
dirFile);
-
+
if (fileToBeDeletedLMT > replacementFileLMT)
{
String fileToBeDeletedLMTString = sdf
}
else
{
- fileToBeDeleted.renameTo(oldestTempFile);
+ moveFileToFile(fileToBeDeleted, oldestTempFile);
}
}
else
{
- fileToBeDeleted.renameTo(oldestTempFile);
+ moveFileToFile(fileToBeDeleted, oldestTempFile);
addDeleteFile(oldestTempFile);
}
{
if (previousFile != null)
{
- ret = ret && backupfile_n.renameTo(previousFile);
+ ret = ret && moveFileToFile(backupfile_n, previousFile);
}
}
.println("WARNING! I am set to delete backupfile '"
+ fileToBeDeleted.getName()
+ "' has modification time "
- + fileToBeDeletedLMTString
+ + fileToBeDeletedLMTString
+ " which is newer than the oldest backupfile being kept '"
- + replacementFile.getName()
+ + replacementFile.getName()
+ "' with modification time "
- + replacementFileLMTString);
+ + replacementFileLMTString);
delete = confirmNewerDeleteFile(fileToBeDeleted,
replacementFile, false);
String latestBackupFilename = dir + File.separatorChar
+ BackupFilenameParts.getBackupFilename(nextIndexNum, basename,
suffix, digits);
- ret |= file.renameTo(new File(latestBackupFilename));
+ ret |= moveFileToFile(file, new File(latestBackupFilename));
if (tidyUp)
{
null, options, options[0]);
}
-
// return should be TRUE if file is to be deleted
return (confirmButton == JvOptionPane.YES_OPTION);
}
}
private TreeMap<Integer, File> sortBackupFilesAsTreeMap(
- File[] backupFiles,
- String basename)
+ File[] backupFiles, String basename)
{
// sort the backup files (based on integer found in the suffix) using a
// precomputed Hashmap for speed
if (!okay)
{
StringBuilder messageSB = new StringBuilder();
- messageSB.append(MessageManager.getString( "label.backupfiles_confirm_save_file_backupfiles_roll_wrong"));
+ messageSB.append(MessageManager.getString(
+ "label.backupfiles_confirm_save_file_backupfiles_roll_wrong"));
if (rename)
{
if (messageSB.length() > 0)
return ret;
}
+ private boolean moveFileToFile(File oldFile, File newFile)
+ {
+ boolean ret = false;
+ Path oldPath = Paths.get(oldFile.getAbsolutePath());
+ Path newPath = Paths.get(newFile.getAbsolutePath());
+ try
+ {
+ Files.move(oldPath, newPath, StandardCopyOption.REPLACE_EXISTING);
+ ret = true;
+ } catch (IOException e)
+ {
+ Cache.log.warn("Could not move file '" + oldPath.toString() + "' to '"
+ + newPath.toString() + "'");
+ ret = false;
+ }
+ return ret;
+ }
}