11package com .github .stickerifier .stickerify .process ;
22
33import static java .nio .charset .StandardCharsets .UTF_8 ;
4- import static java .util .concurrent .TimeUnit .MINUTES ;
54
65import com .github .stickerifier .stickerify .exception .ProcessException ;
76
87import java .io .IOException ;
9- import java .io .InputStream ;
8+ import java .util .LinkedList ;
9+ import java .util .List ;
1010import java .util .concurrent .Semaphore ;
1111
1212public final class ProcessHelper {
@@ -21,65 +21,40 @@ public final class ProcessHelper {
2121 * on Windows they will be at most 4, on every other system they will be at most 5.
2222 *
2323 * @param command the command to be executed
24- * @return the output of the command
24+ * @return the output of the command, split by lines
2525 * @throws ProcessException either if:
2626 * <ul>
2727 * <li>the command was unsuccessful
28- * <li>the waiting time elapsed
2928 * <li>an unexpected failure happened running the command
29+ * <li>an unexpected failure happened reading the output
3030 * </ul>
31+ * @throws InterruptedException if the current thread is interrupted while waiting for the command to finish execution
3132 */
32- public static String executeCommand (final String [] command ) throws ProcessException {
33- Process process = null ;
34-
33+ public static List <String > executeCommand (final String [] command ) throws ProcessException , InterruptedException {
3534 try {
3635 SEMAPHORE .acquire ();
37- process = new ProcessBuilder (command ).start ();
38- var processExited = process .waitFor (1 , MINUTES );
36+ var process = new ProcessBuilder (command ).redirectErrorStream (true ).start ();
3937
40- if (!processExited || process .exitValue () != 0 ) {
41- var reason = processExited ? "successfully" : "in time" ;
42- var output = readStream (process .getErrorStream ());
43- throw new ProcessException ("The command {} couldn't complete {}\n {}" , command [0 ], reason , output );
38+ var output = new LinkedList <String >();
39+ try (var reader = process .inputReader (UTF_8 )) {
40+ reader .lines ().forEach (output ::add );
4441 }
4542
46- return readProcessOutput (process );
47- } catch (IOException | InterruptedException e ) {
43+ var exitCode = process .waitFor ();
44+ if (exitCode != 0 ) {
45+ process .destroy ();
46+ var lines = String .join ("\n " , output );
47+ throw new ProcessException ("The command {} exited with code {}\n {}" , command [0 ], exitCode , lines );
48+ }
49+
50+ return output ;
51+ } catch (IOException e ) {
4852 throw new ProcessException (e );
4953 } finally {
5054 SEMAPHORE .release ();
51- if (process != null ) {
52- process .destroy ();
53- }
5455 }
5556 }
5657
57- /**
58- * Processes the content of the stream and retrieves its UTF-8 string representation.
59- *
60- * @param stream the stream to be decoded
61- * @return the UTF-8 representation of passed-in stream
62- * @throws IOException if an error occurs reading stream's bytes
63- */
64- private static String readStream (InputStream stream ) throws IOException {
65- return new String (stream .readAllBytes (), UTF_8 );
66- }
67-
68- /**
69- * Reads the content of the input stream.
70- * If the input stream is empty, the content of the error stream is returned.
71- *
72- * @param process the process
73- * @return the output of the process
74- * @throws IOException if an error occurs reading stream's bytes
75- */
76- private static String readProcessOutput (Process process ) throws IOException {
77- var inputStream = readStream (process .getInputStream ());
78- var output = inputStream .isEmpty () ? readStream (process .getErrorStream ()) : inputStream ;
79-
80- return output .trim ();
81- }
82-
8358 private ProcessHelper () {
8459 throw new UnsupportedOperationException ();
8560 }
0 commit comments