package AndysAutoCopy;
import java.io.IOException;
import java.nio.file.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.nio.file.attribute.DosFileAttributes;
import java.awt.Toolkit;
import java.io.File;
import java.util.Properties;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Iterator;
public class AndysAutoCopy {
public static void main(String[] args) throws IOException {
// Declare the variables
String sourceDirectory;
String destinationDirectory;
String additionalDestinationDirectory;
Properties iniFile = new Properties();
InputStream iniFileInput = null;
File sourceFolder; //used for checking if the source folder exists
File destinationFolder; //used for checking if the destination folder exists
File additionalDestinationFolder; //used for checking if the second destination folder exists
// Initialise the variables. Note loggingLevel is 0 for system type errors, 1 for status updates and 2 for verbose
GlobalCounters.totalFilesCopied = 0;
GlobalCounters.loggingLevel = 0;
GlobalCounters.checkingInterval = 0;
GlobalCounters.numberOfChecks = 0;
GlobalCounters.listOfAllCopiedFiles = new ArrayList(); //Clears list of all files copied
// Confirm execution has started
LogMessage("Checking File Status",1);
// Read the AndysAutoCopy.ini file to get the source, destination & other variables
try {
//Set up the ini file
//iniFileInput = new FileInputStream("d:\\utils\\AndysAutoCopy\\AndysAutoCopy.ini");
iniFileInput = new FileInputStream("AndysAutoCopy.ini");
//Load the ini file
iniFile.load(iniFileInput);
//Read the source and destination directories
sourceDirectory = iniFile.getProperty("sourceDirectory");
destinationDirectory = iniFile.getProperty("destinationDirectory");
additionalDestinationDirectory = iniFile.getProperty("additionalDestinationDirectory");
GlobalCounters.loggingLevel = Integer.parseInt(iniFile.getProperty("loggingLevel"));
GlobalCounters.checkingInterval = Integer.parseInt(iniFile.getProperty("checkingInterval"));
//Display them just to be sure they are OK
LogMessage("Source directory is " + sourceDirectory,1);
LogMessage("Destination directory is " + destinationDirectory,1);
LogMessage("Additional destination directory is " + additionalDestinationDirectory,1);
LogMessage("Error logging level is " + GlobalCounters.loggingLevel,1);
LogMessage("Checking interval is " + GlobalCounters.checkingInterval,1);
LogMessage("",1);
} catch (IOException ex) {
LogMessage("Error opening ini file",0);
ex.printStackTrace();
return;
}
// Check the destination directories exist. If not, post message and abort.
destinationFolder = new File(destinationDirectory);
additionalDestinationFolder = new File(additionalDestinationDirectory);
if (destinationFolder.exists() == false){
LogMessage("Destination directory does not exists: " + destinationDirectory,0);
LogMessage("Aborting",0);
System.exit(0);
}
if (additionalDestinationFolder.exists() == false){
LogMessage("Additional destination directory does not exists: " + additionalDestinationDirectory,0);
LogMessage("Aborting",0);
System.exit(0);
}
//Start the checking loop. Do we make the loop infinite?
//If the source directory exists, check it. If not, it indicates the card hasn't been inserted
sourceFolder = new File(sourceDirectory);
while(true){
GlobalCounters.numberOfChecks++;
if (sourceFolder.exists()){
//The folder does exist, so reset counters, make a beep noise and start checking for locked files.
LogMessage(sourceFolder.getPath() + " exists - reading directory",1);
Beeper();
GlobalCounters.totalFilesCopied = 0;
//Do the actual check here
FindAndCopy(sourceDirectory, destinationDirectory, additionalDestinationDirectory);
if (GlobalCounters.totalFilesCopied > 0) {
LogMessage("",1);
LogMessage("+++ File Copy Complete. " + GlobalCounters.totalFilesCopied + " files copied successfully",1);
LogMessage("",1);
}
}
else {
//Folder doesn't exist so log that and continue
LogMessage("Checking loop " + GlobalCounters.numberOfChecks + ": " + sourceFolder.getPath() + " not found.",1);
}
LogMessage("Waiting to re-check",3);
try {
Thread.sleep(GlobalCounters.checkingInterval);
} catch (InterruptedException ex) {
Logger.getLogger(AndysAutoCopy.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
public static void Beeper() {
/* Makes a beep noise using the standard windows default beep sound that can be changed in Control Panel */
Toolkit.getDefaultToolkit().beep();
}
public static void FindAndCopy(String sourceDirectory, String destinationDirectory, String additionalDestinationDirectory) throws IOException{
/* Get list of files in a directory. Note this is a recursive routine and */
/* it will call itself if it finds a directory in the list of files. That */
/* directory will then become the new sourceDirectory and so on until the */
/* all files & directories in the tree have been exhausted. */
Path newFileLocation;
Path oldFileLocation;
Path additionalFileLocation;
File folder = new File(sourceDirectory);
// Get the list of files in the direcory
File[] listOfFiles = folder.listFiles();
LogMessage("Checking " + listOfFiles.length + " entries.", 2);
//Loop through the list of files in this directory
for (int i=0; i < listOfFiles.length; i++){
//For each entry, check if it is a directory
if (listOfFiles.isDirectory()) {
//It is a directory, so run a recursive call to get all the files in this directory and so on
LogMessage(listOfFiles.getPath() + " is a directory",3);
FindAndCopy (listOfFiles.getPath(), destinationDirectory, additionalDestinationDirectory);
}
else {
if (IsItReadOnly(listOfFiles.getPath())){
// File is read only so copy check if it has already been copied
//Need to loop through the list of files copied and see if this one has already been copied.
if (!GlobalCounters.listOfAllCopiedFiles.contains(listOfFiles.getName())) {
//File hasn't been copied before, so go ahead and copy it now
oldFileLocation = FileSystems.getDefault().getPath(listOfFiles.getPath());
newFileLocation = FileSystems.getDefault().getPath(destinationDirectory, listOfFiles.getName());
if (Files.exists(newFileLocation)) {
LogMessage("Locked file " + oldFileLocation + " already exists - skipped",2);
}
else {
//Execute the actual file copy here
Files.copy (oldFileLocation, newFileLocation);
LogMessage(">>> Locked file " + oldFileLocation + " copied to " + newFileLocation, 1);
//Need to set the Read Only attribute to FALSE on the destination file otherwise LR doesn't pick it up.
Files.setAttribute(newFileLocation, "dos:readonly", false);
LogMessage(newFileLocation + " set to writable",2);
if (additionalDestinationDirectory != null){
//User has asked for the file to also be copied to an additional place
additionalFileLocation = FileSystems.getDefault().getPath(additionalDestinationDirectory, listOfFiles.getName());
if (Files.exists(additionalFileLocation)) {
LogMessage("File also exists in the additional location - skipped", 2);
}
else {
// File doesn't exist in the destination directory, so execute the copy and set read only to FALSE
LogMessage("Additional directory specified - copying..." + oldFileLocation + " to " + additionalFileLocation, 2);
Files.copy(oldFileLocation, additionalFileLocation);
Files.setAttribute(additionalFileLocation, "dos:readonly", false);
LogMessage("...and also copied to " + additionalFileLocation, 1);
}
}
//Add the file name into the array of copied files to avoid repeat copying
GlobalCounters.listOfAllCopiedFiles.add(listOfFiles.getName());
LogMessage("Length of listOfAllCopiedFiles is " + GlobalCounters.listOfAllCopiedFiles.size(),3);
Beeper();
GlobalCounters.totalFilesCopied++;
}
}
else {
LogMessage(listOfFiles.getPath() + " already copied this session - skipped",2);
}
}
else {
LogMessage(listOfFiles.getPath() + " is NOT read only - skipped",3);
}
}
}
}
public static boolean IsItReadOnly(String TheFileName){
/* Takes in a filename and checks if it is read only or not*/
Path FilePath;
DosFileAttributes TheDosFileAttributes = null;
boolean ReadOnlyFlag;
FilePath = java.nio.file.FileSystems.getDefault().getPath(TheFileName);
try {
TheDosFileAttributes = java.nio.file.Files.readAttributes(FilePath, DosFileAttributes.class);
ReadOnlyFlag = TheDosFileAttributes.isReadOnly();
return ReadOnlyFlag;
} catch (IOException ex) {
LogMessage("Error in IsItReadOnly trying to get that ReadOnlyFlag",0);
Logger.getLogger(AndysAutoCopy.class.getName()).log(Level.SEVERE, null, ex);
}
return false;
}
public static void LogMessage(String theMessage, int thisLogLevel){
if (GlobalCounters.loggingLevel >= thisLogLevel){
System.out.println(theMessage);
}
}
}