package ch.cyberduck.ui; /* * Copyright (c) 2009 David Kocher. All rights reserved. * http://cyberduck.ch/ * * 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. * * Bug fixes, suggestions and comments should be sent to: * dkocher@cyberduck.ch */ import ch.cyberduck.core.threading.BackgroundAction; import ch.cyberduck.core.threading.DefaultMainAction; import ch.cyberduck.core.threading.MainAction; import ch.cyberduck.core.threading.ThreadPool; import org.apache.log4j.Logger; import org.rococoa.internal.OperationBatcher; //import org.rococoa.internal.OperationBatcher; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; /** * @version $Id$ */ public abstract class AbstractController implements Controller { private static Logger log = Logger.getLogger(AbstractController.class); /** * * @param runnable The action to execute */ public void invoke(MainAction runnable) { this.invoke(runnable, true); } /** * Will queue up the <code>BackgroundAction</code> to be run in a background thread. Will be executed * as soon as no other previous <code>BackgroundAction</code> is pending. * Will return immediatly but not run the runnable before the lock of the runnable is acquired. * * @param runnable The runnable to execute in a secondary Thread * @see java.lang.Thread * @see ch.cyberduck.core.threading.BackgroundAction#lock() */ public void background(final BackgroundAction runnable) { if(log.isDebugEnabled()) { log.debug("background:" + runnable); } runnable.init(); // Start background task Runnable command = new Runnable() { public void run() { // Synchronize all background threads to this lock so actions run // sequentially as they were initiated from the main interface thread synchronized(runnable.lock()) { final OperationBatcher autorelease = AbstractController.this.getBatcher(); if(log.isDebugEnabled()) { log.debug("Acquired lock for background runnable:" + runnable); } try { if(runnable.prepare()) { // Execute the action of the runnable runnable.run(); } } finally { // Increase the run counter runnable.finish(); // Invoke the cleanup on the main thread to let the action synchronize the user interface invoke(new DefaultMainAction() { public void run() { runnable.cleanup(); } }); if(log.isDebugEnabled()) { log.debug("Releasing lock for background runnable:" + runnable); } autorelease.operate(); } } } }; ThreadPool.instance().execute(command); log.info("Scheduled background runnable for execution:" + runnable); } /** * @uml.property name="timerPool" */ private static ScheduledExecutorService timerPool; /** * @return * @uml.property name="timerPool" */ protected ScheduledExecutorService getTimerPool() { if(null == timerPool) { timerPool = Executors.newScheduledThreadPool(1); } return timerPool; } /** * Placeholder implementation * @uml.property name="b" * @uml.associationEnd */ private final OperationBatcher b = new OperationBatcher(0) { @Override protected void operation() { ; } @Override protected void reset() { ; } }; protected OperationBatcher getBatcher() { return this.getBatcher(1); } protected OperationBatcher getBatcher(int size) { return b; } }