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 * Opposite to {@link #isClosed()}.
45 */
46 protected boolean canContinue()
47 {
48 return !isClosed();
49 }
50
51 /**
52 * Possibly waiting for next command (see {@link #nextCommand()}) unless the stream is atomically
53 * closed (see {@link #isClosed()} returns {@code true}) before this method has returned.
54 */
55 protected void beforeNextCommand()
56 throws IOException
57 {
58 }
59
60 protected abstract Command nextCommand();
61
62 /**
63 * Returns quietly and immediately.
64 */
65 protected final void invalidateInternalBuffer()
66 {
67 currentBuffer = null;
68 currentPos = 0;
69 }
70
71 protected final MasterProcessCommand getLastCommand()
72 {
73 return lastCommand;
74 }
75
76 /**
77 * Used by single thread in StreamFeeder class.
78 *
79 * @return {@inheritDoc}
80 * @throws IOException {@inheritDoc}
81 */
82 @SuppressWarnings( "checkstyle:magicnumber" )
83 @Override
84 public int read()
85 throws IOException
86 {
87 if ( isClosed() )
88 {
89 return -1;
90 }
91
92 byte[] buffer = currentBuffer;
93 if ( buffer == null )
94 {
95 tryFlush();
96
97 if ( !canContinue() )
98 {
99 close();
100 return -1;
101 }
102
103 beforeNextCommand();
104
105 if ( isClosed() )
106 {
107 return -1;
108 }
109
110 Command cmd = nextCommand();
111 lastCommand = cmd.getCommandType();
112 buffer = lastCommand.hasDataType() ? lastCommand.encode( cmd.getData() ) : lastCommand.encode();
113 }
114
115 int b = buffer[currentPos++] & 0xff;
116 if ( currentPos == buffer.length )
117 {
118 buffer = null;
119 currentPos = 0;
120 }
121 currentBuffer = buffer;
122 return b;
123 }
124 }