mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-12-18 22:57:47 +01:00
#1467 Create backup before migrating; output newly added message keys
- Extract logic for creating a backup timestamp into FileUtils
This commit is contained in:
parent
ffeb04c0a2
commit
9dd4039fdd
@ -1,5 +1,6 @@
|
||||
package fr.xephi.authme.datasource;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.settings.Settings;
|
||||
import fr.xephi.authme.settings.properties.DatabaseSettings;
|
||||
@ -8,14 +9,10 @@ import fr.xephi.authme.util.FileUtils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.file.Files;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Migrates the SQLite database when necessary.
|
||||
@ -70,11 +67,10 @@ class SqLiteMigrater {
|
||||
File backupDirectory = new File(dataFolder, "backups");
|
||||
FileUtils.createDirectory(backupDirectory);
|
||||
|
||||
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm");
|
||||
String backupName = "backup-" + databaseName + dateFormat.format(new Date()) + ".db";
|
||||
String backupName = "backup-" + databaseName + FileUtils.createCurrentTimeString() + ".db";
|
||||
File backup = new File(backupDirectory, backupName);
|
||||
try {
|
||||
Files.copy(sqLite.toPath(), backup.toPath());
|
||||
Files.copy(sqLite, backup);
|
||||
return backupName;
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Failed to create SQLite backup before migration", e);
|
||||
|
@ -19,7 +19,7 @@ import java.util.Objects;
|
||||
* Implementation of {@link PropertyReader} which can read a file or a stream with
|
||||
* a specified charset.
|
||||
*/
|
||||
public class MessageMigraterPropertyReader implements PropertyReader {
|
||||
public final class MessageMigraterPropertyReader implements PropertyReader {
|
||||
|
||||
public static final Charset CHARSET = StandardCharsets.UTF_8;
|
||||
|
||||
@ -31,6 +31,12 @@ public class MessageMigraterPropertyReader implements PropertyReader {
|
||||
root = valuesMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new property reader for the given file.
|
||||
*
|
||||
* @param file the file to load
|
||||
* @return the created property reader
|
||||
*/
|
||||
public static MessageMigraterPropertyReader loadFromFile(File file) {
|
||||
Map<String, Object> valuesMap;
|
||||
try (InputStream is = new FileInputStream(file)) {
|
||||
|
@ -7,12 +7,17 @@ import ch.jalu.configme.properties.Property;
|
||||
import ch.jalu.configme.properties.StringProperty;
|
||||
import ch.jalu.configme.resource.YamlFileResource;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
import fr.xephi.authme.message.MessageKey;
|
||||
import fr.xephi.authme.util.FileUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
@ -60,6 +65,8 @@ public class MessageUpdater {
|
||||
boolean addedMissingKeys = addMissingKeys(jarMessageSource, userResource);
|
||||
|
||||
if (movedOldKeys || addedMissingKeys) {
|
||||
backupMessagesFile(userFile);
|
||||
|
||||
SettingsManager settingsManager = new SettingsManager(userResource, null, CONFIGURATION_DATA);
|
||||
settingsManager.save();
|
||||
ConsoleLogger.debug("Successfully saved {0}", userFile);
|
||||
@ -77,20 +84,32 @@ public class MessageUpdater {
|
||||
}
|
||||
|
||||
private boolean addMissingKeys(JarMessageSource jarMessageSource, YamlFileResource userResource) {
|
||||
int addedKeys = 0;
|
||||
List<String> addedKeys = new ArrayList<>();
|
||||
for (Property<?> property : CONFIGURATION_DATA.getProperties()) {
|
||||
if (userResource.getString(property.getPath()) == null) {
|
||||
userResource.setValue(property.getPath(), jarMessageSource.getMessageFromJar(property));
|
||||
++addedKeys;
|
||||
final String key = property.getPath();
|
||||
if (userResource.getString(key) == null) {
|
||||
userResource.setValue(key, jarMessageSource.getMessageFromJar(property));
|
||||
addedKeys.add(key);
|
||||
}
|
||||
}
|
||||
if (addedKeys > 0) {
|
||||
ConsoleLogger.info("Added " + addedKeys + " missing keys to your messages_xx.yml file");
|
||||
if (!addedKeys.isEmpty()) {
|
||||
ConsoleLogger.info(
|
||||
"Added " + addedKeys.size() + " missing keys to your messages_xx.yml file: " + addedKeys);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void backupMessagesFile(File messagesFile) {
|
||||
String backupName = FileUtils.createBackupFilePath(messagesFile);
|
||||
File backupFile = new File(backupName);
|
||||
try {
|
||||
Files.copy(messagesFile, backupFile);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Could not back up '" + messagesFile + "' to '" + backupFile + "'", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs the {@link ConfigurationData} for exporting a messages file in its entirety.
|
||||
*
|
||||
|
@ -16,8 +16,6 @@ import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
|
||||
import static fr.xephi.authme.util.Utils.logAndSendMessage;
|
||||
import static fr.xephi.authme.util.Utils.logAndSendWarning;
|
||||
@ -27,7 +25,6 @@ import static fr.xephi.authme.util.Utils.logAndSendWarning;
|
||||
*/
|
||||
public class BackupService {
|
||||
|
||||
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd_HH-mm");
|
||||
private final File dataFolder;
|
||||
private final File backupFolder;
|
||||
private final Settings settings;
|
||||
@ -181,7 +178,7 @@ public class BackupService {
|
||||
* @return the file to back up the data to
|
||||
*/
|
||||
private File constructBackupFile(String fileExtension) {
|
||||
String dateString = dateFormat.format(new Date());
|
||||
String dateString = FileUtils.createCurrentTimeString();
|
||||
return new File(backupFolder, "backup" + dateString + "." + fileExtension);
|
||||
}
|
||||
|
||||
|
@ -1,12 +1,14 @@
|
||||
package fr.xephi.authme.util;
|
||||
|
||||
import com.google.common.io.Files;
|
||||
import fr.xephi.authme.AuthMe;
|
||||
import fr.xephi.authme.ConsoleLogger;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
|
||||
import static java.lang.String.format;
|
||||
|
||||
@ -15,6 +17,9 @@ import static java.lang.String.format;
|
||||
*/
|
||||
public final class FileUtils {
|
||||
|
||||
private static final DateTimeFormatter CURRENT_DATE_STRING_FORMATTER =
|
||||
DateTimeFormatter.ofPattern("yyyyMMdd_HHmm");
|
||||
|
||||
// Utility class
|
||||
private FileUtils() {
|
||||
}
|
||||
@ -40,7 +45,7 @@ public final class FileUtils {
|
||||
ConsoleLogger.warning(format("Cannot copy resource '%s' to file '%s': cannot load resource",
|
||||
resourcePath, destinationFile.getPath()));
|
||||
} else {
|
||||
Files.copy(is, destinationFile.toPath());
|
||||
java.nio.file.Files.copy(is, destinationFile.toPath());
|
||||
return true;
|
||||
}
|
||||
} catch (IOException e) {
|
||||
@ -138,4 +143,28 @@ public final class FileUtils {
|
||||
public static String makePath(String... elements) {
|
||||
return String.join(File.separator, elements);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a textual representation of the current time (including minutes), e.g. useful for
|
||||
* automatically generated backup files.
|
||||
*
|
||||
* @return string of the current time for use in file names
|
||||
*/
|
||||
public static String createCurrentTimeString() {
|
||||
return LocalDateTime.now().format(CURRENT_DATE_STRING_FORMATTER);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a path to a new file (which doesn't exist yet) with a timestamp in the name in the same
|
||||
* folder as the given file and containing the given file's filename.
|
||||
*
|
||||
* @param file the file based on which a new file path should be created
|
||||
* @return path to a file suitably named for storing a backup
|
||||
*/
|
||||
public static String createBackupFilePath(File file) {
|
||||
String filename = "backup_" + Files.getNameWithoutExtension(file.getName())
|
||||
+ "_" + createCurrentTimeString()
|
||||
+ "." + Files.getFileExtension(file.getName());
|
||||
return makePath(file.getParent(), filename);
|
||||
}
|
||||
}
|
||||
|
@ -11,6 +11,7 @@ import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.matchesPattern;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.hamcrest.Matchers.nullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
@ -20,6 +21,9 @@ import static org.junit.Assert.assertThat;
|
||||
*/
|
||||
public class FileUtilsTest {
|
||||
|
||||
/** Regex that matches timestamps such as 20180211_1048. */
|
||||
private static final String BACKUP_TIMESTAMP_PATTERN = "20\\d{6}_\\d{4}";
|
||||
|
||||
@BeforeClass
|
||||
public static void initLogger() {
|
||||
TestHelper.setupLogger();
|
||||
@ -186,6 +190,29 @@ public class FileUtilsTest {
|
||||
TestHelper.validateHasOnlyPrivateEmptyConstructor(FileUtils.class);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void shouldCreateCurrentTimestampString() {
|
||||
// given / when
|
||||
String currentTimeString = FileUtils.createCurrentTimeString();
|
||||
|
||||
// then
|
||||
assertThat(currentTimeString, matchesPattern(BACKUP_TIMESTAMP_PATTERN));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldCreateBackupFile() {
|
||||
// given
|
||||
File file = new File("some/folders/config.yml");
|
||||
|
||||
// when
|
||||
String backupFile = FileUtils.createBackupFilePath(file);
|
||||
|
||||
// then
|
||||
String folders = String.join(File.separator,"some", "folders", "").replace("\\", "\\\\");
|
||||
assertThat(backupFile, matchesPattern(folders + "backup_config_" + BACKUP_TIMESTAMP_PATTERN + "\\.yml"));
|
||||
}
|
||||
|
||||
private static void createFiles(File... files) throws IOException {
|
||||
for (File file : files) {
|
||||
boolean result = file.getParentFile().mkdirs() & file.createNewFile();
|
||||
|
Loading…
Reference in New Issue
Block a user