1 package org.junit.runner.notification;
2
3 import static java.util.Arrays.asList;
4
5 import java.util.ArrayList;
6 import java.util.List;
7 import java.util.concurrent.CopyOnWriteArrayList;
8
9 import org.junit.runner.Description;
10 import org.junit.runner.Result;
11
12
13
14
15
16
17
18
19
20
21 public class RunNotifier {
22 private final List<RunListener> listeners = new CopyOnWriteArrayList<RunListener>();
23 private volatile boolean pleaseStop = false;
24
25
26
27
28 public void addListener(RunListener listener) {
29 if (listener == null) {
30 throw new NullPointerException("Cannot add a null listener");
31 }
32 listeners.add(wrapIfNotThreadSafe(listener));
33 }
34
35
36
37
38 public void removeListener(RunListener listener) {
39 if (listener == null) {
40 throw new NullPointerException("Cannot remove a null listener");
41 }
42 listeners.remove(wrapIfNotThreadSafe(listener));
43 }
44
45
46
47
48
49 RunListener wrapIfNotThreadSafe(RunListener listener) {
50 return listener.getClass().isAnnotationPresent(RunListener.ThreadSafe.class) ?
51 listener : new SynchronizedRunListener(listener, this);
52 }
53
54
55 private abstract class SafeNotifier {
56 private final List<RunListener> currentListeners;
57
58 SafeNotifier() {
59 this(listeners);
60 }
61
62 SafeNotifier(List<RunListener> currentListeners) {
63 this.currentListeners = currentListeners;
64 }
65
66 void run() {
67 int capacity = currentListeners.size();
68 ArrayList<RunListener> safeListeners = new ArrayList<RunListener>(capacity);
69 ArrayList<Failure> failures = new ArrayList<Failure>(capacity);
70 for (RunListener listener : currentListeners) {
71 try {
72 notifyListener(listener);
73 safeListeners.add(listener);
74 } catch (Exception e) {
75 failures.add(new Failure(Description.TEST_MECHANISM, e));
76 }
77 }
78 fireTestFailures(safeListeners, failures);
79 }
80
81 abstract protected void notifyListener(RunListener each) throws Exception;
82 }
83
84
85
86
87 public void fireTestRunStarted(final Description description) {
88 new SafeNotifier() {
89 @Override
90 protected void notifyListener(RunListener each) throws Exception {
91 each.testRunStarted(description);
92 }
93 }.run();
94 }
95
96
97
98
99 public void fireTestRunFinished(final Result result) {
100 new SafeNotifier() {
101 @Override
102 protected void notifyListener(RunListener each) throws Exception {
103 each.testRunFinished(result);
104 }
105 }.run();
106 }
107
108
109
110
111
112
113
114 public void fireTestStarted(final Description description) throws StoppedByUserException {
115 if (pleaseStop) {
116 throw new StoppedByUserException();
117 }
118 new SafeNotifier() {
119 @Override
120 protected void notifyListener(RunListener each) throws Exception {
121 each.testStarted(description);
122 }
123 }.run();
124 }
125
126
127
128
129
130
131 public void fireTestFailure(Failure failure) {
132 fireTestFailures(listeners, asList(failure));
133 }
134
135 private void fireTestFailures(List<RunListener> listeners,
136 final List<Failure> failures) {
137 if (!failures.isEmpty()) {
138 new SafeNotifier(listeners) {
139 @Override
140 protected void notifyListener(RunListener listener) throws Exception {
141 for (Failure each : failures) {
142 listener.testFailure(each);
143 }
144 }
145 }.run();
146 }
147 }
148
149
150
151
152
153
154
155
156 public void fireTestAssumptionFailed(final Failure failure) {
157 new SafeNotifier() {
158 @Override
159 protected void notifyListener(RunListener each) throws Exception {
160 each.testAssumptionFailure(failure);
161 }
162 }.run();
163 }
164
165
166
167
168
169
170 public void fireTestIgnored(final Description description) {
171 new SafeNotifier() {
172 @Override
173 protected void notifyListener(RunListener each) throws Exception {
174 each.testIgnored(description);
175 }
176 }.run();
177 }
178
179
180
181
182
183
184
185
186 public void fireTestFinished(final Description description) {
187 new SafeNotifier() {
188 @Override
189 protected void notifyListener(RunListener each) throws Exception {
190 each.testFinished(description);
191 }
192 }.run();
193 }
194
195
196
197
198
199
200
201 public void pleaseStop() {
202 pleaseStop = true;
203 }
204
205
206
207
208 public void addFirstListener(RunListener listener) {
209 if (listener == null) {
210 throw new NullPointerException("Cannot add a null listener");
211 }
212 listeners.add(0, wrapIfNotThreadSafe(listener));
213 }
214 }