blob: 9e47230344dec2d825bb08d7e7b8340d17aeedae [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2009, 2013 Tasktop Technologies and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.commons.core.operations;
import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.mylyn.commons.core.StatusHandler;
import org.eclipse.mylyn.internal.commons.core.CommonsCorePlugin;
import org.eclipse.osgi.util.NLS;
/**
* Intended to be implemented by high-level operation that run on a single thread.
*
* @author Steffen Pingel
* @since 3.7
* @see OperationUtil#execute(IProgressMonitor, Operation)
*/
public abstract class MonitoredOperation<T> extends Operation<T> implements ICancellableOperation {
private static ThreadLocal<MonitoredOperation<?>> currentOperation = new ThreadLocal<MonitoredOperation<?>>();
/**
* Returns the operation that is associated with the current thread.
*/
public static MonitoredOperation<?> getCurrentOperation() {
return currentOperation.get();
}
/**
* Sets <code>operation</code> as the operation associated with the current thread.
*/
static void setCurrentOperation(MonitoredOperation<?> operation) {
if (operation != null && currentOperation.get() != null) {
StatusHandler.log(new Status(IStatus.ERROR, CommonsCorePlugin.ID_PLUGIN, NLS.bind(
"Unexpected operation already in progress ''{0}''", currentOperation.get()), //$NON-NLS-1$
new IllegalStateException()));
}
currentOperation.set(operation);
}
private final CopyOnWriteArrayList<ICancellable> listeners = new CopyOnWriteArrayList<ICancellable>();
private final IProgressMonitor monitor;
public MonitoredOperation(IProgressMonitor monitor) {
Assert.isNotNull(monitor);
this.monitor = monitor;
}
@Override
public void abort() {
for (ICancellable listener : listeners.toArray(new ICancellable[0])) {
try {
listener.abort();
} catch (Exception e) {
// ignore
}
}
}
/**
* @since 3.9
*/
@Override
public boolean isCanceled() {
return monitor.isCanceled();
}
public void addListener(ICancellable listener) {
listeners.add(listener);
}
public T call() throws Exception {
try {
assert MonitoredOperation.getCurrentOperation() == null;
MonitoredOperation.setCurrentOperation(this);
return execute();
} finally {
MonitoredOperation.setCurrentOperation(null);
listeners.clear();
}
}
public IProgressMonitor getMonitor() {
return monitor;
}
public void removeListener(ICancellable listener) {
listeners.remove(listener);
}
protected abstract T execute() throws Exception;
}