/* * JFileSync * Copyright (C) 2002-2007, Jens Heidrich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301, USA */ package jfs.conf; import java.io.File; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; import java.util.Map; import jfs.sync.JFSElement; import jfs.sync.JFSElement.ElementState; import jfs.sync.JFSRootElement; import jfs.sync.JFSTable; /** * Manager all histories of synchronized directory pairs. * * @author Jens Heidrich * @version $Id: JFSHistoryManager.java,v 1.8 2007/07/20 15:59:30 heidrich Exp $ */ public final class JFSHistoryManager { /** * Stores the only instance of the class. * * SingletonHolder is loaded on the first execution of JFSHistoryManager.getInstance() * or the first access to SingletonHolder.INSTANCE, not before. */ private static class SingletonHolder { public static final JFSHistoryManager INSTANCE = new JFSHistoryManager(); } /** * The stored histories. */ private final List<JFSHistory> histories = new ArrayList<>(); /** * Constructs a the only history manager. */ protected JFSHistoryManager() { // Avoid instanciation from outside } /** * Returns the reference of the only instance. * * @return The only instance. */ public static JFSHistoryManager getInstance() { return SingletonHolder.INSTANCE; } /** * Sorts all histories stored. */ public void sortHistories() { Collections.sort(histories); } /** * Returns the set of histories. * * @return The histories. */ public List<JFSHistory> getHistories() { return histories; } /** * Returns the history for a special directory pair. If no history is found, a new one is created and added to the * list of histories. * * @param pair * The directory pair to search the history for. * @return The history. */ public JFSHistory getHistory(JFSDirectoryPair pair) { for (JFSHistory h : histories) { if (h.getPair().equals(pair)) { return h; } } JFSHistory h = new JFSHistoryXML(); h.setPair(pair); histories.add(h); return h; } /** * Adds a special history. * * @param history * The history to add. */ public void addHistory(JFSHistory history) { histories.add(history); } /** * Deletes the history for a special history; that is, deletes the file, the history is stored to and removes the * history from the list of histories. * * @param history * The history to delete. */ public void deleteHistory(JFSHistory history) { deleteHistoryFile(history); history.clear(); histories.remove(history); } /** * Deletes all histories. * * @see #deleteHistory(JFSHistory) */ public void deleteAll() { for (JFSHistory h : histories) { deleteHistoryFile(h); h.clear(); } histories.clear(); } /** * Deletes the history file for a special history. * * @param history * The history to delete the corresponding file for. */ private void deleteHistoryFile(JFSHistory history) { File file = new File(JFSConst.HOME_DIR+File.separatorChar+history.getFileName()); if (file.exists()) { file.delete(); } } /** * Cleans the JFS configuration directory by cleaning all history files that are not referenced in the history * manager. */ public void cleanHistories() { List<String> historyFiles = new ArrayList<>(); for (JFSHistory h : getHistories()) { historyFiles.add(h.getFileName()); } File jfsDir = new File(JFSConst.HOME_DIR); for (File f : jfsDir.listFiles()) { String name = f.getName(); if (name.startsWith(JFSConst.HISTORY_FILE_PREFIX)&&name.endsWith(".xml")&&!historyFiles.contains(name)) { f.delete(); } } } /** * Updates and stores the currently managed histories with the synchronization table. If the element's files are * equal (identified by their equal time stamp), an existing history item has to be updated or a new one has to be * created. If a history item was found (and updated) or a new one was created, it is added to the new history. The * relative path is stored as well as the last modified date and the length. That means, if the JFS element's files * are not equal, the previous history item is kept as is. The latter can be caused by an interrupted or failed * synchronization process or if JFS elements are deactivated before synchronization. */ public void updateHistories() { JFSTable table = JFSTable.getInstance(); JFSHistory h = null; JFSRootElement root = null; List<JFSHistoryItem> newHistory = null; Map<String, JFSHistoryItem> newDirectories = null; Map<String, JFSHistoryItem> newFiles = null; for (int i = 0; i<table.getTableSize(); i++) { JFSElement element = table.getTableElement(i); // If root is found, update previous history and get new one: if (element.getState()==ElementState.IS_ROOT) { if (root!=null&&h!=null) { h.update(root, newHistory, newDirectories, newFiles); } root = (JFSRootElement) element; h = root.getHistory(); h.setDate(System.currentTimeMillis()); newHistory = new ArrayList<>(); newDirectories = new HashMap<>(); newFiles = new HashMap<>(); } JFSHistoryItem item = h.getHistory(element); // If the element's files are equal, an existing item has to be // updated or a new one has to be created: if (element.getState()==ElementState.EQUAL) { // Use the source file (which exists if both files are equal) // to construct the new history item: if (item==null) { item = new JFSHistoryItem(element.getRelativePath()); item.setDirectory(element.isDirectory()); } item.setLastModified(element.getSrcFile().getLastModified()); item.setLength(element.getSrcFile().getLength()); } // If a history item was found or a new one was created, add this // to the new history: if (item!=null) { newHistory.add(item); if (item.isDirectory()) { newDirectories.put(item.getRelativePath(), item); } else { newFiles.put(item.getRelativePath(), item); } } } // Update last history read: if (root!=null&&h!=null) { h.update(root, newHistory, newDirectories, newFiles); } } }