11/*
2- Copyright 2017 The Kubernetes Authors.
2+ Copyright 2017, 2018 The Kubernetes Authors.
33Licensed under the Apache License, Version 2.0 (the "License");
44you may not use this file except in compliance with the License.
55You may obtain a copy of the License at
1818import java .io .IOException ;
1919import java .io .InputStream ;
2020import java .io .OutputStream ;
21+ import java .util .HashMap ;
22+ import java .util .Map ;
2123import java .util .concurrent .TimeUnit ;
2224import org .apache .commons .lang3 .StringUtils ;
25+ import org .slf4j .Logger ;
26+ import org .slf4j .LoggerFactory ;
2327
2428public class Exec {
29+ private static final Logger log = LoggerFactory .getLogger (Exec .class );
30+
2531 private ApiClient apiClient ;
2632
2733 /** Simple Exec API constructor, uses default configuration */
@@ -178,10 +184,34 @@ public Process exec(
178184 return exec ;
179185 }
180186
187+ static int parseExitCode (InputStream inputStream ) {
188+ int exitCode = 0 ;
189+ try {
190+ int available = inputStream .available ();
191+ if (available > 0 ) {
192+ byte [] b = new byte [available ];
193+ inputStream .read (b );
194+ String result = new String (b , "UTF-8" );
195+ int idx = result .lastIndexOf (':' );
196+ if (idx > 0 ) {
197+ try {
198+ exitCode = Integer .parseInt (result .substring (idx + 1 ).trim ());
199+ } catch (NumberFormatException nfe ) {
200+ log .error ("Error parsing exit code from status channel response" , nfe );
201+ }
202+ }
203+ }
204+ } catch (IOException io ) {
205+ log .error ("Error parsing exit code from status channel response" , io );
206+ }
207+
208+ return exitCode ;
209+ }
210+
181211 private static class ExecProcess extends Process {
182212 private final WebSocketStreamHandler streamHandler ;
183213 private volatile int statusCode ;
184- private volatile boolean isDestroyed = false ;
214+ private final Map < Integer , InputStream > input = new HashMap <>() ;
185215
186216 public ExecProcess () throws IOException {
187217 this .statusCode = -1 ;
@@ -190,25 +220,7 @@ public ExecProcess() throws IOException {
190220 @ Override
191221 public void close () {
192222 if (statusCode == -1 ) {
193- InputStream inputStream = getInputStream (3 );
194- int exitCode = 0 ;
195- try {
196- int available = inputStream .available ();
197- if (available > 0 ) {
198- byte [] b = new byte [available ];
199- inputStream .read (b );
200- String result = new String (b , "UTF-8" );
201- int idx = result .lastIndexOf (':' );
202- if (idx > 0 ) {
203- try {
204- exitCode = Integer .parseInt (result .substring (idx + 1 ).trim ());
205- } catch (NumberFormatException nfe ) {
206- // no-op
207- }
208- }
209- }
210- } catch (IOException e ) {
211- }
223+ int exitCode = parseExitCode (ExecProcess .this .getInputStream (3 ));
212224
213225 // notify of process completion
214226 synchronized (ExecProcess .this ) {
@@ -217,7 +229,7 @@ public void close() {
217229 }
218230 }
219231
220- if ( isDestroyed ) super .close ();
232+ super .close ();
221233 }
222234 };
223235 }
@@ -233,12 +245,19 @@ public OutputStream getOutputStream() {
233245
234246 @ Override
235247 public InputStream getInputStream () {
236- return streamHandler . getInputStream (1 );
248+ return getInputStream (1 );
237249 }
238250
239251 @ Override
240252 public InputStream getErrorStream () {
241- return streamHandler .getInputStream (2 );
253+ return getInputStream (2 );
254+ }
255+
256+ private synchronized InputStream getInputStream (int stream ) {
257+ if (!input .containsKey (stream )) {
258+ input .put (stream , streamHandler .getInputStream (stream ));
259+ }
260+ return input .get (stream );
242261 }
243262
244263 @ Override
@@ -265,8 +284,14 @@ public int exitValue() {
265284
266285 @ Override
267286 public void destroy () {
268- isDestroyed = true ;
269287 streamHandler .close ();
288+ for (InputStream in : input .values ()) {
289+ try {
290+ in .close ();
291+ } catch (IOException ex ) {
292+ log .error ("Error on close" , ex );
293+ }
294+ }
270295 }
271296 }
272297}
0 commit comments