| /******************************************************************************* |
| * Copyright (c) 2008 EclipseSource 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: |
| * EclipseSource - initial API and implementation |
| ******************************************************************************/ |
| package org.eclipse.ecf.core.util; |
| |
| import org.eclipse.core.runtime.*; |
| import org.eclipse.ecf.internal.core.ECFPlugin; |
| |
| public class FutureStatus extends Status implements IFutureStatus { |
| |
| class FutureStatusProgressMonitor implements IProgressMonitor { |
| |
| private final IProgressMonitor monitor; |
| |
| public FutureStatusProgressMonitor(IProgressMonitor progressMonitor) { |
| this.monitor = progressMonitor; |
| } |
| |
| public void beginTask(String name, int totalWork) { |
| monitor.beginTask(name, totalWork); |
| } |
| |
| public void done() { |
| monitor.done(); |
| } |
| |
| public void internalWorked(double work) { |
| monitor.internalWorked(work); |
| } |
| |
| public boolean isCanceled() { |
| return monitor.isCanceled(); |
| } |
| |
| public void setCanceled(boolean value) { |
| monitor.setCanceled(value); |
| // If this is intended to cancel |
| // the operation, then we also call |
| // FutureStatus.this.setCanceled() |
| if (value) |
| FutureStatus.this.setCanceled(); |
| } |
| |
| public void setTaskName(String name) { |
| monitor.setTaskName(name); |
| } |
| |
| public void subTask(String name) { |
| monitor.subTask(name); |
| } |
| |
| public void worked(int work) { |
| monitor.worked(work); |
| } |
| |
| } |
| |
| private Object resultValue = null; |
| private boolean resultReady = false; |
| private int futureSeverity; |
| private IProgressMonitor progressMonitor = null; |
| |
| public FutureStatus(String pluginId, String message, IProgressMonitor progressMonitor) { |
| super(IStatus.OK, pluginId, message); |
| this.progressMonitor = new FutureStatusProgressMonitor((progressMonitor == null) ? new NullProgressMonitor() : progressMonitor); |
| setSeverity(IFutureStatus.IN_PROGRESS); |
| } |
| |
| public FutureStatus(String message, IProgressMonitor progressMonitor) { |
| this(ECFPlugin.PLUGIN_ID, message, progressMonitor); |
| } |
| |
| public FutureStatus(IProgressMonitor progressMonitor) { |
| this(null, progressMonitor); |
| } |
| |
| public FutureStatus() { |
| this(null); |
| } |
| |
| private void throwIfCanceled() throws CanceledException { |
| IProgressMonitor pm = getProgressMonitor(); |
| if (pm != null && pm.isCanceled()) |
| throw new CanceledException(this); |
| } |
| |
| public synchronized Object get() throws InterruptedException, CanceledException { |
| throwIfCanceled(); |
| while (!resultReady) |
| wait(); |
| throwIfCanceled(); |
| return resultValue; |
| } |
| |
| public synchronized Object get(long waitTimeInMillis) throws InterruptedException, TimeoutException, CanceledException { |
| long startTime = (waitTimeInMillis <= 0) ? 0 : System.currentTimeMillis(); |
| long waitTime = waitTimeInMillis; |
| throwIfCanceled(); |
| if (resultReady) |
| return resultValue; |
| else if (waitTime <= 0) |
| throw new TimeoutException(waitTimeInMillis); |
| else { |
| for (;;) { |
| wait(waitTime); |
| throwIfCanceled(); |
| if (resultReady) |
| return resultValue; |
| waitTime = waitTimeInMillis - (System.currentTimeMillis() - startTime); |
| if (waitTime <= 0) |
| throw new TimeoutException(waitTimeInMillis); |
| } |
| } |
| } |
| |
| public IProgressMonitor getProgressMonitor() { |
| return progressMonitor; |
| } |
| |
| public synchronized boolean isDone() { |
| return resultReady; |
| } |
| |
| synchronized void setCanceled() { |
| resultReady = true; |
| notifyAll(); |
| } |
| |
| /** |
| * Set the underlying function call that will return a result asynchronously |
| * |
| * @param function |
| * the {@link IFutureCallable} to be called |
| * @return Runnable to run in separate thread |
| */ |
| public Runnable setter(final IFutureCallable function) { |
| return new Runnable() { |
| public void run() { |
| try { |
| set(function.call(getProgressMonitor())); |
| } catch (Throwable ex) { |
| setException(ex); |
| } |
| } |
| }; |
| } |
| |
| protected synchronized void setSeverity(int severity) { |
| Assert.isTrue(severity == IStatus.OK || severity == IStatus.CANCEL || severity == IStatus.ERROR || severity == IStatus.INFO || severity == IStatus.WARNING || severity == IFutureStatus.IN_PROGRESS); |
| this.futureSeverity = severity; |
| } |
| |
| public synchronized int getSeverity() { |
| return futureSeverity; |
| } |
| |
| public synchronized void setException(Throwable ex) { |
| super.setException(ex); |
| resultReady = true; |
| setSeverity(IStatus.ERROR); |
| notifyAll(); |
| } |
| |
| public synchronized void set(Object newValue) { |
| resultValue = newValue; |
| resultReady = true; |
| setSeverity(IStatus.OK); |
| notifyAll(); |
| } |
| |
| } |