View Javadoc
1   package org.apache.maven.plugin.surefire.extensions;
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.plugin.surefire.log.api.ConsoleLogger;
23  import org.apache.maven.surefire.api.booter.Command;
24  import org.apache.maven.surefire.extensions.CloseableDaemonThread;
25  import org.apache.maven.surefire.extensions.CommandReader;
26  import org.apache.maven.surefire.stream.CommandEncoder;
27  
28  import javax.annotation.Nonnull;
29  import java.io.IOException;
30  import java.nio.channels.ClosedChannelException;
31  import java.nio.channels.NonWritableChannelException;
32  import java.nio.channels.WritableByteChannel;
33  
34  /**
35   * Commands which are sent from plugin to the forked jvm.
36   * <br>
37   *     <br>
38   * magic number : opcode [: opcode specific data]*
39   * <br>
40   *     or data encoded with Base64
41   * <br>
42   * magic number : opcode [: Base64(opcode specific data)]*
43   *
44   * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
45   * @since 3.0.0-M5
46   */
47  public class StreamFeeder extends CloseableDaemonThread
48  {
49      private final WritableByteChannel channel;
50      private final CommandReader commandReader;
51      private final ConsoleLogger logger;
52  
53      private volatile boolean disabled;
54      private volatile Throwable exception;
55  
56      public StreamFeeder( @Nonnull String threadName, @Nonnull WritableByteChannel channel,
57                           @Nonnull CommandReader commandReader, @Nonnull ConsoleLogger logger )
58      {
59          super( threadName );
60          this.channel = channel;
61          this.commandReader = commandReader;
62          this.logger = logger;
63      }
64  
65      @Override
66      @SuppressWarnings( "checkstyle:innerassignment" )
67      public void run()
68      {
69          try ( CommandEncoder encoder = new CommandEncoder( channel ) )
70          {
71              for ( Command cmd; ( cmd = commandReader.readNextCommand() ) != null; )
72              {
73                  if ( !disabled )
74                  {
75                      switch ( cmd.getCommandType() )
76                      {
77                          case RUN_CLASS:
78                              encoder.sendRunClass( cmd.getData() );
79                              break;
80                          case TEST_SET_FINISHED:
81                              encoder.sendTestSetFinished();
82                              break;
83                          case SKIP_SINCE_NEXT_TEST:
84                              encoder.sendSkipSinceNextTest();
85                              break;
86                          case SHUTDOWN:
87                              encoder.sendShutdown( cmd.getData() );
88                              break;
89                          case NOOP:
90                              encoder.sendNoop();
91                              break;
92                          case BYE_ACK:
93                              encoder.sendByeAck();
94                              break;
95                          default:
96                              logger.error( "Unknown enum " + cmd.getCommandType().name() );
97                      }
98                  }
99              }
100         }
101         catch ( ClosedChannelException e )
102         {
103             // closed externally
104         }
105         catch ( IOException | NonWritableChannelException e )
106         {
107             exception = e.getCause() == null ? e : e.getCause();
108         }
109         catch ( IllegalArgumentException e )
110         {
111             logger.error( e.getLocalizedMessage() );
112         }
113     }
114 
115     public void disable()
116     {
117         disabled = true;
118     }
119 
120     public Throwable getException()
121     {
122         return exception;
123     }
124 
125     @Override
126     public void close() throws IOException
127     {
128         channel.close();
129     }
130 }