package org.wildstang.wildrank.desktop.utils; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.File; import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; import java.util.ArrayList; import java.util.Calendar; import java.util.Iterator; import java.util.List; import java.util.TimeZone; import org.apache.commons.io.FileUtils; import org.wildstang.wildrank.desktop.GlobalAppHandler; public class FileUtilities { public static boolean isUSBConnected() { // Test if USB is connected String flashDriveSyncedDirectoryString = GlobalAppHandler.getInstance().getAppData().getFlashDriveLocation() + File.separator + "synced"; File flashDriveSyncedDirectory = new File(flashDriveSyncedDirectoryString); flashDriveSyncedDirectory.mkdir(); if (flashDriveSyncedDirectory.exists()) { return true; } else { return false; } } public static boolean isSavedConfigFilePresent() { return new File("save.json").exists(); } public static void syncWithFlashDrive() throws IOException { // IMPORTANT! First, make a backup of all the data we have now, both on the flash drive and on local Calendar c = Calendar.getInstance(TimeZone.getTimeZone("CST")); File localBackupDir = new File(getNonsyncedDirectory() + File.separator + "backups" + File.separator + "local" + File.separator + c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH) + "-" + c.get(Calendar.HOUR_OF_DAY) + "." + c.get(Calendar.MINUTE) + "." + c.get(Calendar.SECOND)); localBackupDir.mkdirs(); FileUtils.copyDirectory(getSyncedDirectory(), new File(localBackupDir + File.separator + "synced")); FileUtils.copyDirectory(getUnintegratedDirectory(), new File(localBackupDir + File.separator + "unintegrated")); Logger.getInstance().log("backup of local created"); File flashBackupDir = new File(getNonsyncedDirectory() + File.separator + "backups" + File.separator + "flash" + File.separator + c.get(Calendar.YEAR) + "-" + c.get(Calendar.MONTH) + "-" + c.get(Calendar.DAY_OF_MONTH) + "-" + c.get(Calendar.HOUR_OF_DAY) + "." + c.get(Calendar.MINUTE) + "." + c.get(Calendar.SECOND)); flashBackupDir.mkdirs(); FileUtils.copyDirectory(getFlashDriveSyncedDirectory(), new File(flashBackupDir + File.separator + "synced")); FileUtils.copyDirectory(getFlashDriveUnintegratedDirectory(), new File(flashBackupDir + File.separator + "unintegrated")); Logger.getInstance().log("backup of flash createdd"); syncLocalAndFlashDirectories(); Logger.getInstance().log("syncing synced directories done!"); // Now we copy the contents of the unintegrated files on the flash drive to the local storage // We append the data instead of overwriting it List<File> fileList = new ArrayList<File>(); listFilesInDirectory(getFlashDriveUnintegratedDirectory(), fileList); for (File file : fileList) { File destinationFile = new File(file.getAbsolutePath().replace(getFlashDriveUnintegratedDirectory().getAbsolutePath(), getUnintegratedDirectory().getAbsolutePath())); Logger.getInstance().log("destination: " + destinationFile.getAbsolutePath()); copyFileWithAppend(file, destinationFile); } Logger.getInstance().log("flash unsynced done"); // Next, wipe the unintegrated directory on the flash drive. All unintegrated // files are now stored locally and ready for integration. FileUtils.cleanDirectory(getFlashDriveUnintegratedDirectory()); Logger.getInstance().log("flash unintegrated wiped"); } private static void copyFileWithAppend(File source, File destination) throws IOException { if (!destination.exists()) { destination.getParentFile().mkdirs(); destination.createNewFile(); } if (!source.exists()) { throw new IOException("Source file must exist!"); } BufferedReader sourceReader = new BufferedReader(new FileReader(source)); BufferedWriter destinationWriter = new BufferedWriter(new FileWriter(destination, true)); String line; while ((line = sourceReader.readLine()) != null) { destinationWriter.write(line); destinationWriter.newLine(); } destinationWriter.flush(); destinationWriter.close(); sourceReader.close(); } public static String getRelativePathForLocal(File file) { String absolutePath = file.getAbsolutePath(); // First we find the length of the root path int startIndex = GlobalAppHandler.getInstance().getAppData().getLocalLocation().getAbsolutePath().length(); // Next, we search for the next file separator character after that int fileSeparatorIndex = absolutePath.indexOf(File.separator, startIndex + 1); // If we remove all of the string before that character, we have the relative path! String relativePath = absolutePath.substring(fileSeparatorIndex); Logger.getInstance().log("relative path: " + relativePath); return relativePath; } public static String getRelativePathForFlashDrive(File file) { String absolutePath = file.getAbsolutePath(); // First we find the length of the root path int startIndex = GlobalAppHandler.getInstance().getAppData().getFlashDriveLocation().getAbsolutePath().length(); // Next, we search for the next file separator character after that int fileSeparatorIndex = absolutePath.indexOf(File.separator, startIndex + 1); // If we remove all of the string before that character, we have the relative path! String relativePath = absolutePath.substring(fileSeparatorIndex); Logger.getInstance().log("relative path: " + relativePath); return relativePath; } public static File getSyncedDirectory() { File file = new File(GlobalAppHandler.getInstance().getAppData().getLocalLocation() + File.separator + "synced"); if (!file.exists()) { file.mkdirs(); } return file; } public static File getUnintegratedDirectory() { File file = new File(GlobalAppHandler.getInstance().getAppData().getLocalLocation() + File.separator + "unintegrated"); if (!file.exists()) { file.mkdirs(); } return file; } public static File getNonsyncedDirectory() { File file = new File(GlobalAppHandler.getInstance().getAppData().getLocalLocation() + File.separator + "nonsynced"); if (!file.exists()) { file.mkdirs(); } return file; } public static File getFlashDriveSyncedDirectory() { File file = new File(GlobalAppHandler.getInstance().getAppData().getFlashDriveLocation() + File.separator + "synced"); if (!file.exists()) { file.mkdirs(); } return file; } public static File getFlashDriveUnintegratedDirectory() { File file = new File(GlobalAppHandler.getInstance().getAppData().getFlashDriveLocation() + File.separator + "unintegrated"); if (!file.exists()) { file.mkdirs(); } return file; } public static void listFilesInDirectory(File directory, List<File> list) { Logger.getInstance().log("listFilesInDirectory; directory: " + directory.getAbsolutePath()); File[] files = directory.listFiles(); if (files != null) { for (File file : files) { if (file.isFile() && !file.isHidden()) { list.add(file); } else if (file.isDirectory()) { listFilesInDirectory(file, list); } } } } private static void syncLocalAndFlashDirectories() { long startTime = System.currentTimeMillis(); int totalFiles = 0; // Get lists of files in both directories List<File> localSyncedFiles = new ArrayList<File>(); listFilesInDirectory(getSyncedDirectory(), localSyncedFiles); List<File> flashSyncedFiles = new ArrayList<File>(); listFilesInDirectory(getFlashDriveSyncedDirectory(), flashSyncedFiles); for (File f : localSyncedFiles) { Logger.getInstance().log("local: " + f.getAbsolutePath()); } for (File f : flashSyncedFiles) { Logger.getInstance().log("flash: " + f.getAbsolutePath()); } // Filter each list to have only relative locations List<String> localPaths = new ArrayList<String>(); List<String> flashPaths = new ArrayList<String>(); for (File file : localSyncedFiles) { localPaths.add(getRelativePathForLocal(file)); } for (File file : flashSyncedFiles) { flashPaths.add(getRelativePathForFlashDrive(file)); } Iterator<String> flashIterator = flashPaths.iterator(); while (flashIterator.hasNext()) { String flashPath = flashIterator.next(); totalFiles++; if (localPaths.contains(flashPath)) { File flashFile = new File(getFlashDriveSyncedDirectory() + File.separator + flashPath); File localFile = new File(getSyncedDirectory() + File.separator + flashPath); syncFile(flashFile, localFile); flashIterator.remove(); localPaths.remove(flashPath); } else { File flashFile = new File(getFlashDriveSyncedDirectory() + File.separator + flashPath); File localFile = new File(getSyncedDirectory() + File.separator + flashPath); localFile.getParentFile().mkdirs(); try { localFile.createNewFile(); FileUtils.copyFile(flashFile, localFile); } catch (IOException e) { e.printStackTrace(); } flashIterator.remove(); } } Iterator<String> localIterator = localPaths.iterator(); while (localIterator.hasNext()) { totalFiles++; String localPath = localIterator.next(); if (flashPaths.contains(localPath)) { File flashFile = new File(getFlashDriveSyncedDirectory() + File.separator + localPath); File localFile = new File(getSyncedDirectory() + File.separator + localPath); syncFile(flashFile, localFile); flashPaths.remove(localPaths); localIterator.remove(); } else { File flashFile = new File(getFlashDriveSyncedDirectory() + File.separator + localPath); File localFile = new File(getSyncedDirectory() + File.separator + localPath); localFile.getParentFile().mkdirs(); try { localFile.createNewFile(); FileUtils.copyFile(localFile, flashFile); } catch (IOException e) { e.printStackTrace(); } localIterator.remove(); } } long totalTime = System.currentTimeMillis() - startTime; Logger.getInstance().log("Total time for sync: " + totalTime + "ms"); if (totalFiles != 0) { Logger.getInstance().log("Average time per file: " + (totalTime / totalFiles) + "ms"); } } private static void syncFile(File file1, File file2) { long timestamp1 = file1.lastModified(); long timestamp2 = file2.lastModified(); try { if (timestamp1 > timestamp2) { FileUtils.copyFile(file1, file2); } else if (timestamp1 < timestamp2) { FileUtils.copyFile(file2, file1); } else { // If timestamp is the same, we can assume that the files are identical } } catch (IOException e) { e.printStackTrace(); } } }