1 /* 2 * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package jdk.incubator.code.tools.renderer; 27 28 import java.io.*; 29 import java.util.ArrayList; 30 import java.util.List; 31 import java.util.regex.Matcher; 32 import java.util.regex.Pattern; 33 34 /** 35 * Created by gfrost 36 */ 37 public class ProcessRunner { 38 39 static public ProcessRunner run(String prog) { 40 return new ProcessRunner(prog); 41 } 42 43 static public ProcessRunner run(File file) { 44 return new ProcessRunner(file); 45 } 46 47 List<String> args = new ArrayList<>(); 48 49 @SuppressWarnings("this-escape") 50 public ProcessRunner(String prog) { 51 opt(prog); 52 } 53 54 @SuppressWarnings("this-escape") 55 public ProcessRunner(File prog) { 56 file(prog); 57 } 58 59 public ProcessRunner opt(String... argsToAdd) { 60 for (String s : argsToAdd) { 61 args.add(s); 62 } 63 return this; 64 } 65 66 public ProcessRunner fileOpt(String opt, File file) { 67 return opt(opt).file(file); 68 } 69 70 public ProcessRunner dirOpt(String opt, File dir) { 71 dir.mkdir(); 72 return fileOpt(opt, dir); 73 } 74 75 public ProcessRunner file(File file) { 76 opt(file.getAbsolutePath()); 77 return this; 78 } 79 80 public ProcessRunner files(File[] files) { 81 for (File f : files) { 82 file(f); 83 } 84 return this; 85 } 86 87 public void files(List<File> rsFiles) { 88 files(rsFiles.toArray(new File[0])); 89 } 90 91 public static class Result { 92 public Result() { 93 } 94 95 public void scan(Pattern pattern, Scanner scanner) { 96 for (List<String> list : streams) { //stdout then stderr 97 for (String text : list) { 98 Matcher matcher; 99 if ((matcher = pattern.matcher(text)).matches()) { 100 scanner.process(matcher); 101 } 102 } 103 } 104 } 105 106 public interface Scanner { 107 void process(Matcher m); 108 } 109 110 public int status = -1; 111 public boolean ok = false; 112 public String commandLine = ""; 113 114 public List<String> stdout = new ArrayList<>(); 115 public List<String> stderr = new ArrayList<>(); 116 public List<List<String>> streams = List.of(stdout, stderr); 117 } 118 119 120 public Result go(boolean verbose) { 121 Result result = new Result(); 122 123 StringBuilder commandBuilder = new StringBuilder(); 124 125 for (String arg : args) { 126 commandBuilder.append(arg + " "); 127 if (verbose) { 128 System.out.print(arg + " "); 129 } 130 } 131 132 result.commandLine = commandBuilder.toString(); 133 ProcessBuilder processBuilder = new ProcessBuilder(args); 134 try { 135 Process process = processBuilder.start(); 136 Thread stdout = new StreamReader("OUT", process.getErrorStream(), result.stdout, verbose).thread; 137 Thread stderr = new StreamReader("ERR", process.getInputStream(), result.stderr, verbose).thread; 138 result.status = process.waitFor(); 139 stdout.join(); 140 stderr.join(); 141 result.ok = result.status == 0; 142 } catch (IOException | InterruptedException e) { 143 e.printStackTrace(); 144 } 145 return result; 146 } 147 148 public ProcessRunner temp(String prefix, String suffix, String text) { 149 try { 150 File tempFile = File.createTempFile(prefix, suffix); 151 FileWriter tempDotFileWriter = new FileWriter(tempFile); 152 tempDotFileWriter.append(text); 153 tempDotFileWriter.close(); 154 file(tempFile); 155 } catch (IOException e) { 156 e.printStackTrace(); 157 } 158 return this; 159 } 160 161 162 static class StreamReader { 163 Thread thread; 164 165 StreamReader(final String prefix, InputStream is, final List<String> out, final boolean verbose) { 166 final BufferedReader br = new BufferedReader(new InputStreamReader(is)); 167 thread = new Thread(() -> { 168 try { 169 for (String string = br.readLine(); string != null; string = br.readLine()) { 170 if (verbose) { 171 System.out.println(prefix + ":" + string); 172 } 173 out.add(string); 174 } 175 br.close(); 176 } catch (Exception e) { 177 e.printStackTrace(); 178 } 179 }); 180 thread.start(); 181 182 } 183 184 } 185 186 }