001package io.ebean.docker.commands.process; 002 003import io.ebean.docker.commands.CommandException; 004import org.slf4j.Logger; 005import org.slf4j.LoggerFactory; 006 007import java.io.BufferedReader; 008import java.io.IOException; 009import java.io.InputStreamReader; 010import java.util.ArrayList; 011import java.util.List; 012 013/** 014 * Handle the external process response (exit code, std out, std err). 015 */ 016public class ProcessHandler { 017 018 private static final Logger log = LoggerFactory.getLogger(ProcessHandler.class); 019 020 private final ProcessBuilder builder; 021 022 private Process process; 023 024 /** 025 * Both stdErr and stdOut merged. 026 */ 027 private List<String> out = new ArrayList<>(); 028 029 private String match; 030 private String clearMatch; 031 032 033 private ProcessHandler(ProcessBuilder builder, String match, String clearMatch) { 034 this.builder = builder; 035 this.match = match; 036 this.clearMatch = clearMatch; 037 } 038 039 public static ProcessResult matchCommand(String match, String clearMatch, String... command) { 040 return process(new ProcessBuilder(command), match, clearMatch); 041 } 042 043 /** 044 * Process a basic command. 045 */ 046 public static ProcessResult command(String... command) { 047 return process(new ProcessBuilder(command)); 048 } 049 050 public static ProcessResult command(List<String> commands) { 051 return process(new ProcessBuilder(commands)); 052 } 053 054 public static ProcessResult process(ProcessBuilder pb) { 055 return process(pb, null, null); 056 } 057 058 /** 059 * Process a command. 060 */ 061 private static ProcessResult process(ProcessBuilder pb, String match, String clearMatch) { 062 try { 063 ProcessHandler handler = new ProcessHandler(pb, match, clearMatch); 064 handler.start(); 065 ProcessResult result = handler.read(); 066 if (!result.success()) { 067 throw new CommandException("command failed: " + result.getOutLines(), result); 068 } 069 return result; 070 071 } catch (IOException e) { 072 throw new RuntimeException(e); 073 } 074 } 075 076 private void start() throws IOException { 077 // merge input and error streams 078 builder.redirectErrorStream(true); 079 process = builder.start(); 080 } 081 082 private ProcessResult read() { 083 084 try { 085 BufferedReader stdInput = new BufferedReader(new InputStreamReader(process.getInputStream())); 086 String s; 087 while ((s = stdInput.readLine()) != null) { 088 processLine(s, out); 089 } 090 091 int result = process.waitFor(); 092 ProcessResult pr = new ProcessResult(result, out); 093 if (!pr.success() && log.isTraceEnabled()) { 094 log.trace(pr.debug()); 095 } 096 return pr; 097 098 } catch (Exception e) { 099 throw new RuntimeException(e); 100 } 101 } 102 103 private void processLine(String lineContent, List<String> lines) { 104 if (clearMatch != null && lineContent.contains(clearMatch)) { 105 out.clear(); 106 } else { 107 if (match != null) { 108 if (lineContent.contains(match)) { 109 out.add(lineContent); 110 } 111 } else { 112 lines.add(lineContent); 113 } 114 } 115 } 116 117}