1 package org.apache.maven.plugin.surefire.booterclient.output;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.apache.maven.surefire.api.booter.ForkedProcessEventType;
23 import org.apache.maven.surefire.api.event.AbstractConsoleEvent;
24 import org.apache.maven.surefire.api.event.AbstractStandardStreamEvent;
25 import org.apache.maven.surefire.api.event.AbstractTestControlEvent;
26 import org.apache.maven.surefire.api.event.ConsoleErrorEvent;
27 import org.apache.maven.surefire.api.event.Event;
28 import org.apache.maven.surefire.api.event.JvmExitErrorEvent;
29 import org.apache.maven.surefire.api.event.SystemPropertyEvent;
30 import org.apache.maven.surefire.api.report.ReportEntry;
31 import org.apache.maven.surefire.api.report.RunMode;
32
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentMap;
35
36 import static java.util.Objects.requireNonNull;
37 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_BYE;
38 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_CONSOLE_DEBUG;
39 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_CONSOLE_INFO;
40 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_CONSOLE_WARNING;
41 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_NEXT_TEST;
42 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_STDERR;
43 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_STDERR_NEW_LINE;
44 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_STDOUT;
45 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_STDOUT_NEW_LINE;
46 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_STOP_ON_NEXT_TEST;
47 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TESTSET_COMPLETED;
48 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TESTSET_STARTING;
49 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_ASSUMPTIONFAILURE;
50 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_ERROR;
51 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_FAILED;
52 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_SKIPPED;
53 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_STARTING;
54 import static org.apache.maven.surefire.api.booter.ForkedProcessEventType.BOOTERCODE_TEST_SUCCEEDED;
55
56
57
58
59
60
61
62 public final class ForkedProcessEventNotifier
63 {
64 private volatile ForkedProcessPropertyEventListener propertyEventListener;
65 private volatile ForkedProcessStackTraceEventListener consoleErrorEventListener;
66 private volatile ForkedProcessExitErrorListener exitErrorEventListener;
67
68 private final ConcurrentMap<ForkedProcessEventType, ForkedProcessReportEventListener<?>> reportEventListeners =
69 new ConcurrentHashMap<>();
70
71 private final ConcurrentMap<ForkedProcessEventType, ForkedProcessStandardOutErrEventListener>
72 stdOutErrEventListeners = new ConcurrentHashMap<>();
73
74 private final ConcurrentMap<ForkedProcessEventType, ForkedProcessStringEventListener> consoleEventListeners =
75 new ConcurrentHashMap<>();
76
77 private final ConcurrentMap<ForkedProcessEventType, ForkedProcessEventListener> controlEventListeners =
78 new ConcurrentHashMap<>();
79
80 public void setSystemPropertiesListener( ForkedProcessPropertyEventListener listener )
81 {
82 propertyEventListener = requireNonNull( listener );
83 }
84
85 public <T extends ReportEntry> void setTestSetStartingListener( ForkedProcessReportEventListener<T> listener )
86 {
87 reportEventListeners.put( BOOTERCODE_TESTSET_STARTING, requireNonNull( listener ) );
88 }
89
90 public void setTestSetCompletedListener( ForkedProcessReportEventListener<?> listener )
91 {
92 reportEventListeners.put( BOOTERCODE_TESTSET_COMPLETED, requireNonNull( listener ) );
93 }
94
95 public void setTestStartingListener( ForkedProcessReportEventListener<?> listener )
96 {
97 reportEventListeners.put( BOOTERCODE_TEST_STARTING, requireNonNull( listener ) );
98 }
99
100 public void setTestSucceededListener( ForkedProcessReportEventListener<?> listener )
101 {
102 reportEventListeners.put( BOOTERCODE_TEST_SUCCEEDED, requireNonNull( listener ) );
103 }
104
105 public void setTestFailedListener( ForkedProcessReportEventListener<?> listener )
106 {
107 reportEventListeners.put( BOOTERCODE_TEST_FAILED, requireNonNull( listener ) );
108 }
109
110 public void setTestSkippedListener( ForkedProcessReportEventListener<?> listener )
111 {
112 reportEventListeners.put( BOOTERCODE_TEST_SKIPPED, requireNonNull( listener ) );
113 }
114
115 public void setTestErrorListener( ForkedProcessReportEventListener<?> listener )
116 {
117 reportEventListeners.put( BOOTERCODE_TEST_ERROR, requireNonNull( listener ) );
118 }
119
120 public void setTestAssumptionFailureListener( ForkedProcessReportEventListener<?> listener )
121 {
122 reportEventListeners.put( BOOTERCODE_TEST_ASSUMPTIONFAILURE, requireNonNull( listener ) );
123 }
124
125 public void setStdOutListener( ForkedProcessStandardOutErrEventListener listener )
126 {
127 stdOutErrEventListeners.put( BOOTERCODE_STDOUT, requireNonNull( listener ) );
128 stdOutErrEventListeners.put( BOOTERCODE_STDOUT_NEW_LINE, requireNonNull( listener ) );
129 }
130
131 public void setStdErrListener( ForkedProcessStandardOutErrEventListener listener )
132 {
133 stdOutErrEventListeners.put( BOOTERCODE_STDERR, requireNonNull( listener ) );
134 stdOutErrEventListeners.put( BOOTERCODE_STDERR_NEW_LINE, requireNonNull( listener ) );
135 }
136
137 public void setConsoleInfoListener( ForkedProcessStringEventListener listener )
138 {
139 consoleEventListeners.put( BOOTERCODE_CONSOLE_INFO, requireNonNull( listener ) );
140 }
141
142 public void setConsoleErrorListener( ForkedProcessStackTraceEventListener listener )
143 {
144 consoleErrorEventListener = requireNonNull( listener );
145 }
146
147 public void setConsoleDebugListener( ForkedProcessStringEventListener listener )
148 {
149 consoleEventListeners.put( BOOTERCODE_CONSOLE_DEBUG, requireNonNull( listener ) );
150 }
151
152 public void setConsoleWarningListener( ForkedProcessStringEventListener listener )
153 {
154 consoleEventListeners.put( BOOTERCODE_CONSOLE_WARNING, requireNonNull( listener ) );
155 }
156
157 public void setByeListener( ForkedProcessEventListener listener )
158 {
159 controlEventListeners.put( BOOTERCODE_BYE, requireNonNull( listener ) );
160 }
161
162 public void setStopOnNextTestListener( ForkedProcessEventListener listener )
163 {
164 controlEventListeners.put( BOOTERCODE_STOP_ON_NEXT_TEST, requireNonNull( listener ) );
165 }
166
167 public void setAcquireNextTestListener( ForkedProcessEventListener listener )
168 {
169 controlEventListeners.put( BOOTERCODE_NEXT_TEST, requireNonNull( listener ) );
170 }
171
172 public void setExitErrorEventListener( ForkedProcessExitErrorListener listener )
173 {
174 exitErrorEventListener = requireNonNull( listener );
175 }
176
177 public void notifyEvent( Event event )
178 {
179 ForkedProcessEventType eventType = event.getEventType();
180 if ( event.isControlCategory() )
181 {
182 ForkedProcessEventListener listener = controlEventListeners.get( eventType );
183 if ( listener != null )
184 {
185 listener.handle();
186 }
187 }
188 else if ( event.isConsoleErrorCategory() )
189 {
190 if ( consoleErrorEventListener != null )
191 {
192 consoleErrorEventListener.handle( ( ( ConsoleErrorEvent ) event ).getStackTraceWriter() );
193 }
194 }
195 else if ( event.isConsoleCategory() )
196 {
197 ForkedProcessStringEventListener listener = consoleEventListeners.get( eventType );
198 if ( listener != null )
199 {
200 listener.handle( ( (AbstractConsoleEvent) event ).getMessage() );
201 }
202 }
203 else if ( event.isStandardStreamCategory() )
204 {
205 boolean newLine = eventType == BOOTERCODE_STDOUT_NEW_LINE || eventType == BOOTERCODE_STDERR_NEW_LINE;
206 AbstractStandardStreamEvent standardStreamEvent = (AbstractStandardStreamEvent) event;
207 ForkedProcessStandardOutErrEventListener listener = stdOutErrEventListeners.get( eventType );
208 if ( listener != null )
209 {
210 listener.handle( standardStreamEvent.getMessage(), newLine,
211 standardStreamEvent.getRunMode(), standardStreamEvent.getTestRunId() );
212 }
213 }
214 else if ( event.isSysPropCategory() )
215 {
216 SystemPropertyEvent systemPropertyEvent = (SystemPropertyEvent) event;
217 RunMode runMode = systemPropertyEvent.getRunMode();
218 Long testRunId = systemPropertyEvent.getTestRunId();
219 String key = systemPropertyEvent.getKey();
220 String value = systemPropertyEvent.getValue();
221 if ( propertyEventListener != null )
222 {
223 propertyEventListener.handle( key, value, runMode, testRunId );
224 }
225 }
226 else if ( event.isTestCategory() )
227 {
228 ForkedProcessReportEventListener listener = reportEventListeners.get( eventType );
229 AbstractTestControlEvent testControlEvent = (AbstractTestControlEvent) event;
230 ReportEntry reportEntry = testControlEvent.getReportEntry();
231 if ( listener != null )
232 {
233 listener.handle( reportEntry );
234 }
235 }
236 else if ( event.isJvmExitError() )
237 {
238 JvmExitErrorEvent jvmExitErrorEvent = (JvmExitErrorEvent) event;
239 if ( exitErrorEventListener != null )
240 {
241 exitErrorEventListener.handle( jvmExitErrorEvent.getStackTraceWriter() );
242 }
243 }
244 else
245 {
246 throw new IllegalArgumentException( "Unknown event type " + eventType );
247 }
248 }
249 }