This repository has been archived by the owner on Oct 13, 2020. It is now read-only.
/
AbstractTask.java
126 lines (99 loc) · 2.83 KB
/
AbstractTask.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/**
*
*/
package com.jakeapp.gui.swing.worker.tasks;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Semaphore;
import javax.swing.SwingWorker;
import org.apache.log4j.Logger;
import com.jakeapp.availablelater.AvailabilityListener;
import com.jakeapp.availablelater.AvailableLaterObject;
import com.jakeapp.availablelater.StatusUpdate;
import com.jakeapp.gui.swing.dialogs.debugging.ActiveTasks;
import com.jakeapp.gui.swing.worker.JakeExecutor;
/**
* So you wanted to make a SwingWorker, and your inner method gets back a
* {@link com.jakeapp.core.util.availablelater.AvailableLaterObject}. This resolves this double-Thread waiting
* problem. You only have to implement {@link #calculateFunction()} (instead of
* doInBackground) and {@link #done()} as usual.
*
* @author johannes
* @param <T>
*/
public abstract class AbstractTask<T> extends
SwingWorker<T, StatusUpdate> implements AvailabilityListener<T>, IJakeTask {
private static final Logger log = Logger.getLogger(AbstractTask.class);
private Semaphore s = new Semaphore(0);
private AvailableLaterObject<T> value;
private Exception exception;
private double progress;
private String status;
private StackTraceElement[] callerStackTrace = new Throwable().getStackTrace();
@Override
final protected T doInBackground() throws Exception {
try {
this.value = calculateFunction();
} catch (Exception e) {
error(e);
}
this.value.setListener(this);
this.value.start();
s.acquire();
if (exception != null)
throw exception;
return this.value.get();
}
abstract protected AvailableLaterObject<T> calculateFunction() throws RuntimeException;
@Override
final public void error(Exception t) {
try {
this.exception = t;
s.release();
}
finally {
JakeExecutor.removeTask(this);
}
}
@Override
final public void finished(T o) {
s.release();
}
@Override
final protected void done() {
try {
onDone();
}
finally {
JakeExecutor.removeTask(this);
}
}
protected void onDone() {
}
@Override
final public void statusUpdate(double progress, String status) {
this.progress = progress;
this.status = status;
publish(new StatusUpdate(progress, status));
// HACK to show tasks
ActiveTasks.tasksUpdated();
}
final protected void handleInterruption(InterruptedException e) {
log.warn("Swingworker has been interrupted: " + e.getMessage(), e);
}
final protected void handleExecutionError(ExecutionException e) {
log.warn("Swingworker execution failed: " + e.getMessage(), e);
}
@Override
public String toString() {
return (value != null ? value.toString() : "") + ": " + progress + " " + status;
}
@Override
public int hashCode() {
// Fixme: is this a good idea?
return getClass().toString().hashCode();
}
@Override
final public Exception getException() {
return this.exception;
}
}