src/main/java/fr/xephi/authme/util/FileUtils.java
package fr.xephi.authme.util;
import com.google.common.io.Files;
import fr.xephi.authme.AuthMe;
import fr.xephi.authme.ConsoleLogger;
import fr.xephi.authme.output.ConsoleLoggerFactory;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import static java.lang.String.format;
/**
* File utilities.
*/
public final class FileUtils {
private static final DateTimeFormatter CURRENT_DATE_STRING_FORMATTER =
DateTimeFormatter.ofPattern("yyyyMMdd_HHmm");
private static ConsoleLogger logger = ConsoleLoggerFactory.get(FileUtils.class);
// Utility class
private FileUtils() {
}
/**
* Copy a resource file (from the JAR) to the given file if it doesn't exist.
*
* @param destinationFile The file to check and copy to (outside of JAR)
* @param resourcePath Local path to the resource file (path to file within JAR)
*
* @return False if the file does not exist and could not be copied, true otherwise
*/
public static boolean copyFileFromResource(File destinationFile, String resourcePath) {
if (destinationFile.exists()) {
return true;
} else if (!createDirectory(destinationFile.getParentFile())) {
logger.warning("Cannot create parent directories for '" + destinationFile + "'");
return false;
}
try (InputStream is = getResourceFromJar(resourcePath)) {
if (is == null) {
logger.warning(format("Cannot copy resource '%s' to file '%s': cannot load resource",
resourcePath, destinationFile.getPath()));
} else {
java.nio.file.Files.copy(is, destinationFile.toPath());
return true;
}
} catch (IOException e) {
logger.logException(format("Cannot copy resource '%s' to file '%s':",
resourcePath, destinationFile.getPath()), e);
}
return false;
}
/**
* Creates the given directory.
*
* @param dir the directory to create
* @return true upon success, false otherwise
*/
public static boolean createDirectory(File dir) {
if (!dir.exists() && !dir.mkdirs()) {
logger.warning("Could not create directory '" + dir + "'");
return false;
}
return dir.isDirectory();
}
/**
* Returns a JAR file as stream. Returns null if it doesn't exist.
*
* @param path the local path (starting from resources project, e.g. "config.yml" for 'resources/config.yml')
* @return the stream if the file exists, or false otherwise
*/
public static InputStream getResourceFromJar(String path) {
// ClassLoader#getResourceAsStream does not deal with the '\' path separator: replace to '/'
final String normalizedPath = path.replace("\\", "/");
return AuthMe.class.getClassLoader().getResourceAsStream(normalizedPath);
}
/**
* Delete a given directory and all its content.
*
* @param directory The directory to remove
*/
public static void purgeDirectory(File directory) {
if (!directory.isDirectory()) {
return;
}
File[] files = directory.listFiles();
if (files == null) {
return;
}
for (File target : files) {
if (target.isDirectory()) {
purgeDirectory(target);
}
delete(target);
}
}
/**
* Delete the given file or directory and log a message if it was unsuccessful.
* Method is null safe and does nothing when null is passed.
*
* @param file the file to delete
*/
public static void delete(File file) {
if (file != null) {
boolean result = file.delete();
if (!result) {
logger.warning("Could not delete file '" + file + "'");
}
}
}
/**
* Creates the given file or throws an exception.
*
* @param file the file to create
*/
public static void create(File file) {
try {
boolean result = file.createNewFile();
if (!result) {
throw new IllegalStateException("Could not create file '" + file + "'");
}
} catch (IOException e) {
throw new IllegalStateException("Error while creating file '" + file + "'", e);
}
}
/**
* Construct a file path from the given elements, i.e. separate the given elements by the file separator.
*
* @param elements The elements to create a path with
*
* @return The created path
*/
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);
}
}