1 package org.apache.maven.plugin.surefire.booterclient.lazytestprovider;
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.booter.Command;
23 import org.apache.maven.surefire.booter.MasterProcessCommand;
24
25 import java.io.IOException;
26
27 /**
28 * Reader stream sends commands to forked jvm std-{@link java.io.InputStream input-stream}.
29 *
30 * @author <a href="mailto:tibordigana@apache.org">Tibor Digana (tibor17)</a>
31 * @since 2.19
32 * @see org.apache.maven.surefire.booter.Command
33 */
34 public abstract class AbstractCommandStream
35 extends AbstractForkInputStream
36 {
37 private byte[] currentBuffer;
38 private int currentPos;
39 private volatile MasterProcessCommand lastCommand;
40
41 protected abstract boolean isClosed();
42
43 /**
44 * Unnecessarily opposite to {@link #isClosed()} however may respect
45 * {@link #getLastCommand() last command} and {@link #isClosed()}.
46 */
47 protected abstract boolean canContinue();
48
49 /**
50 * Possibly waiting for next command (see {@link #nextCommand()}) unless the stream is atomically
51 * closed (see {@link #isClosed()} returns {@code true}) before this method has returned.
52 */
53 protected void beforeNextCommand()
54 throws IOException
55 {
56 }
57
58 protected abstract Command nextCommand();
59
60 /**
61 * Returns quietly and immediately.
62 */
63 protected final void invalidateInternalBuffer()
64 {
65 currentBuffer = null;
66 currentPos = 0;
67 }
68
69 protected final MasterProcessCommand getLastCommand()
70 {
71 return lastCommand;
72 }
73
74 /**
75 * Used by single thread in StreamFeeder class.
76 *
77 * @return {@inheritDoc}
78 * @throws IOException {@inheritDoc}
79 */
80 @SuppressWarnings( "checkstyle:magicnumber" )
81 @Override
82 public int read()
83 throws IOException
84 {
85 if ( isClosed() )
86 {
87 return -1;
88 }
89
90 byte[] buffer = currentBuffer;
91 if ( buffer == null )
92 {
93 tryFlush();
94
95 if ( !canContinue() )
96 {
97 close();
98 return -1;
99 }
100
101 beforeNextCommand();
102
103 if ( isClosed() )
104 {
105 return -1;
106 }
107
108 Command cmd = nextCommand();
109 lastCommand = cmd.getCommandType();
110 buffer = lastCommand.hasDataType() ? lastCommand.encode( cmd.getData() ) : lastCommand.encode();
111 }
112
113 int b = buffer[currentPos++] & 0xff;
114 if ( currentPos == buffer.length )
115 {
116 buffer = null;
117 currentPos = 0;
118 }
119 currentBuffer = buffer;
120 return b;
121 }
122 }