/* * 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 Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * For information about the authors of this project Have a look * at the AUTHORS file in the root of this project. */ package net.sourceforge.fullsync.impl; import java.io.IOException; import java.util.ArrayList; import net.sourceforge.fullsync.Action; import net.sourceforge.fullsync.BufferUpdate; import net.sourceforge.fullsync.ExceptionHandler; import net.sourceforge.fullsync.IoStatistics; import net.sourceforge.fullsync.Location; import net.sourceforge.fullsync.Task; import net.sourceforge.fullsync.TaskExecutor; import net.sourceforge.fullsync.TaskFinishedEvent; import net.sourceforge.fullsync.TaskFinishedListener; import net.sourceforge.fullsync.TaskTree; import net.sourceforge.fullsync.buffer.ExecutionBuffer; import net.sourceforge.fullsync.fs.File; public class FillBufferTaskExecutor implements TaskExecutor { private ArrayList<TaskFinishedListener> listeners; private boolean statisticsOnly; private IoStatisticsImpl stats; private ExecutionBuffer buffer; public FillBufferTaskExecutor(ExecutionBuffer buffer) { this.listeners = new ArrayList<TaskFinishedListener>(); this.statisticsOnly = false; this.buffer = buffer; buffer.addEntryFinishedListener((entry, ioe) -> { Task task = entry.getTask(); if (null != task) { if (null != ioe) { fireTaskFinished(new TaskFinishedEvent(task, ioe.getLocalizedMessage())); } else { fireTaskFinished(new TaskFinishedEvent(task, 0)); } } }); } @Override public IoStatistics createStatistics(TaskTree tree) { statisticsOnly = true; enqueue(tree); statisticsOnly = false; return stats; } @Override public void enqueue(TaskTree tree) { stats = new IoStatisticsImpl(); enqueue(tree.getRoot()); } protected void enqueueTaskChildren(Task task) { for (Task t : task.getChildren()) { enqueue(t); } } @Override public void enqueue(Task task) { if (!task.getCurrentAction().isBeforeRecursion()) { enqueueTaskChildren(task); } executeTask(task); if (task.getCurrentAction().isBeforeRecursion()) { enqueueTaskChildren(task); } } protected void storeDirCreation(Task task, File subject) throws IOException { if (!statisticsOnly) { buffer.storeEntry(new DirCreationEntryDescriptor(task, subject)); } stats.dirsCreated++; } protected void storeFileCopy(Task task, File source, File destination) throws IOException { try { if (!statisticsOnly) { buffer.storeEntry(new FileCopyEntryDescriptor(task, source, destination)); } stats.filesCopied++; stats.bytesTransferred += source.getSize(); } catch (IOException ioe) { // FIXME that's not right, the task does not neccessarily be the one // that throws this exception as there are flushs involved fireTaskFinished(new TaskFinishedEvent(task, ioe.getMessage())); } } protected void storeDeleteNode(Task task, File subject) throws IOException { if (!statisticsOnly) { buffer.storeEntry(new DeleteNodeEntryDescriptor(task, subject)); } stats.deletions++; } protected void executeTask(Task task) { try { // TODO lock tasks here Action action = task.getCurrentAction(); File source = task.getSource(); File destination = task.getDestination(); switch (action.getType()) { case Add: case Update: if (action.getLocation() == Location.Destination) { if (source.isDirectory()) { storeDirCreation(task, destination); } else { storeFileCopy(task, source, destination); } } else if (action.getLocation() == Location.Source) { if (destination.isDirectory()) { storeDirCreation(task, source); } else { storeFileCopy(task, destination, source); } } break; case Delete: if (action.getLocation() == Location.Destination) { storeDeleteNode(task, destination); } else if (action.getLocation() == Location.Source) { storeDeleteNode(task, source); } break; default: break; } if ((action.getBufferUpdate() != BufferUpdate.None) && !statisticsOnly) { buffer.storeEntry(new BufferUpdateEntryDescriptor(source, destination, action.getBufferUpdate())); } } catch (IOException ioe) { ExceptionHandler.reportException(ioe); } } @Override public void flush() throws IOException { buffer.flush(); } protected void fireTaskFinished(TaskFinishedEvent event) { for (TaskFinishedListener listener : listeners) { listener.taskFinished(event); } } @Override public void addTaskFinishedListener(TaskFinishedListener listener) { listeners.add(listener); } @Override public void removeTaskFinishedListener(TaskFinishedListener listener) { listeners.remove(listener); } }