package ie.dcu.apps.ist.recent; import java.io.*; import java.util.*; import java.util.logging.*; /** * Class for managing a recent documents list. * * @author Kevin McGuinness */ public class RecentFiles implements Iterable { public static final int DEFAULT_CAPACITY = 10; private final LinkedList history; private final List listeners; private final File store; private int capacity; public RecentFiles(File store) { // Check the store is ok checkValid(store); // Construct this.history = new LinkedList(); this.listeners = new LinkedList(); this.store = store; this.capacity = DEFAULT_CAPACITY; // Add a vm shutdown hook addShutdownHook(); } public void setCapacity(int capacity) { // Check positive if (capacity < 0) { throw new IllegalArgumentException("capacity < 0"); } if (this.capacity != capacity) { this.capacity = capacity; // Capacity may have reduced boolean reduced = history.size() > capacity; while (history.size() > capacity) { history.removeLast(); } // Fire change if (reduced) { fireHistoryChanged(); } } } public int getCapacity() { return capacity; } public void add(File file) { if (!history.contains(file)) { history.addFirst(file); // Check if we have exceeded capacity if (history.size() > capacity) { history.removeLast(); } // Fire change fireHistoryChanged(); } } public void clear() { if (!empty()) { history.clear(); fireHistoryChanged(); } } public List files() { return Collections.unmodifiableList(history); } public Iterator iterator() { return files().iterator(); } public boolean empty() { return history.isEmpty(); } public void load() throws IOException { if (!store.exists()) { // Create an empty store store.createNewFile(); } BufferedReader in = null; try { read(in = new BufferedReader(new FileReader(store))); } finally { in.close(); } } public void store() throws IOException { PrintWriter out = null; try { write(out = new PrintWriter(store)); } finally { out.close(); } } public void addListener(RecentFilesListener rfl) { listeners.add(rfl); } public void removeListener(RecentFilesListener rfl) { listeners.remove(rfl); } protected static Logger getLogger() { return Logger.getLogger(RecentFiles.class.getName()); } private void shutdown() { try { store(); } catch (IOException e) { getLogger().warning("Error writing recent documents to store: " + e); } } private void fireHistoryChanged() { RecentFilesEvent evt = null; for (RecentFilesListener listener : listeners) { if (evt == null) { evt = new RecentFilesEvent(this); listener.historyChanged(evt); } } } private void checkValid(File store) { if (store == null) { throw new IllegalArgumentException("store cannot be null"); } if (store.isDirectory()) { throw new IllegalArgumentException("store cannot be a directory"); } if (store.isFile()) { if (!store.canWrite()) { throw new IllegalArgumentException("store not writable"); } } } private void addShutdownHook() { Runtime.getRuntime().addShutdownHook(new Thread() { public void run() { shutdown(); } }); } private void read(BufferedReader in) throws IOException { // Remember old history to check for changes LinkedList old = new LinkedList(history); // Clear history if not empty history.clear(); // Read files (discarding no longer existent ones) String line; while ((line = in.readLine()) != null) { // Stop when full if (history.size() == capacity) { break; } File file = new File(line); if (file.exists()) { history.add(file); } } // Fire change if a change occurred if (!history.equals(old)) { fireHistoryChanged(); } } private void write(PrintWriter out) throws IOException { for (File file : history) { String path = file.getAbsolutePath(); out.println(path); } // Check for errors if (out.checkError()) { throw new IOException("Error writing to file"); } } }