View Javadoc
1   package org.apache.maven.plugin.surefire.booterclient.output;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *     http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
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   * magic number : run mode : opcode [: opcode specific data]*
58   *
59   * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
60   * @since 3.0.0-M4
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.getRunMode(), standardStreamEvent.getMessage(), newLine );
211             }
212         }
213         else if ( event.isSysPropCategory() )
214         {
215             SystemPropertyEvent systemPropertyEvent = (SystemPropertyEvent) event;
216             RunMode runMode = systemPropertyEvent.getRunMode();
217             String key = systemPropertyEvent.getKey();
218             String value = systemPropertyEvent.getValue();
219             if ( propertyEventListener != null )
220             {
221                 propertyEventListener.handle( runMode, key, value );
222             }
223         }
224         else if ( event.isTestCategory() )
225         {
226             ForkedProcessReportEventListener listener = reportEventListeners.get( eventType );
227             AbstractTestControlEvent testControlEvent = (AbstractTestControlEvent) event;
228             RunMode mode = testControlEvent.getRunMode();
229             ReportEntry reportEntry = testControlEvent.getReportEntry();
230             if ( listener != null )
231             {
232                 listener.handle( mode, reportEntry );
233             }
234         }
235         else if ( event.isJvmExitError() )
236         {
237             JvmExitErrorEvent jvmExitErrorEvent = (JvmExitErrorEvent) event;
238             if ( exitErrorEventListener != null )
239             {
240                 exitErrorEventListener.handle( jvmExitErrorEvent.getStackTraceWriter() );
241             }
242         }
243         else
244         {
245             throw new IllegalArgumentException( "Unknown event type " + eventType );
246         }
247     }
248 }