| /******************************************************************************* |
| * Copyright (c) 2014 Sam Davis and others. |
| * |
| * This program and the accompanying materials are made available under the |
| * terms of the Eclipse Public License v. 2.0 which is available at |
| * https://www.eclipse.org/legal/epl-2.0 |
| * |
| * SPDX-License-Identifier: EPL-2.0 |
| * |
| * Contributors: |
| * Sam Davis - initial API and implementation |
| *******************************************************************************/ |
| |
| package org.eclipse.mylyn.internal.bugzilla.rest.core; |
| |
| import java.util.Collections; |
| import java.util.List; |
| import java.util.concurrent.ExecutionException; |
| import java.util.concurrent.Executor; |
| import java.util.concurrent.TimeUnit; |
| import java.util.concurrent.TimeoutException; |
| |
| import org.eclipse.core.runtime.IStatus; |
| import org.eclipse.core.runtime.jobs.IJobChangeEvent; |
| import org.eclipse.core.runtime.jobs.Job; |
| import org.eclipse.core.runtime.jobs.JobChangeAdapter; |
| |
| import com.google.common.collect.Lists; |
| import com.google.common.util.concurrent.ListenableFuture; |
| |
| public abstract class ListenableFutureJob<V> extends Job implements ListenableFuture<V> { |
| |
| private class Listener { |
| |
| Runnable runnable; |
| |
| Executor executor; |
| |
| public Listener(Runnable runnable, Executor executor) { |
| this.runnable = runnable; |
| this.executor = executor; |
| } |
| |
| public void run() { |
| executor.execute(runnable); |
| } |
| } |
| |
| List<Listener> listeners = Collections.synchronizedList(Lists.<Listener> newArrayList()); |
| |
| private volatile boolean done; |
| |
| private V resultObject; |
| |
| public ListenableFutureJob(String name) { |
| super(name); |
| resultObject = null; |
| this.addJobChangeListener(new JobChangeAdapter() { |
| |
| @Override |
| public void done(IJobChangeEvent event) { |
| done = true; |
| synchronized (listeners) { |
| for (Listener listener : listeners) { |
| listener.run(); |
| } |
| } |
| } |
| }); |
| } |
| |
| @Override |
| public boolean cancel(boolean mayInterruptIfRunning) { |
| return this.cancel(); |
| } |
| |
| @Override |
| public V get() throws InterruptedException, ExecutionException { |
| this.join(); |
| return resultObject; |
| } |
| |
| @Override |
| public V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException { |
| long start = System.currentTimeMillis(); |
| while (!done && System.currentTimeMillis() - start < unit.toMillis(timeout)) { |
| Thread.sleep(250); |
| } |
| if (!done) { |
| throw new TimeoutException("ListenableFutureJob.get() could not get the result!"); |
| } |
| return resultObject; |
| } |
| |
| protected void set(V future) { |
| this.resultObject = future; |
| } |
| |
| @Override |
| public boolean isCancelled() { |
| return this.getResult().getSeverity() == IStatus.CANCEL; |
| } |
| |
| @Override |
| public boolean isDone() { |
| return done; |
| } |
| |
| @Override |
| public void addListener(Runnable listener, Executor executor) { |
| listeners.add(new Listener(listener, executor)); |
| } |
| } |