package de.grey.ownsync;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.Properties;
import org.apache.commons.vfs.FileObject;
import org.apache.commons.vfs.FileSystemException;
import de.grey.ownsync.config.FolderConfiguration;
import de.grey.ownsync.exception.OwnSyncException;
import de.grey.ownsync.facade.OwnSyncStatus;
import de.grey.ownsync.pattern.SyncExclusionPatterns;
import de.grey.ownsync.utils.DataFormatter;
import de.grey.ownsync.utils.FileStateHashMap;
import de.grey.ownsync.utils.FileUtils;
import de.grey.ownsync.utils.PropertiesHelper;
/**
* @author wogy
*/
public class FolderState
{
final private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy.MM.dd HH:mm:ss");
final private static String SCANTIME = "ScanTime";
private FileStateHashMap newFolderState = new FileStateHashMap();
private FileStateHashMap oldFolderState = new FileStateHashMap();
private HashMap comparedFolderState;
private String lastSyncDate = null;
private FolderConfiguration folderConfiguration;
/**
* @throws OwnSyncException
* @throws FileSystemException
*
*/
public FolderState(FolderConfiguration folderConfiguration) throws OwnSyncException, FileSystemException
{
this.folderConfiguration = folderConfiguration;
if (!getFolderStateFile().exists() || FileUtils.getSize(getFolderStateFile()) == 0)
{
oldFolderState = scanFolderState(oldFolderState);
writeFolderState(oldFolderState, getFolderStateFile());
newFolderState = (FileStateHashMap) oldFolderState.clone();
}
else
{
newFolderState = scanFolderState(newFolderState);
oldFolderState = loadFolderState(getFolderStateFile());
}
comparedFolderState = compareOldStateWithNewState();
}
private FileStateHashMap scanFolderState(FileStateHashMap folderState) throws OwnSyncException, FileSystemException
{
OwnSyncStatus.setMessage("Scanning " + FileUtils.getAbsolutePath(getFolderLocation()));
long start = System.currentTimeMillis();
ScanFolderState scanFolderState = new ScanFolderState(folderState, folderConfiguration);
FileStateHashMap props = scanFolderState.scan();
OwnSyncStatus.appendToMessage(" took " + DataFormatter.getTimeString(System.currentTimeMillis() - start));
OwnSyncStatus.setMessage("---------------------------------------------------------");
OwnSyncStatus.setMessage("Found:\t\t files: " + scanFolderState.getFileCount() + "\t\t folders: " + scanFolderState.getDirectoryCount());
OwnSyncStatus.setMessage("---------------------------------------------------------");
return props;
}
private HashMap compareOldStateWithNewState()
{
OwnSyncStatus.setMessage("Comparing old and current folder state for folder " + getFolderLocation());
long start = System.currentTimeMillis();
// String lastSyncDate = getLastSyncDate(oldFolderState);
oldFolderState.remove(SCANTIME);
newFolderState.remove(SCANTIME);
HashMap allFolders = new HashMap(oldFolderState);
allFolders.putAll(newFolderState);
String key;
byte modified;
FileState oldFileState;
FileState newFileState;
ArrayList list = new ArrayList(allFolders.keySet());
for (int i = 0; i < list.size(); i++)
{
key = (String) list.get(i);
oldFileState = oldFolderState.get(key);
newFileState = newFolderState.get(key);
modified = FileState.compareTo(newFileState, oldFileState);
((FileState) allFolders.get(key)).setModifications(modified);
}
// Wird nicht mehr gebraucht;
oldFolderState.clear();
oldFolderState = null;
// free memory (if possible)
System.gc();
OwnSyncStatus.appendToMessage(" took " + DataFormatter.getTimeString(System.currentTimeMillis() - start));
if (lastSyncDate != null)
OwnSyncStatus.setMessage("Last sync was at " + lastSyncDate);
else
OwnSyncStatus.setMessage("This is the first sync");
return allFolders;
}
private void writeFolderState(HashMap folderState, FileObject storeInFile) throws FileSystemException
{
OwnSyncStatus.setMessage("Writing folder state to file " + FileUtils.getAbsolutePath(storeInFile));
long start = System.currentTimeMillis();
Properties folderStateStringProperties = new Properties();
ArrayList list = new ArrayList(folderState.keySet());
for (int i = 0; i < list.size(); i++)
{
folderStateStringProperties.put(list.get(i), ((FileState) folderState.get(list.get(i))).toString());
}
setLastSyncDate(folderStateStringProperties);
if (!storeInFile.exists())
storeInFile.createFile();
BufferedOutputStream bos = null;
try
{
bos = new BufferedOutputStream(storeInFile.getContent().getOutputStream());
folderStateStringProperties = PropertiesHelper.storeToXML(folderStateStringProperties, bos, "OwnSync Folder snapshot description\n(C) Wilko Grey");
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if (bos != null)
bos.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
OwnSyncStatus.appendToMessage(" took " + DataFormatter.getTimeString(System.currentTimeMillis() - start));
}
public FileStateHashMap loadFolderState(FileObject readFromFile) throws FileSystemException
{
OwnSyncStatus.setMessage("Reading old folder state from file " + FileUtils.getAbsolutePath(readFromFile));
long start = System.currentTimeMillis();
Properties folderStateProperties = new Properties();
FileStateHashMap folderState = null;
BufferedInputStream bis = null;
try
{
bis = new BufferedInputStream(readFromFile.getContent().getInputStream());
folderStateProperties = PropertiesHelper.loadFromXML(folderStateProperties, bis);
String key;
ArrayList list = new ArrayList(folderStateProperties.keySet());
folderState = new FileStateHashMap(list.size());
for (int i = 0; i < list.size(); i++)
{
key = (String) list.get(i);
if (SCANTIME.equals(key))
{
lastSyncDate = (String) folderStateProperties.get(key);
continue;
}
try
{
folderState.put(key, new FileState((String) folderStateProperties.get(key), getTrashbox()));
}
catch (java.lang.StringIndexOutOfBoundsException e)
{
folderState.put(key, folderStateProperties.get(key));
}
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
if (bis != null)
bis.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
OwnSyncStatus.appendToMessage(" took " + DataFormatter.getTimeString(System.currentTimeMillis() - start));
// OwnSyncStatus.setMessage("Last Sync was at " + getLastSyncDate(folderStateProperties));
return folderState;
}
public HashMap getComparedFolderState()
{
return comparedFolderState;
}
public HashMap getNewFolderState()
{
return newFolderState;
}
public void writeChangedFolderState() throws OwnSyncException, FileSystemException
{
writeFolderState(newFolderState, getFolderStateFile());
}
public void addFileState2NewFolderState(FileObject file) throws Exception
{
newFolderState.put(FileUtils.getAbsolutePath(file), new FileState(file, getFolderLocation(), getTrashbox(), getLastModifiedDelta()));
}
public FileObject getFolderLocation()
{
return folderConfiguration.getSyncFolder();
}
public FileObject getFolderStateFile()
{
return folderConfiguration.getFolderStateFile();
}
public SyncTrashbox getTrashbox()
{
return folderConfiguration.getTrashbox();
}
public SyncExclusionPatterns getSyncExclusionPatterns()
{
return folderConfiguration.getSyncExclusionPatterns();
}
public long getLastModifiedDelta()
{
return folderConfiguration.getLastModifiedDelta();
}
private void setLastSyncDate(Properties folderStateProperties)
{
folderStateProperties.put(SCANTIME, sdf.format(new Date()));
}
}